diff --git a/.github/workflows/audit-account.yml b/.github/workflows/audit-account.yml new file mode 100644 index 00000000..e0d2331e --- /dev/null +++ b/.github/workflows/audit-account.yml @@ -0,0 +1,64 @@ +name: Audit Account + +on: + schedule: + - cron: "0 16 * * 1" # Every Monday at 1600 UTC + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.ref }} + cancel-in-progress: false + +permissions: + id-token: write + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: set variable values + run: ./.github/build-vars.sh set_values + env: + AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }} + AWS_OIDC_ROLE_TO_ASSUME: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }} + - name: Configure AWS credentials for GitHub Actions + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.AWS_OIDC_ROLE_TO_ASSUME }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - name: Collect resources from account + run: pushd .github && aws resourcegroupstaggingapi get-resources > resources.json + - name: List active resources created by CI pipeline + run: pushd .github && ./audit-account.sh ci_active resources.json + - name: List orphaned resources created by CI pipeline + run: pushd .github && ./audit-account.sh ci_inactive resources.json + - name: List resources created by Cloudformation but not from CI pipeline + run: pushd .github && ./audit-account.sh cf_other resources.json + - name: List untagged resources + run: pushd .github && ./audit-account.sh untagged resources.json + - name: Create reports dir + run: pushd .github && mkdir -p reports + - name: Assemble CSV files + run: | + #!/bin/bash + pushd .github + echo "Reports with no entries will be omitted" + CI_ACTIVE="$(./audit-account.sh ci_active resources.json)" + [[ $(jq -r 'length' <<< "${CI_ACTIVE}") -gt 0 ]] && jq -r '(.[0] + | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' <<< "${CI_ACTIVE}" > reports/ci_active.csv + CI_INACTIVE="$(./audit-account.sh ci_inactive resources.json)" + [[ $(jq -r 'length' <<< "${CI_INACTIVE}") -gt 0 ]] && jq -r '(.[0] + | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' <<< "${CI_INACTIVE}" > reports/ci_inactive.csv + CF_OTHER="$(./audit-account.sh cf_other resources.json)" + [[ $(jq -r 'length' <<< "${CF_OTHER}") -gt 0 ]] && jq -r '(.[0] + | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' <<< "${CF_OTHER}" > reports/cf_other.csv + UNTAGGED="$(./audit-account.sh untagged resources.json)" + [[ $(jq -r 'length' <<< "${UNTAGGED}") -gt 0 ]] && jq -r '(.[0] + | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' <<< "${UNTAGGED}" > reports/untagged.csv + - name: Upload reports + uses: actions/upload-artifact@v4 + with: + name: resource-reports + path: .github/reports/ + retention-days: 14 diff --git a/.github/workflows/post-deploy-slack-notification.yml b/.github/workflows/post-deploy-slack-notification.yml new file mode 100755 index 00000000..a3ac0ef4 --- /dev/null +++ b/.github/workflows/post-deploy-slack-notification.yml @@ -0,0 +1,51 @@ +name: Post Deploy + +on: + workflow_run: + workflows: [Deploy] + types: [completed] + branches: + - 'main' + - 'val' + - 'production' + - 'snyk-**' + +jobs: + notify_on_failure: + # Sends alert to macpro-mdct--alerts channel in CMS slack when any integration environment fails to deploy or run tests + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' && (github.event.workflow_run.head_branch == 'main' || github.event.workflow_run.head_branch == 'val' || github.event.workflow_run.head_branch == 'production') }} + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_TITLE: ":boom: The latest ${{ github.repository }} build on branch '${{ github.event.workflow_run.head_branch }}' has failed" + SLACK_MESSAGE: "${{ github.event.workflow_run.html_url }}" + MSG_MINIMAL: true + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + # Notify the integrations channel only when a Snyk auto merge fails + notify_failed_snyk_auto_merge: + runs-on: ubuntu-latest + #only check branch names that begin with snyk- + if: ${{ github.event.workflow_run.conclusion == 'failure' && startsWith(github.event.workflow_run.head_branch, 'snyk-') }} + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_TITLE: ":boom: A Synk auto merge has failed in ${{ github.repository }}" + SLACK_MESSAGE: "${{ github.event.workflow_run.html_url }}" + MSG_MINIMAL: true + SLACK_WEBHOOK: ${{ secrets.INTEGRATIONS_SLACK_WEBHOOK }} + + # Sends a slack message to the mdct-prod-releases channel in CMS slack + notify_on_prod_release: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_branch == 'production') }} + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_TITLE: ":rocket: ${{ github.repository }} has successfully released to production." + MSG_MINIMAL: true + SLACK_WEBHOOK: ${{ secrets.PROD_RELEASE_SLACK_WEBHOOK }} diff --git a/.github/workflows/pr-notification.yml b/.github/workflows/pr-notification.yml new file mode 100755 index 00000000..bf9befa9 --- /dev/null +++ b/.github/workflows/pr-notification.yml @@ -0,0 +1,61 @@ +name: Pull Request Notification + +on: + pull_request: + types: [opened, reopened, ready_for_review] + +permissions: + id-token: write + contents: write + issues: write + pull-requests: write + +jobs: + endpoint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: set branch_name # Some integrations (Snyk) build very long branch names. This is a switch to make long branch names shorter. + run: | + BRANCH_NAME=$(./.github/setBranchName.sh ${{ github.event.pull_request.head.ref }}) + echo "branch_name=${BRANCH_NAME}" >> $GITHUB_ENV + - uses: actions/checkout@v4 + - name: set branch specific variable names + run: ./.github/build-vars.sh set_names + - name: set variable values + run: ./.github/build-vars.sh set_values + - name: Configure AWS credentials for GitHub Actions + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_OIDC_ROLE_TO_ASSUME }} + aws-region: ${{ secrets.AWS_DEFAULT_REGION }} + - name: get endpoint + id: getendpoint + run: | + set +e + application_endpoint_url=$(aws cloudformation describe-stacks --stack-name ui-${{ env.branch_name }} --output text --query "Stacks[0].Outputs[?OutputKey=='ApplicationEndpointUrl'].OutputValue") + set -e + if [[ -z $application_endpoint_url || ! $application_endpoint_url == http* ]]; then + application_endpoint_url="endpoint not found" + fi + echo "application_endpoint_url=$application_endpoint_url" >> $GITHUB_OUTPUT + + outputs: + application_endpoint_url: ${{ steps.getendpoint.outputs.application_endpoint_url }} + + + notify_integrations_channel: + runs-on: ubuntu-latest + needs: + - endpoint + # avoiding notifications for automated Snyk Pull Requests and draft pull requests + if: github.actor != 'mdct-github-service-account' && !github.event.pull_request.draft + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_TITLE: ":github: A new pull request has been created in ${{ github.repository }} by ${{ github.event.pull_request.user.login }}" + SLACK_MESSAGE: "${{ github.event.pull_request.html_url }} \n Cloudfront URL: ${{ needs.endpoint.outputs.application_endpoint_url }}" + MSG_MINIMAL: true + SLACK_WEBHOOK: ${{ secrets.INTEGRATIONS_SLACK_WEBHOOK }}