Slackbot
01/10/2024, 5:08 PMLoïc Petit
01/10/2024, 5:11 PMversion: 3
delete_source_branch_on_merge: true
automerge: false
projects:
- name: sdbx-deployment
# execution_order_group: 1 => raised an error
branch: /hotfix/
dir: infra
workspace: staging
autoplan:
when_modified: ["*.tf", "./values/sdbx-sre/*.tfvars", "./infra/values/sdbx-sre/*.tfvars"]
enabled: true
apply_requirements: [mergeable, approved]
workflow: tf-deployment
workflows:
tf-deployment:
plan:
steps:
- init
- run: terraform workspace select $WORKSPACE || terraform workspace new $WORKSPACE
- env:
name: AWS_ACCOUNT
command: 'echo $WORKSPACE | cut -d "_" -f4'
- plan:
extra_args:
- "-var-file=values/$AWS_ACCOUNT/$WORKSPACE.tfvars"
apply:
steps:
- run: terraform workspace select $WORKSPACE
- applyoponomarov-tu
01/17/2024, 3:45 PMatlantis apply on a hotfix branch without the need for a PR approval.
at my org i did solve this problem differently -- we have a custom github action workflow that reacts to /approve comment and then the technical user account (bot) comes in and approves the pr. the workflow accepts a github team, so basically only sre can use /approve.oponomarov-tu
01/17/2024, 3:46 PMLoïc Petit
01/18/2024, 10:46 AMoponomarov-tu
03/01/2024, 11:21 AM---
name: slash command dispatcher
on:
workflow_call:
secrets:
gh_token:
required: true
jobs:
command:
runs-on: ubuntu-latest
steps:
- name: slash command dispatch pull-request
if: ${{ github.event.issue.pull_request }}
uses: peter-evans/slash-command-dispatch@v3
with:
token: ${{ secrets.gh_token }}
commands: |
approve
static-args: |
author=${{ github.actor }}
pull_request=true
pull_request_number=${{ github.event.issue.number }}
slash-on-approve.yaml:
---
name: slash command on approve
on:
workflow_call:
inputs:
allowed_team:
description: "The team name that is permitted to execute the `/approve` command. This team should belong to the specified organization."
required: true
type: string
approver:
description: "The GitHub user or bot that will be marked as the approver for certain actions within this workflow. Defaults to '<redacted>-ci-bot'."
required: false
type: string
default: "<redacted>-ci-bot"
organization:
description: "The name of the GitHub organization in which the allowed team is situated. Defaults to '<your org name>'."
required: false
type: string
default: "<your org name>"
secrets:
gh_token:
description: "The GitHub token used for authentication and performing privileged actions (review / approve) within this workflow. Make sure this token has appropriate permissions."
required: true
jobs:
command:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
github-token: ${{ secrets.gh_token }}
debug: true
script: |
const pull_request = '${{ github.event.client_payload.slash_command.args.named.pull_request }}'
const pull_request_number = '${{ github.event.client_payload.slash_command.args.named.pull_request_number }}'
const author = '${{ github.event.client_payload.slash_command.args.named.author }}'
const approver = '${{ inputs.approver }}'
const allowed_teams = ['${{ inputs.allowed_team }}']
// Check if author belongs to any of the allowed teams
var is_allowed = false;
for (const team of allowed_teams) {
try {
const { data: membership } = await github.rest.teams.getMembershipForUserInOrg({
org: '${{ inputs.organization }}',
team_slug: team,
username: author
});
if (membership.state === "active") {
is_allowed = true;
break;
}
} catch (error) {
console.log(`User ${author} is not a member of team ${team}`);
}
}
if (!is_allowed) {
github.rest.issues.createComment({
issue_number: pull_request_number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Error: You must be a member of one of the following teams to use the \`/approve\` command: ${allowed_teams.join(', ')}.`
});
return;
}
const {data: thepull} = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull_request_number
})
const output = `Emergency pull-request approval. Approved by: \`${approver}\``;
const {data: reviewers} = await github.rest.pulls.listRequestedReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull_request_number
});
const {data: reviews} = await github.rest.pulls.listReviews({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull_request_number
});
var is_approved = false;
var is_requested_for_review = false;
for (const aReview of reviews) {
if(aReview.user.login == approver && aReview.state == 'APPROVED') {
is_approved = true;
break;
}
}
for (const aUser of reviewers.users) {
if (aUser.login == approver) {
is_requested_for_review = true;
break;
}
}
if (!is_approved || is_requested_for_review) {
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull_request_number,
event: "APPROVE"
});
github.rest.issues.createComment({
issue_number: pull_request_number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
});
}
then in the terraform repo just call the workflows:
1:
---
name: chatops
on:
issue_comment:
types:
- created
permissions:
issues: write
pull-requests: write
jobs:
slash-command-dispatcher:
uses: <org name>/github-actions/.github/workflows/slash-commands.yaml@master
secrets:
gh_token: ${{ secrets.<pat for the ci bot that can approve the pr> }}
2:
---
name: slash command on approve
on:
repository_dispatch:
types:
- approve-command
permissions:
issues: write
pull-requests: write
jobs:
slash-command-dispatcher:
uses: <org name>/github-actions/.github/workflows/slash-on-approve.yaml@master
with:
allowed_team: 'team-name-that-can-/approve'
secrets:
gh_token: ${{ secrets.<pat for the ci bot that can approve the pr> }}Loïc Petit
03/01/2024, 2:08 PM