gramos
gramos

Reputation: 129

Clone github repository in specific directory with terraform

This week I started to learn terraform to make server deployments and the thing is I need to clone a git repository in a specific folder, but after hours of research I didn't find how. Can anyone help me?
Thanks in advance

Upvotes: 3

Views: 16438

Answers (5)

Dustin
Dustin

Reputation: 129

Here is a solution using only the GitHub and Local providers to make this happen, avoiding the use of a null_resource and provisioner:

terraform {
  required_providers {
    github = {
      source  = "integrations/github"
      version = "~> 6.0"

    }
  }
}

provider "github" {}

variable "branch_name" {
  default     = null
  description = "The name of the GitHub repository branch to use.  Defaults to the default branch."
  type        = string
}

variable "repository_name" {
  default     = "demo-repo"
  description = "The name of the GitHub repository to use."
  type        = string
}

data "github_repository" "repo" {
  name = var.repository_name
}

data "github_branch" "branch" {
  repository = data.github_repository.repo.name
  branch     = var.branch_name == null ? data.github_repository.repo.default_branch : var.branch_name
}

data "github_tree" "tree" {
  recursive  = true
  repository = data.github_repository.repo.name
  tree_sha   = data.github_branch.branch.sha
}

locals {
  tree_files = { for i in data.github_tree.tree.entries : i.sha => i }
}

data "github_repository_file" "file" {
  for_each = local.tree_files

  repository = data.github_repository.repo.name
  branch     = data.github_branch.branch.ref
  file       = each.value.path
}

locals {
  file_contents = {
    for k, v in data.github_repository_file.file : k => {
      content = v.content
      path    = local.tree_files[k].path
    } if local.tree_files[k].type == "blob" && !startswith(local.tree_files[k].path, ".")
  }
}

resource "local_file" "files" {
  for_each = local.file_contents

  filename = "${path.cwd}/${each.value.path}"
  content  = each.value.content
}

output "entries" {
  value = data.github_tree.tree.entries
}

output "files" {
  value = local.file_contents
}

For my use case, I simply want the normal repo contents, so no dotfiles:

### loop filter
} if local.tree_files[k].type == "blob" && !startswith(local.tree_files[k].path, ".")

Upvotes: 0

VonC
VonC

Reputation: 1326686

If your Git repository represents a terraform module, you could declare them as

module "vpc" {
  source = "git::https://example.com/vpc.git" 
}

module "storage" {
  source = "git::ssh://[email protected]/storage.git"
}

Arbitrary Git repositories can be used by prefixing the address with the special git:: prefix.
After this prefix, any valid Git URL can be specified to select one of the protocols supported by Git.


If it is not a module, then you would need to a resource

resource "github_repository" "example" {
  name        = "example"
  description = "My awesome codebase"

  private = true

  template {
    owner = "github"
    repository = "terraform-module-template"
  }
}

However, k'' mentions in the comments this is for creating a repository. It is not for cloning it. Same for github_repository, which only allows you to create and manage repositories within your GitHub organization or personal account.

Upvotes: 4

Başar Söker
Başar Söker

Reputation: 726

For a clearer version of the andybkay's answer:

#pull the code from github
resource "null_resource" "git_clone" {
  provisioner "local-exec" {
    command = "git clone [email protected]:useinsider/${var.git_repo}.git"
  }
}

And call this from CLI as follows:

terraform apply -var git_repo="<<your-repo-name>>"

Upvotes: 5

andybkay
andybkay

Reputation: 81

So this is a few years after the original ask, but this may be useful to anyone who may need it if they land here.

I've just had this issue, and the best solution is to use null_resource/local-exec.

resource "null_resource" "git_clone" {
  provisioner "local-exec" {
    command = "../scripts/get_repo.sh"
    interpreter = ["bash"]
  }
}

../scripts/get_repo.sh should contain the following:

git clone <insert repo here> /put/your/destination/here

While not the cleanest, it does perform the job required.

(Checked with terraform 0.13.3)

Upvotes: 4

jack_t
jack_t

Reputation: 163

Terraform Github provider does not direct support cloning repository but there is another way to retrieve data of the repository and clone it. I would rather call it a semi-declarative approach.

Create github_clone.tf with following snippet -

provider "github" {
  token        = var.gh_token
  organization = "test-tf"
  base_url = var.gh_base_url
  version = "~>v2.9"
}

data "github_repository" "dummy" {
  full_name = "test-tf/dummy-tf"
}

to retrieve your secrets, create another file vars.tf

variable gh_token {
    default = "YOUR-GH-TOKEN"
}

variable gh_base_url {
    default = "YOUR-GH-BASE-URL"
}

Once saved initialize terraform with -

terraform init

  • to download Github provider. Then run

terraform show -json | jq -r '.values.root_module.resources[0].values.http_clone_url'

It will return url to clone github repo.

Upvotes: 1

Related Questions