# This file is generated by `generate.sh`. # Generated from https://github.com/bellroy/gha-workflows/tree/master/dhall/workflows/configuration/main.dhall # Think twice before editing it directly. concurrency: cancel-in-progress: false group: "${{ github.ref }}" env: SYSTEM_NAME: Product Configuration jobs: build: needs: - validateContent runs-on: ubuntu-20.04 steps: - if: "github.ref == 'refs/heads/master' || github.ref == 'refs/heads/stable'" name: checkout branch uses: "bellroy/gha-workflows/composite/checkout@master" with: fetch-depth: "0" token: "${{ env.GH_TOKEN }}" - if: "github.ref != 'refs/heads/master' && github.ref != 'refs/heads/stable'" name: checkout branch uses: "bellroy/gha-workflows/composite/checkout@master" with: fetch-depth: "1" token: "${{ env.GH_TOKEN }}" - id: extract_branch name: Extract branch name run: | echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT shell: bash - if: "github.ref == 'refs/heads/master'" name: Set env variables for staging run: | echo "DESTINATION=Staging Environment" >> $GITHUB_ENV echo "ENVIRONMENT=staging" >> $GITHUB_ENV - if: "github.ref == 'refs/heads/stable'" name: Set env variables for production run: | echo "DESTINATION=Production Environment" >> $GITHUB_ENV echo "ENVIRONMENT=production" >> $GITHUB_ENV - name: Install and setup nix uses: "bellroy/gha-workflows/composite/install-nix@master" with: bellroy-nix-cache-access: none nix-config-access-tokens: "github.com=${{ secrets.READ_HASKELL_REPO_PAT }}" - name: Install script packages run: | sudo apt-get update sudo apt-get install -y parallel - name: Get Pull Request number run: | echo "PR_NUMBER=$(gh pr view --json number -q .number)" >> $GITHUB_ENV working-directory: "${{ env.GITHUB_WORKSPACE }}" - id: changed-files name: Get changed files uses: "tj-actions/changed-files@48d8f15b2aaa3d255ca5af3eba4870f807ce6b3c" with: path: "${{ env.GIT_REPOSITORY_PATH }}" - id: check_changes name: Check for CSV changes run: 'echo "csv_changed=${{ steps.changed-files.outputs.all_changed_files == '''' && ''0'' || contains(steps.changed-files.outputs.all_changed_files, ''.csv'') && ''1'' || ''0'' }}" >> $GITHUB_OUTPUT' - if: "steps.check_changes.outputs.csv_changed == '1'" name: Check that all configuration CSV files are sorted alphabetically run: | set +e IFS= output=$(./scripts/check_configuration_csvs_sorted 2>&1) status=$? if (($status)); then echo "Configuration CSV files are not sorted:" >>/tmp/pr-comment.txt echo "" >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt echo $output >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt exit $status else echo "All configuration CSV files are sorted." fi - id: fetch_byproduct name: Fetch byproduct uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: byproduct tool-version: latest - id: fetch_gitapult name: Fetch gitapult uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: gitapult tool-version: latest - id: fetch_config-rules-cli name: Fetch config-rules-cli uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: config-rules-cli tool-version: latest - id: fetch_powerful-owl name: Fetch powerful-owl uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: powerful-owl tool-version: latest - name: Run byproduct once run: | find products/autogenerated/ -type f -name '*.json' | grep -v './\.' | xargs rm ./byproduct execute --once --in products/configuration --out products/autogenerated - name: Configure git run: | git config --global user.name "${{ github.actor }}" git config --global user.email "${{ github.actor }}@users.noreply.github.com" - name: Update autogenerated product files run: | git add products/autogenerated if git commit -m "Update autogenerated product files"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi - name: Update products autogenerated content blocks run: | scripts/update_products_autogenerated_content_blocks git add products/content if git commit -m "Update autogenerated products content blocks"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi - name: Set merge base run: | if [ "${{ github.ref }}" = "refs/heads/master" ]; then echo "MERGE_BASE=origin/stable" >> $GITHUB_ENV else echo "MERGE_BASE=$(git show-branch --merge-base origin/master ${{ steps.extract_branch.outputs.branch }})" >> $GITHUB_ENV fi - if: "env.PR_NUMBER != 0" name: Write byproduct validate output to env variable run: | set +e IFS= output=$(./gitapult changeset --git_root "$GITHUB_WORKSPACE" --from "${{ env.MERGE_BASE }}" | ./byproduct validate --markdown 2>&1) status=$? if (($status)); then echo $output >>/tmp/pr-comment.txt exit $status else echo "Byproduct validation succeeded." fi - name: Update feed autogenerated content blocks run: | nix run .#update_feeds_autogenerated_content_blocks git add feeds/content if git commit -m "Update autogenerated feed content blocks"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi - name: Update feed autogenerated rendering data run: | POWERFUL_OWL_COMMAND=$GITHUB_WORKSPACE/powerful-owl POWERFUL_OWL_FOLDER=./feeds/ ./scripts/generate-rendering-data git add ./feeds/page_rendering_data git add ./feeds/rendering_data if git commit -m "Update feed autogenerated rendering data"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi working-directory: "${{ env.GIT_REPOSITORY_PATH }}" - name: Update feed golden tests run: | scripts/update_feeds_golden_tests git add feeds/tests/golden if git commit -m "Update autogenerated feeds golden test outputs"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi - name: Update autogenerated shipping configuration files run: | set +e IFS= output=$(./config-rules-cli shipping-options-transform --input-csv-dir shipping/configuration --output-json-dir shipping/autogenerated) status=$? if (($status)); then echo "Failed to transform shipping data" >>/tmp/pr-comment.txt echo "" >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt echo $output >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt exit $status else git add shipping/autogenerated if git commit -m "Update autogenerated shipping configuration files"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi fi - name: Generate new shipping tests run: | SHIPPING_TEST_DIRECTORY=shipping/tests find $SHIPPING_TEST_DIRECTORY -type f -name '*.result.json' -exec rm {} \; ./config-rules-cli -- shipping-options-check --repo-dir . - if: "env.PR_NUMBER != 0 && github.ref != 'refs/heads/stable' && github.ref != 'refs/heads/master'" name: Commit new shipping tests run: | if [ $(git status shipping/tests --porcelain=v1 | wc -l) -gt 0 ] then git add shipping/tests git commit -m "Update shipping tests" echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV fi - name: Update autogenerated promotion configuration files run: | set +e IFS= output=$(./config-rules-cli promotion-transform --input-csv-dir promotions/configuration --output-json-dir promotions/autogenerated) status=$? if (($status)); then echo "Failed to transform promotions data" >>/tmp/pr-comment.txt echo "" >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt echo $output >>/tmp/pr-comment.txt echo "\`\`\`" >>/tmp/pr-comment.txt exit $status else git add promotions/autogenerated if git commit -m "Update autogenerated promotions configuration files"; then echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV else echo "No changes detected" fi fi - name: Generate new promotion rule tests run: | PROMOTIONS_TEST_DIRECTORY=promotions/tests find $PROMOTIONS_TEST_DIRECTORY -type f -name '*.result.json' -exec rm {} \; ./config-rules-cli -- promotion-check --repo-dir . - if: "env.PR_NUMBER != 0 && github.ref != 'refs/heads/stable' && github.ref != 'refs/heads/master'" name: Commit new promotion tests run: | if [ $(git status promotions/tests --porcelain=v1 | wc -l) -gt 0 ] then git add promotions/tests git commit -m "Update promotion tests" echo "GENERATED_ANOTHER_COMMIT=true" >> $GITHUB_ENV fi - if: "env.GENERATED_ANOTHER_COMMIT == 'true'" name: Push any new commits and exit workflow if commits pushed run: | git push --set-upstream origin HEAD gh run cancel ${{ github.run_id }} gh run watch ${{ github.run_id }} - id: current-time name: Get current time run: 'echo "timestamp=$(date -u +"%y%m%d%H%M%S")" >> $GITHUB_OUTPUT' - id: extract_changes if: "github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/master'" name: Set changes variable run: | echo "COMMIT_CHANGES<> $GITHUB_ENV echo "$(git log --oneline --format=\"%s\" $(git tag -l [0-9]*_${{ env.ENVIRONMENT }} | tail -n 1)..${{ steps.extract_branch.outputs.branch }} | grep -v 'Merge pull request' | grep -v "Merge branch 'master' into" | sed -e 's/^"//' -e 's/"$//' | cat)" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV shell: bash working-directory: "${{ env.GITHUB_WORKSPACE }}" - env: SLACK_BOT_TOKEN: "${{ secrets.BELLROY_SLACK_TOKEN }}" id: slack-deploy if: "github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/master'" name: Slack - Notifications - Post to slack uses: "slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e" with: channel-id: "${{ env.SLACK_CHANNEL_ID }}" payload: | { "text": ":loudspeaker: *${{ github.actor }}* is deploying *${{ env.SYSTEM_NAME }}* to *${{ env.DESTINATION }}* from *${{ steps.extract_branch.outputs.branch }}*", "attachments": [ { "fallback": "Deployment summary", "color": "ffd966", "fields": [ { "title": "What is being deployed", "value": ${{ toJSON(env.COMMIT_CHANGES) }}, "short": false }, { "title": "Status", "short": true, "value": "In Progress" } ] } ] } - if: "github.ref == 'refs/heads/master'" name: Push content to staging run: | set -e # XXX: Gitapult cannot distinguish datasets, so we push all data to # both endpoints and allow the server to decide what to do. # Kafka Webhooks accepts all datasets at once ./gitapult run \ --git_root "$GITHUB_WORKSPACE" \ --authorization_token "$KW_STAGING_API_KEY" \ --changeset_url "$KW_STAGING_BASE_URL/gitapult/configuration/records" \ --revision_url "$KW_STAGING_BASE_URL/gitapult/configuration/revision" \ --api_key \ --compress \ --max-payload-bytes 3000000 # XXX: V3 doesn't care about rendering data, but it is too large to send. # As at 2024-02-14 gitapult does not support selecting which data to send. git -C "$GIT_REPOSITORY_PATH" rm feeds/rendering_data/.gitapult.json ./gitapult run \ --git_root "$GITHUB_WORKSPACE" \ --authorization_token "$SF_STAGING_API_KEY" \ --changeset_url "$SF_STAGING_BASE_URL/api/v1/configuration/shipping" \ --revision_url "$SF_STAGING_BASE_URL/api/v1/configuration/shipping/revisions" && \ git -C "$GIT_REPOSITORY_PATH" restore --staged feeds/rendering_data/.gitapult.json git -C "$GIT_REPOSITORY_PATH" restore feeds/rendering_data/.gitapult.json - if: "success() && github.ref == 'refs/heads/master'" name: Tag published staging content run: | git tag "${{ join(steps.current-time.outputs.*, '\n') }}_staging" && git push --tags - if: "github.ref == 'refs/heads/master'" name: Open PR to stable run: | curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls -d '{"head":"master","base":"stable","title":"Merge branch master into stable","body":"This PR was automatically generated by CI."}' PR_URL=$(curl -sX GET -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls\?head\=bellroy:master\&base\=stable | jq -r '.[0].html_url | select(length>0)') echo "PR_URL=$PR_URL" >> $GITHUB_ENV - continue-on-error: true if: "github.ref == 'refs/heads/master'" name: Set assignee run: | PR_RESPONSE=$(curl -sX GET -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls\?head\=bellroy:master\&base\=stable | jq -r '.[0]') PR_NUM=$(echo "$PR_RESPONSE" | jq -r ".number") PR_ASSIGNEE=$(echo "$PR_RESPONSE" | jq -r ".assignee") COMMITS_RESPONSE=$(curl -sX GET -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUM/commits) FIRST_COMMITTER=$(curl -sX GET -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUM/commits | jq -r '. | sort_by(.commit.author.date) | .[0] | .author.login') # special case for squashed PRs created by trike-deploy e.g. gha-workflows if [[ "$FIRST_COMMITTER" == "trike-deploy" ]]; then FIRST_COMMITTER=$(echo "$COMMITS_RESPONSE" | jq -r '. | sort_by(.commit.author.date) | .[0]' | sed -En "s/.*Co-authored-by: (.*) <.*@.*>\",/\1/p") fi if [[ "$PR_ASSIGNEE" == "null" ]]; then curl -sX POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUM/assignees -d "{\"assignees\":[\"$FIRST_COMMITTER\"]}" fi - if: "github.ref == 'refs/heads/stable'" name: Push content to production run: | set -e # XXX: Gitapult cannot distinguish datasets, so we push all data to # both endpoints and allow the server to decide what to do. # Kafka Webhooks accepts all datasets at once ./gitapult run \ --git_root "$GITHUB_WORKSPACE" \ --authorization_token "$KW_PRODUCTION_API_KEY" \ --changeset_url "$KW_PRODUCTION_BASE_URL/gitapult/configuration/records" \ --revision_url "$KW_PRODUCTION_BASE_URL/gitapult/configuration/revision" \ --api_key \ --compress \ --max-payload-bytes 3000000 # XXX: V3 doesn't care about rendering data, but it is too large to send. # As at 2024-02-14 gitapult does not support selecting which data to send. git -C "$GIT_REPOSITORY_PATH" rm feeds/rendering_data/.gitapult.json ./gitapult run \ --git_root "$GITHUB_WORKSPACE" \ --authorization_token "$SF_PRODUCTION_API_KEY" \ --changeset_url "$SF_PRODUCTION_BASE_URL/api/v1/configuration/shipping" \ --revision_url "$SF_PRODUCTION_BASE_URL/api/v1/configuration/shipping/revisions" && \ git -C "$GIT_REPOSITORY_PATH" restore --staged feeds/rendering_data/.gitapult.json git -C "$GIT_REPOSITORY_PATH" restore feeds/rendering_data/.gitapult.json - if: "success() && github.ref == 'refs/heads/stable'" name: Tag published production content run: | git tag "${{ join(steps.current-time.outputs.*, '\n') }}_production" && git push --tags - if: "github.ref == 'refs/heads/master'" name: Set success message variable for staging run: | echo "SUCCESS_MESSAGE=:tada: \nA PR has been opened against the stable branch: ${{ env.PR_URL }}" >> $GITHUB_ENV echo "SUCCESS_MESSAGE_BODY=https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks\n\n*PR for Production:* ${{ env.PR_URL }}" >> $GITHUB_ENV - if: "github.ref == 'refs/heads/stable'" name: Set success message variable for production run: | echo "SUCCESS_MESSAGE=:tada:" >> $GITHUB_ENV echo "SUCCESS_MESSAGE_BODY=https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks" >> $GITHUB_ENV - env: SLACK_BOT_TOKEN: "${{ secrets.BELLROY_SLACK_TOKEN }}" id: slack-deploy-success if: "success() && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/master')" name: Post to Slack if published successfully uses: "slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e" with: channel-id: "${{ env.SLACK_CHANNEL_ID }}" payload: | { "text": ":loudspeaker: *${{ github.actor }}* has deployed *${{ env.SYSTEM_NAME }}* to *${{ env.DESTINATION }}* from *${{ steps.extract_branch.outputs.branch }}* ${{ env.SUCCESS_MESSAGE }}", "attachments": [ { "fallback": "Deployment summary", "color": "00ff00", "fields": [ { "title": "What was deployed", "value": ${{ toJSON(env.COMMIT_CHANGES) }}, "short": false }, { "title": "Status", "short": true, "value": "Deployed" }, { "title": "Output", "short": false, "value": "${{ env.SUCCESS_MESSAGE_BODY }}" } ] } ] } update-ts: "${{ steps.slack-deploy.outputs.ts }}" - env: SLACK_BOT_TOKEN: "${{ secrets.BELLROY_SLACK_TOKEN }}" id: slack-deploy-failed if: "failure() && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/master')" name: Post to Slack if build/deploy fails uses: "slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e" with: channel-id: "${{ env.SLACK_CHANNEL_ID }}" payload: | { "text": ":loudspeaker: *BUILD/DEPLOY FAILURE* of *${{ env.SYSTEM_NAME }}* to *${{ env.DESTINATION }}*", "attachments": [ { "fallback": "Deployment summary", "color": "ff0000", "fields": [ { "title": "What was being deployed", "value": ${{ toJSON(env.COMMIT_CHANGES) }}, "short": false }, { "title": "Status", "short": true, "value": "Failed" }, { "title": "Who broke it", "value": "${{ github.actor }}" }, { "title": "Output", "short": false, "value": "https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks" } ] } ] } update-ts: "${{ steps.slack-deploy.outputs.ts }}" - if: "always() && env.PR_NUMBER != 0" name: Add comment to PR run: "gh pr comment ${{ env.PR_NUMBER }} --body-file /tmp/pr-comment.txt || true" working-directory: "${{ env.GITHUB_WORKSPACE }}" validateContent: runs-on: ubuntu-20.04 steps: - id: checkout_branch name: checkout branch uses: "bellroy/gha-workflows/composite/checkout@master" with: fetch-depth: "1" path: "${{ env.GITHUB_WORKSPACE }}" token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" - id: extract_branch name: Extract branch name run: | echo "branch=${GITHUB_REF#refs/heads/}" >>$GITHUB_OUTPUT shell: bash - name: Install and setup nix uses: "bellroy/gha-workflows/composite/install-nix@master" with: bellroy-nix-cache-access: none - id: fetch_gitapult name: Fetch gitapult uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: gitapult tool-version: latest - id: fetch_powerful-owl name: Fetch powerful-owl uses: "bellroy/gha-workflows/composite/get-tool@master" with: token: "${{ secrets.BELLROY_DEPLOY_USER_TOKEN }}" tool-name: powerful-owl tool-version: latest - name: Get Pull Request number run: | echo "PR_NUMBER=$(gh pr view --json number -q .number)" >> $GITHUB_ENV working-directory: "${{ env.GITHUB_WORKSPACE }}" - name: Ensure tmp directory exists run: mkdir -p tmp working-directory: "${{ env.GITHUB_WORKSPACE }}" - name: Validate with gitapult run: | ./gitapult validate --git_root "$GITHUB_WORKSPACE" - name: Validate content with powerful-owl run: | for CONTENT_DIR in feeds products do if [[ "$PR_NUMBER" ]] then ./powerful-owl validate --markdown --content_path "$GITHUB_WORKSPACE/$CONTENT_DIR" &>>/tmp/pr-comment.txt else ./powerful-owl validate --content_path "$GITHUB_WORKSPACE/$CONTENT_DIR" fi done - if: "always() && env.PR_NUMBER != 0" name: Add comment to PR run: "gh pr comment ${{ env.PR_NUMBER }} --body-file /tmp/pr-comment.txt || true" working-directory: "${{ env.GITHUB_WORKSPACE }}" - if: "failure() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/stable')" name: Post to slack if build fails uses: "bellroy/gha-workflows/composite/slack-update@master" with: branch: "${{ steps.checkout_branch.outputs.branch }}" channel-id: "${{ env.SLACK_CHANNEL_ID }}" message-type: build-fail show-authors: "true" slack-bot-token: "${{ secrets.BELLROY_SLACK_TOKEN }}" timeout-minutes: 30 name: Publish on: push: branches-ignore: - "refs/tags/*_staging" - "refs/tags/*_production"