Skip to content
Merged
110 changes: 110 additions & 0 deletions .github/workflows/dependabot-auto-approve.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Dependabot auto-approve
on: pull_request
permissions:
pull-requests: read
jobs:
validate_dependabot_opened_this_PR:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]'
steps:
- run: echo "This PR was raised by Dependabot"
validate_this_is_an_allowed_dependency:
needs: validate_dependabot_opened_this_PR
runs-on: ubuntu-latest
outputs:
is_allowed_dependency: ${{ steps.check_if_allowed_dependency.outputs.is_allowed_dependency }}
steps:
- name: Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2
- if: |
contains(steps.dependabot-metadata.outputs.package-ecosystem, 'bundler') &&
(steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch')
id: check_if_allowed_dependency
run: |
echo "is_allowed_dependency=1" >> "$GITHUB_OUTPUT"
wait_for_checks:
runs-on: ubuntu-latest
needs: [ validate_dependabot_opened_this_PR, validate_this_is_an_allowed_dependency ]
if: ${{ needs.validate_this_is_an_allowed_dependency.outputs.is_allowed_dependency == 1 }}
steps:
- name: Wait for required checks to pass
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
SHA: ${{ github.event.pull_request.head.sha }}
run: |
echo "Waiting for all required checks to pass on commit $SHA..."

MAX_RETRIES=30
RETRY_DELAY=10
ATTEMPT=0

while [ $ATTEMPT -lt $MAX_RETRIES ]; do
echo "Attempt $((ATTEMPT+1))/$MAX_RETRIES"

# Get all check runs for the commit
RESPONSE=$(curl -s -H "Authorization: token $GH_TOKEN" \
"https://api.github.com/repos/$REPO/commits/$SHA/check-runs")

# Exclude self (wait_for_checks)
EXCLUDED_CHECK="wait_for_checks"

echo "Ignoring ${EXCLUDED_CHECK}"

# Extract conclusions
CONCLUSIONS=$(echo "$RESPONSE" | jq -r '.check_runs[] | select(.name != "wait_for_checks") | .name + ":" + (.status + "/" + (.conclusion // "none"))')

echo "$CONCLUSIONS"

# Are there any in_progress or queued?
PENDING=$(echo "$RESPONSE" | jq -r --arg exclude "$EXCLUDED_CHECK" '[.check_runs[] | select(.name != $exclude and .status != "completed")] | length')

# Are all completed and successful?
FAILED=$(echo "$RESPONSE" | jq -r --arg exclude "$EXCLUDED_CHECK" '[.check_runs[] | select(.name != $exclude and .status == "completed" and .conclusion != "success")] | length')

if [ "$PENDING" -eq 0 ] && [ "$FAILED" -eq 0 ]; then
echo "All checks completed successfully."
exit 0
fi

if [ "$FAILED" -gt 0 ]; then
echo "One or more checks failed."
exit 1
fi

echo "Some checks still pending. Waiting $RETRY_DELAY seconds..."
sleep $RETRY_DELAY
ATTEMPT=$((ATTEMPT + 1))
done

echo "Timed out waiting for checks to complete."
exit 1
auto_approve_and_merge:
permissions:
pull-requests: write
contents: write
runs-on: ubuntu-latest
needs: [validate_dependabot_opened_this_PR, validate_this_is_an_allowed_dependency, wait_for_checks]
if: ${{ needs.validate_this_is_an_allowed_dependency.outputs.is_allowed_dependency == 1 }}
steps:
- uses: actions/checkout@v4
- name: Approve a PR if not already approved
run: |
# Sets the upstream metadata for `gh pr status`
gh pr checkout "${PR_URL}"

if [ "$(gh pr status --json reviewDecision -q .currentBranch.reviewDecision)" != "APPROVED" ];
then
gh pr review --approve "${PR_URL}"
else
echo "PR already approved, skipping additional approvals to minimize emails/notification noise.";
fi
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Enable auto-merge for Dependabot PRs
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
22 changes: 22 additions & 0 deletions .github/workflows/lint_workflows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: "Lint Workflows"

on:
pull_request:
branches: [main]
permissions:
contents: read
jobs:
actionlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download actionlint
id: get_actionlint
run: |
curl -L "https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz" | tar -xvz actionlint
chmod +x actionlint
sudo mv actionlint /usr/local/bin/actionlint
shell: bash
- name: Check workflow files
run: actionlint -color
shell: bash
13 changes: 8 additions & 5 deletions .github/workflows/review_apps_on_pr_change.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: Determine Terraform version
id: terraform-version
run: |
cat .review_apps/.terraform-version | xargs printf "TF_VERSION=%s" >> "$GITHUB_OUTPUT"
echo "TF_VERSION=$(< .review_apps/.terraform-version)" >> "$GITHUB_OUTPUT"

- uses: hashicorp/setup-terraform@v3
with:
Expand All @@ -64,10 +64,11 @@ jobs:
-no-color \
-auto-approve

echo "REVIEW_APP_URL=$(terraform output -raw review_app_url)" >> "$GITHUB_OUTPUT"
echo "ADMIN_APP_URL=$(terraform output -raw admin_app_url)" >> "$GITHUB_OUTPUT"
echo "ECS_CLUSTER_ID=$(terraform output -raw review_app_ecs_cluster_id)" >> "$GITHUB_OUTPUT"
echo "ECS_SERVICE_NAME=$(terraform output -raw review_app_ecs_service_name)" >> "$GITHUB_OUTPUT"
# shellcheck disable=SC2129 # SC2129 is "mainly a stylistic issue" and it breaks our flow
echo "REVIEW_APP_URL=$(terraform output -raw review_app_url)" >> "$GITHUB_OUTPUT"
echo "ADMIN_APP_URL=$(terraform output -raw admin_app_url)" >> "$GITHUB_OUTPUT"
echo "ECS_CLUSTER_ID=$(terraform output -raw review_app_ecs_cluster_id)" >> "$GITHUB_OUTPUT"
echo "ECS_SERVICE_NAME=$(terraform output -raw review_app_ecs_service_name)" >> "$GITHUB_OUTPUT"

- name: Wait for AWS ECS deployments to finish
run: |
Expand Down Expand Up @@ -102,6 +103,8 @@ jobs:
$COMMENT_MARKER
EOF

# shellcheck disable=SC2016
# `jq` uses single-quote characters on Unix shells
old_comment_ids=$(gh api "repos/{owner}/{repo}/issues/${{github.event.pull_request.number}}/comments" --jq 'map(select((.user.login == "github-actions[bot]") and (.body | endswith($ENV.COMMENT_MARKER + "\n")))) | .[].id')
for comment_id in $old_comment_ids; do
gh api -X DELETE "repos/{owner}/{repo}/issues/comments/${comment_id}"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/review_apps_on_pr_close.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Determine Terraform version
id: terraform-version
run: |
cat .review_apps/.terraform-version | xargs printf "TF_VERSION=%s" >> "$GITHUB_OUTPUT"
echo "TF_VERSION=$(< .review_apps/.terraform-version)" >> "$GITHUB_OUTPUT"

- uses: hashicorp/setup-terraform@v3
with:
Expand Down