Created
March 1, 2021 16:23
-
-
Save eddie-knight/0872c56b3d0f388b936dd6bd33448f37 to your computer and use it in GitHub Desktop.
Revisions
-
Eddie Knight created this gist
Mar 1, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,66 @@ anchors: tf_init: &tf_init | terraform init -lock=false \ -backend-config="resource_group_name=terraform" \ -backend-config="key=${{ env.TF_BACKEND_KEY }}" \ -backend-config="access_key=${{ secrets.TF_BACKEND_ACCESS_KEY }}" \ -backend-config="storage_account_name=${{ secrets.TF_BACKEND_SA }}" setup_backend_key: &setup_backend_key "githubdeployment.${{ github.event.inputs.environment }}.aks_setup.terraform.tfstate" configure_backend_key: &configure_backend_key "githubdeployment.${{ github.event.inputs.environment }}.aks_configure.terraform.tfstate" validation_steps: &validation_steps - name: Checkout uses: actions/checkout@v2 - name: Setup Terraform Environment uses: hashicorp/setup-terraform@v1 with: terraform_version: 0.14.5 cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }} - name: Terraform Format id: fmt run: terraform fmt -check continue-on-error: true - name: Terraform Init run: *tf_init id: init continue-on-error: true - name: Terraform Validate id: validate if: github.event_name == 'pull_request' run: terraform validate -no-color continue-on-error: true - name: Create PR comment with check results uses: actions/[email protected] if: github.event_name == 'pull_request' && (steps.fmt.outcome == 'failure' || steps.init.outcome == 'failure' || steps.validate.outcome == 'failure') with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `### Result from failed workflow: ${{ github.workflow }} #### Terraform Format and Style :pencil2: \`${{ steps.fmt.outcome }}\` #### Terraform Initialization :gear:\`${{ steps.init.outcome }}\` #### Terraform Validate :interrobang:\`${{ steps.validate.outcome }}\` *Pusher: @${{ github.actor }}, Action: ${{ github.event_name }}*`; github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output }) - name: Exit based on status of fmt, init, and validate if: steps.fmt.outcome == 'failure' || steps.init.outcome == 'failure' || steps.validate.outcome == 'failure' run: | echo Init: ${{ steps.init.outcome }} echo Format: ${{ steps.fmt.outcome }} echo Validate: ${{ steps.validate.outcome }} exit 1 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,42 @@ jobs: validate: defaults: run: {shell: bash, working-directory: terraform/aks/setup} env: {TF_BACKEND_KEY: githubdeployment.dev.aks_setup.terraform.tfstate} name: Validate Terraform runs-on: ubuntu-latest steps: - {name: Checkout, uses: actions/checkout@v2} - name: Setup Terraform Environment uses: hashicorp/setup-terraform@v1 with: {cli_config_credentials_token: '${{ secrets.TF_API_TOKEN }}', terraform_version: 0.14.5} - {continue-on-error: true, id: fmt, name: Terraform Format, run: terraform fmt -check} - {continue-on-error: true, id: init, name: Terraform Init, run: "terraform init\ \ -lock=false \\\n-backend-config=\"resource_group_name=terraform\" \\\n-backend-config=\"\ key=${{ env.TF_BACKEND_KEY }}\" \\\n-backend-config=\"access_key=${{ secrets.TF_BACKEND_ACCESS_KEY\ \ }}\" \\\n-backend-config=\"storage_account_name=${{ secrets.TF_BACKEND_SA\ \ }}\"\n"} - {continue-on-error: true, id: validate, if: github.event_name == 'pull_request', name: Terraform Validate, run: terraform validate -no-color} - if: github.event_name == 'pull_request' && (steps.fmt.outcome == 'failure' || steps.init.outcome == 'failure' || steps.validate.outcome == 'failure') name: Create PR comment with check results uses: actions/[email protected] with: {github-token: '${{ secrets.GITHUB_TOKEN }}', script: "const output =\ \ `### Result from failed workflow: ${{ github.workflow }}\n#### Terraform\ \ Format and Style :pencil2: \\`${{ steps.fmt.outcome }}\\`\n\n#### Terraform\ \ Initialization :gear:\\`${{ steps.init.outcome }}\\`\n\n#### Terraform\ \ Validate :interrobang:\\`${{ steps.validate.outcome }}\\`\n\n*Pusher:\ \ @${{ github.actor }}, Action: ${{ github.event_name }}*`;\n \ngithub.issues.createComment({\n\ \ issue_number: context.issue.number,\n owner: context.repo.owner,\n \ \ repo: context.repo.repo,\n body: output\n})\n"} - {if: steps.fmt.outcome == 'failure' || steps.init.outcome == 'failure' || steps.validate.outcome == 'failure', name: 'Exit based on status of fmt, init, and validate', run: "echo\ \ Init: ${{ steps.init.outcome }}\necho Format: ${{ steps.fmt.outcome }}\n\ echo Validate: ${{ steps.validate.outcome }}\nexit 1\n"} name: Validate AKS Setup Terraform on: pull_request: paths: [.github/anchors.yml, .github/workflows/aks-setup-validate.yml, terraform/aks/setup/*, terraform/modules/aks/setup/*] This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,22 @@ name: "Validate AKS Setup Terraform" on: pull_request: paths: - ".github/anchors.yml" - ".github/workflows/aks-setup-validate.yml" - "terraform/aks/setup/*" - "terraform/modules/aks/setup/*" jobs: validate: name: "Validate Terraform" runs-on: ubuntu-latest env: TF_BACKEND_KEY: githubdeployment.dev.aks_setup.terraform.tfstate defaults: run: shell: bash working-directory: terraform/aks/setup steps: *validation_steps This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,103 @@ #!/c/Users/eknight/AppData/Local/Microsoft/WindowsApps/python # Dev requirement for modifying "anchored" github workflows: # Change the above line to YOUR `which python` # then run `git config core.hooksPath .githooks` import subprocess, sys import ruamel.yaml from pathlib import Path import json yaml = ruamel.yaml.YAML(typ='safe') anchors = '' def main(): ''' Search for any .anchored workflows, parse them, then add any changed files to the current commit ''' cmd = subprocess.check_output( ["ls", ".github/anchored-workflows/*.anchored"], stderr=subprocess.STDOUT).decode("utf-8") # Get all .anchored filenames filepaths = cmd.splitlines() with open(".github/anchors.yml", errors='ignore') as file: global anchors anchors = file.read() for infile_path in filepaths: parse(infile_path) def parse(infile_path): ''' Parse anchored file, and if modified then stage the new file to be included in the current commit ''' outfile_path = infile_path.replace("anchored-workflows", "workflows").replace(".anchored", "") parsed = parse_anchored_yaml(infile_path, outfile_path) if parsed: print(f"Parsed anchored workflow: {infile_path}->{outfile_path}") subprocess.call( ["git", "add", outfile_path, infile_path], stderr=subprocess.STDOUT) # Stage file into the current commit def parse_anchored_yaml(infile_path, outfile_path): ''' Parses any .anchored file into a valid Github Actions workflow ''' yaml_data = parse_workflow(infile_path, outfile_path) if not yaml_data: return False if write_parsed_workflow(infile_path, outfile_path, yaml_data): return True def write_parsed_workflow(infile_path, outfile_path, yaml_data): ''' If workflow would be modified by changes to the .anchored file, write those changes now ''' try: with open(outfile_path, "r") as file: old_yaml = yaml.load(file) except: old_yaml = None if old_yaml != yaml_data: with open(outfile_path, "w") as file: yaml.dump(yaml_data, file) return True return False def parse_workflow(infile, outfile): ''' Parse the .anchored workflow with anchors, then restore it to it's previous state ''' anchored = add_anchors_to_infile(infile) yaml_data = get_parsed_workflow(infile) restore_anchored_file(infile, anchored) if yaml_data: return yaml_data return None def add_anchors_to_infile(infile): ''' Rewrite the .anchored file with our anchors appended to the top ''' with open(infile, "r", errors='ignore') as file: anchored = file.read() with open(infile, "w") as file: file.write(f"{anchors}\n{anchored}") return anchored def get_parsed_workflow(infile): ''' Load the .anchored workflow into memory, automatically parsing all anchors ''' with open(infile, "r", errors='ignore') as file: try: yaml_data = yaml.load(file) del yaml_data["anchors"] # Github Actions will fail if this is present return yaml_data except Exception as e: print(f"Invalid YAML in {infile}:\n {e}") return None def restore_anchored_file(infile, anchored): ''' Return the .anchored file to its previous state ''' with open(infile, "w", errors='ignore') as file: file.seek(0) file.write(anchored) main()