Repository navigation
Deprecate deploy_environment and lock tf_apply per Terraform state #177
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
base: main
Are you sure you want to change the base?
Changes from all commits
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,44 @@ | ||
| const { readWorkflow } = require('./workflow-test-helpers'); | ||
|
|
||
| const concurrency = workflowFile => { | ||
| const block = readWorkflow(workflowFile).match(/^concurrency:\n((?: {2}.*\n)+)/m); | ||
| if (!block) { | ||
| throw new Error(`No workflow-level concurrency block in ${workflowFile}`); | ||
| } | ||
| return block[1]; | ||
| }; | ||
|
|
||
| describe('Terraform apply concurrency', () => { | ||
| test('tf_apply locks one Terraform state: repository, environment, root, and workspace', () => { | ||
| const block = concurrency('tf_apply.yml'); | ||
|
|
||
| expect(block).toContain( | ||
| 'group: core-gha-tf-apply-${{ github.repository }}-${{ inputs.environment }}-${{ inputs.terraform-root }}-${{ inputs.terraform-workspace }}' | ||
| ); | ||
| expect(block).not.toContain('cancel-in-progress'); | ||
| }); | ||
|
|
||
| test('tf_apply waits for a state lock held by another run', () => { | ||
| expect(readWorkflow('tf_apply.yml')).toContain( | ||
| 'run: terraform apply -auto-approve -input=false -lock-timeout=5m' | ||
| ); | ||
| }); | ||
|
|
||
| test('deploy_thru_prod locks its roots and workspace and calls tf_apply directly', () => { | ||
| const workflow = readWorkflow('deploy_thru_prod.yml'); | ||
| const block = concurrency('deploy_thru_prod.yml'); | ||
|
|
||
| expect(block).toMatch(/group: core-gha-deploy-thru-prod-\$\{\{ github\.repository \}\}-/); | ||
| for (const input of [ | ||
| 'terraform-root-dev', | ||
| 'terraform-root-stage', | ||
| 'terraform-root-prod', | ||
| 'terraform-workspace', | ||
| ]) { | ||
| expect(block).toContain(`inputs.${input}`); | ||
| } | ||
| expect(block).not.toContain('cancel-in-progress'); | ||
| expect(workflow.match(/uses: \.\/\.github\/workflows\/tf_apply\.yml/g)).toHaveLength(3); | ||
| expect(workflow).not.toContain('deploy_environment.yml'); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,8 +37,10 @@ on: | |
| ORG_GITHUB_PACKAGES_READ_ONLY_TOKEN: | ||
| required: true | ||
|
|
||
|
|
||
| concurrency: ${{ github.repository }} | ||
| # One deployment chain at a time per set of Terraform states. A newer pending run replaces an older | ||
| # pending one, since the newer commit includes its changes. | ||
| concurrency: | ||
| group: core-gha-deploy-thru-prod-${{ github.repository }}-${{ inputs.terraform-root-dev || 'terraform/dev' }}-${{ inputs.terraform-root-stage || 'terraform/stage' }}-${{ inputs.terraform-root-prod || 'terraform/prod' }}-${{ inputs.terraform-workspace }} | ||
|
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. Serialize deployment chains that share any Terraform state. If two runs differ only in Retain repository-wide chain serialization unless the workflow can enforce that concurrently running chains have disjoint states.
|
||
|
|
||
| permissions: {} | ||
|
|
||
|
|
@@ -58,7 +60,7 @@ jobs: | |
| DeployDev: | ||
| name: Apply Dev | ||
| needs: [Set-Release-Tag] | ||
| uses: ./.github/workflows/deploy_environment.yml | ||
| uses: ./.github/workflows/tf_apply.yml | ||
| permissions: | ||
| id-token: write # Required to assume the Terraform apply role through OIDC. | ||
| contents: read # Required to check out the Terraform code. | ||
|
|
@@ -77,7 +79,7 @@ jobs: | |
| DeployStage: | ||
| name: Apply Stage | ||
| needs: [Set-Release-Tag, DeployDev] | ||
| uses: ./.github/workflows/deploy_environment.yml | ||
| uses: ./.github/workflows/tf_apply.yml | ||
| permissions: | ||
| id-token: write # Required to assume the Terraform apply role through OIDC. | ||
| contents: read # Required to check out the Terraform code. | ||
|
|
@@ -96,7 +98,7 @@ jobs: | |
| DeployProd: | ||
| name: Apply Prod | ||
| needs: [Set-Release-Tag, DeployStage] | ||
| uses: ./.github/workflows/deploy_environment.yml | ||
| uses: ./.github/workflows/tf_apply.yml | ||
| permissions: | ||
| id-token: write # Required to assume the Terraform apply role through OIDC. | ||
| contents: read # Required to check out the Terraform code. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the upgrade-together requirement to the migration note.
Callers that remain on the old
deploy_environmenttag run atf_applywith a different concurrency group and no lock timeout. Runs on tf_apply 0.4.0 do not queue behind them. An old run can start while a new run holds the state lock, and then it fails on the lock instead of waiting. Terraform's state lock still prevents two applies from writing the same state at once, so the failure is a failed run that a rerun can recover.Add this sentence to the migration note, after the instruction to switch the
uses:line: