-
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 all 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,49 @@ | ||
| name: Main CD for Ephememeral Devnet Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| branch: | ||
| required: true | ||
| type: string | ||
| genesis_hash: | ||
| required: true | ||
| type: string | ||
| 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" | ||
| 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 | ||
| branch: ${{ github.event.inputs.branch }} | ||
| genesis_hash: ${{ github.event.inputs.genesis_hash }} | ||
| instance: ec2 | ||
| resource: network | ||
| tf_workspace_name: ephemeral-devnet | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| run_apply: ${{ github.event.inputs.run_apply }} | ||
| run_destroy: ${{ github.event.inputs.run_destroy }} | ||
| secrets: | ||
| TRANSCRYPT: ${{ secrets.TRANSCRYPT }} | ||
| TF_API_TOKEN: ${{ secrets.TF_API_TOKEN }} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| name: Main CD for Ephememeral Devnet Deployment | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| branch: | ||
| required: true | ||
| type: string | ||
| genesis_hash: | ||
| required: true | ||
| type: string | ||
| 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" | ||
| 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 | ||
| branch: ${{ github.event.inputs.branch }} | ||
| genesis_hash: ${{ github.event.inputs.genesis_hash }} | ||
| instance: hetzner | ||
| resource: network | ||
| tf_workspace_name: ephemeral-devnet-hetzner | ||
| tf_version: 1.5.7 | ||
| tf_organization: subspace | ||
| run_apply: ${{ github.event.inputs.run_apply }} | ||
| run_destroy: ${{ github.event.inputs.run_destroy }} | ||
| 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-3g/**" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| deploy: | ||
| uses: ./.github/workflows/terraform_template_deploy.yml | ||
| with: | ||
| project: aws | ||
| resource: gemini-3g | ||
| tf_workspace_name: gemini-3g | ||
| 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/dedicated/**" | ||
|
|
||
| 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,42 @@ jobs: | |
| - name: Set up Terraform | ||
| uses: hashicorp/setup-terraform@v1 | ||
| with: | ||
| terraform_version: "1.4.2" | ||
| cli_config_credentials_token: ${{ secrets.TF_CLOUD_TOKEN }} | ||
| terraform_version: "1.5.7" | ||
| cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} | ||
|
|
||
| - name: Install dependencies | ||
| - name: Decrypt the secrets | ||
| run: | | ||
| # Install any dependencies required by your Terraform code | ||
| bash scripts/transcrypt -c aes-256-cbc -p ${{ secrets.TRANSCRYPT }} -y | ||
|
|
||
| - name: Run Bash Script | ||
| id: generate_runner_token | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| # GitHub repository and access token | ||
| repo="subspace/infra" | ||
| token=${{ secrets.PAT_TOKEN }} | ||
|
|
||
| # API endpoint | ||
| url="https://api.github.com/repos/$repo/actions/runners/registration-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
|
||
|
|
||
| # Send POST request to get the registration token | ||
| response=$(curl -X POST -H "Authorization: token $token" -s "$url") | ||
| # API endpoint | ||
| url="https://api.github.com/repos/$repo/actions/runners/registration-token" | ||
|
|
||
| # Extract the token value from the response | ||
| runner_token=$(echo "$response" | jq -r '.token') | ||
| # Send POST request to get the registration token | ||
| response=$(curl -X POST -H "Authorization: token $token" -s "$url") | ||
|
|
||
| # Export the token as an environment variable | ||
| echo "export RUNNER_TOKEN=$runner_token" >> $GITHUB_ENV | ||
| # Extract the token value from the response | ||
| runner_token=$(echo "$response" | jq -r '.token') | ||
|
|
||
| # Set the runner token as an environment variable | ||
| export RUNNER_TOKEN="$runner_token" | ||
| # Mask the runner token in the logs | ||
| echo "::add-mask::$runner_token" | ||
|
|
||
| # Store the token as a secret in GitHub Actions | ||
| gh secret set RUNNER_TOKEN -r "$repo" -b "$runner_token" | ||
| # Pass the runner token in GitHub Actions for use | ||
| # in subsequent steps with terraform for runner registration | ||
| echo "::set-output name=runner_token::$runner_token" | ||
|
|
||
| - name: Run Terraform | ||
| working-directory: ./github-runners/terraform/base | ||
| working-directory: ./github-runners/terraform/dedicated | ||
| 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 | ||
| terraform plan -var-file=terraform.tfvars | ||
| terraform apply -auto-approve -var "gh_token=${{ steps.generate_runner_token.outputs.runner_token }}" -var-file=terraform.tfvars | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| 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: 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: | | ||
| terraform init | ||
|
|
||
| - name: Terraform Validate | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: terraform validate | ||
|
|
||
| - name: Terraform Plan for ${{ inputs.project }}/${{ inputs.resource }} | ||
| if: ${{ (inputs.run_destroy == 'no') }} | ||
| working-directory: ${{ inputs.project }}/${{ inputs.resource }} | ||
| run: | | ||
| terraform plan -var-file=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=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=terraform.tfvars | ||
| terraform destroy -auto-approve -var-file=terraform.tfvars |
Uh oh!
There was an error while loading. Please reload this page.