Created
March 1, 2021 16:23
-
-
Save eddie-knight/0872c56b3d0f388b936dd6bd33448f37 to your computer and use it in GitHub Desktop.
This file contains 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 characters
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 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 characters
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 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 characters
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 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 characters
#!/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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment