-
Notifications
You must be signed in to change notification settings - Fork 4
Add CI/CD workflows for terraform automation #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
55c06e4
99a5ac2
4a6c180
546685a
2d35eef
2fe0c94
d865c7c
174064d
6ea4586
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: Main CD for Devnet Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| push: | ||
| branches: | ||
| - "!main" | ||
| paths: | ||
| - "aws/devnet/**" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| deploy: | ||
| uses: ./.github/workflows/terraform_template_deploy.yml | ||
| with: | ||
| project: aws | ||
| resource: devnet | ||
| tf_workspace_name: devnet-aws | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| secrets: | ||
| TRANSCRYPT: ${{ secrets.TRANSCRYPT }} | ||
| TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| name: Main CD for Ephememeral Devnet Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| push: | ||
| branches: | ||
| - "!main" | ||
| paths: | ||
| - "testing-framework/ec2/network/**" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| deploy: | ||
| uses: ./.github/workflows/terraform_template_ephemeral_deploy.yml | ||
| with: | ||
| project: testing-framework | ||
| instance: ec2 | ||
| resource: network | ||
| tf_workspace_name: ephemeral-devnet | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| secrets: | ||
| TRANSCRYPT: ${{ secrets.TRANSCRYPT }} | ||
| TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| name: Main CD for Ephememeral Devnet Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| push: | ||
| branches: | ||
| - "!main" | ||
| paths: | ||
| - "testing-framework/hetzner/network/**" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| deploy: | ||
| uses: ./.github/workflows/terraform_template_ephemeral_deploy.yml | ||
| with: | ||
| project: testing-framework | ||
| instance: hetzner | ||
| resource: network | ||
| tf_workspace_name: ephemeral-devnet-hetzner | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| secrets: | ||
| TRANSCRYPT: ${{ secrets.TRANSCRYPT }} | ||
| TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: Main CD for Gemini Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| push: | ||
| branches: | ||
| - "!main" | ||
| paths: | ||
| - "aws/gemini-3f/**" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| deploy: | ||
| uses: ./.github/workflows/terraform_template_deploy.yml | ||
| with: | ||
| project: aws | ||
| resource: gemini-3f | ||
| tf_workspace_name: gemini-3f | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| secrets: | ||
| TRANSCRYPT: ${{ secrets.TRANSCRYPT }} | ||
| TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,18 @@ | ||
| name: Terraform Workflow | ||
| name: Terraform GH Runner Deployment | ||
|
|
||
| on: | ||
| push: | ||
| workflow_dispatch: | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| paths: | ||
| - './github-runners/terraform/base/**' | ||
| workflow_dispatch: | ||
| - "github-runners/terraform/base/**" | ||
|
|
||
| jobs: | ||
| terraform_gh_runner: | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
Comment on lines
+14
to
+15
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't seem to be used, why setting?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The env variable needs to be set when calling github api, otherwise an error is thrown.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What and where calls those APIs? I don't see any usage of it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The GITHUB_TOKEN is needed in CI or bash cli for API calls. The API is called with curl via https://github.com/subspace/infra/pull/183/files/99a5ac25712fdda531fd88026a12f96aafeacb83#diff-b46b68b6df852ad5f8fc96162f55c2fe198f6d53eb2fe7d7ce12fcd4b2650ba6R39-R43
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What you linked doesn't use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nazar-pc removed it, here you go:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, so it is not for With that knowledge we understand why it is necessary. I think what we should do now in a secure way without using heavy tools like setting repo (I'm fairly certain simply setting environment variable wasn't) without using heavy tools like setting repo's secrets from workflow is to use outputs and mask them such that they are not visible in logs: https://github.com/orgs/community/discussions/25225#discussioncomment-3246942 That is the goal here: to pass the token from one step into another. What we had in earlier versions of this PR are various suboptimal/incorrect ways of achieving that ultimate goal.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct, github cli, I should have been more clear about that "The GITHUB_TOKEN is needed in CI or bash cli for API calls" but couldn't remember exactly since it was a while ago. That being said the solution of masking the secret and just passing it is nice if using the ephemeral runners maybe but this solution and workflow is for the dedicated runners, where i need to retain the secret so I can unregister and delete runner if need be and remove it from github. See https://docs.github.com/en/free-pro-team@latest/rest/actions/self-hosted-runners?apiVersion=2022-11-28#delete-a-self-hosted-runner-from-an-organization
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you mentioned that tokens only live for 1 hour, so you'll have to retrieve fresh token anyway. Why retaining it then at all?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The token is not needed to deregister, a force delete can be done. So i've used the masking technique. |
||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
|
|
@@ -19,40 +21,43 @@ jobs: | |
| - name: Set up Terraform | ||
| uses: hashicorp/setup-terraform@v1 | ||
| with: | ||
| terraform_version: "1.4.2" | ||
| terraform_version: "1.5.7" | ||
| cli_config_credentials_token: ${{ secrets.TF_CLOUD_TOKEN }} | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| # Install any dependencies required by your Terraform code | ||
|
|
||
| - name: Run Bash Script | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # GitHub repository and access token | ||
| repo="subspace/infra" | ||
| token=${{ secrets.PAT_TOKEN }} | ||
| # GitHub repository and access token for github api calls, since GITHUB_TOKEN can't | ||
| # be used for this purpose. | ||
| repo="subspace/infra" | ||
| token=${{ secrets.PAT_TOKEN }} | ||
nazar-pc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # API endpoint | ||
| url="https://api.github.com/repos/$repo/actions/runners/registration-token" | ||
| # API endpoint | ||
| url="https://api.github.com/repos/$repo/actions/runners/registration-token" | ||
|
|
||
| # Send POST request to get the registration token | ||
| response=$(curl -X POST -H "Authorization: token $token" -s "$url") | ||
| # Send POST request to get the registration token | ||
| response=$(curl -X POST -H "Authorization: token $token" -s "$url") | ||
|
|
||
| # Extract the token value from the response | ||
| runner_token=$(echo "$response" | jq -r '.token') | ||
| # Extract the token value from the response | ||
| runner_token=$(echo "$response" | jq -r '.token') | ||
|
|
||
| # Export the token as an environment variable | ||
| echo "export RUNNER_TOKEN=$runner_token" >> $GITHUB_ENV | ||
| # Store the token as a secret in GitHub Actions for use | ||
| # in subsequent steps with terraform for runner registration | ||
| gh secret set RUNNER_TOKEN -r "$repo" -b "$runner_token" | ||
|
|
||
| # Set the runner token as an environment variable | ||
| export RUNNER_TOKEN="$runner_token" | ||
|
|
||
| # Store the token as a secret in GitHub Actions | ||
| gh secret set RUNNER_TOKEN -r "$repo" -b "$runner_token" | ||
| - name: Fetch and write terraform.tfvars | ||
| run: | | ||
| echo ${{ secrets.TF_VARS_FILE }} > /tmp/terraform.tfvars | ||
| chmod 600 /tmp/terraform.tfvars | ||
|
|
||
| - name: Run Terraform | ||
| working-directory: ./github-runners/terraform/base | ||
| run: | | ||
| terraform init-backend-config="organization=${{ secrets.ORGANIZATION_NAME }}" -backend-config="workspaces=${{ secrets.WORKSPACE_NAME }}" | ||
| terraform plan -var-file=${{ secrets.VAR_FILE }} | ||
| terraform apply -auto-approve -var "gh_token=${{ secrets.RUNNER_TOKEN }}" | ||
| terraform init-backend-config="organization=subspace" -backend-config="workspaces=${{ secrets.WORKSPACE_NAME }}" | ||
| terraform plan -var-file=/tmp/terraform.tfvars | ||
| terraform apply -auto-approve -var "gh_token=${{ secrets.RUNNER_TOKEN }}" -var-file=/tmp/terraform.tfvars | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| name: Template Deploy | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| project: | ||
| required: true | ||
| type: string | ||
| resource: | ||
| required: true | ||
| type: string | ||
| tf_workspace_name: | ||
| description: "Name of the workspace in terraform cloud" | ||
| required: false | ||
| type: string | ||
| tf_version: | ||
| description: "Version of the terraform" | ||
| required: true | ||
| type: string | ||
| tf_organization: | ||
| description: "Name of the TF organization" | ||
| default: "subspace" | ||
| type: string | ||
| required: true | ||
| run_apply: | ||
| description: "The code needs to be deployed or not" | ||
| type: string | ||
| default: "no" | ||
| run_destroy: | ||
| description: "The resources need to be destroyed or not" | ||
| type: string | ||
| default: "no" | ||
| secrets: | ||
| TRANSCRYPT: | ||
| required: true | ||
| TF_API_TOKEN: | ||
| required: false | ||
| env: | ||
| TF_CLOUD_ORGANIZATION: "${{ inputs.tf_organization }}" | ||
| TF_API_TOKEN: "${{ secrets.TF_API_TOKEN }}" | ||
| TF_VERSION: "${{ inputs.tf_version }}" | ||
|
|
||
| jobs: | ||
| template-deploy: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout the repo | ||
| uses: actions/checkout@v3 | ||
|
|
||
| - name: Decrypt the secrets | ||
| run: | | ||
| bash scripts/transcrypt -c aes-256-cbc -p ${{ secrets.TRANSCRYPT }} -y | ||
|
|
||
| - uses: hashicorp/setup-terraform@v2 | ||
| with: | ||
| terraform_version: ${{ env.TF_VERSION }} | ||
| terraform_wrapper: false | ||
| cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} | ||
|
|
||
| - name: Setup Remote Config Backend | ||
| run: | | ||
| cat > /tmp/config.remote.tfbackend <<EOF | ||
| workspaces { name = "${{ inputs.tf_workspace_name }}"} | ||
| hostname = "app.terraform.io" | ||
| organization = "${{ inputs.tf_organization }}" | ||
| EOF | ||
|
|
||
| - name: Terraform fmt | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: terraform fmt -check | ||
| continue-on-error: true | ||
|
|
||
| - name: Terraform Init for ${{ inputs.project }}/${{ inputs.resource }} | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: | | ||
| cat /tmp/config.remote.tfbackend | ||
| terraform init -backend-config=/tmp/config.remote.tfbackend | ||
|
|
||
| - name: Terraform Validate | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: terraform validate | ||
|
|
||
| - name: Fetch and write terraform.tfvars | ||
| run: | | ||
| echo ${{ secrets.TF_VARS_FILE }} > /tmp/terraform.tfvars | ||
| chmod 600 /tmp/terraform.tfvars | ||
|
|
||
| - name: Terraform Plan for ${{ inputs.project }}/${{ inputs.resource }} | ||
| if: ${{ (inputs.run_destroy == 'no') }} | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: | | ||
| terraform plan -var-file=/tmp/terraform.tfvars | ||
|
|
||
| - name: Terraform Apply for ${{ inputs.project }}/${{ inputs.resource }} | ||
| if: ${{ (inputs.run_apply == 'yes') && (inputs.run_destroy == 'no') }} | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: | | ||
| terraform apply -auto-approve -var-file=/tmp/terraform.tfvars | ||
|
|
||
| - name: Terraform Destroy for ${{ inputs.project }}/${{ inputs.resource }} | ||
| if: ${{ (inputs.run_destroy == 'yes') }} | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: | | ||
| terraform plan -destroy -var-file=/tmp/terraform.tfvars | ||
| terraform destroy -auto-approve -var-file=/tmp/terraform.tfvars |
Uh oh!
There was an error while loading. Please reload this page.