From 3a0620a40c2b1d22ecd7ff65e8ab0c7a604d5e5f Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Wed, 30 Nov 2022 20:51:52 -0800 Subject: [PATCH] tools: Reimplement CI failure script without using CircleCI endpoint. Using curl to POST to the CircleCI workflow endpoint on CZO: - Doesn't work on zulip/zulip@main (CZO runs a revert) - Sets a bad example for other orgs - Robs us of an opportunity to dogfood our own zulip/github-actions-zulip Refactor the Actions workflows in this repo to report failure states using the Zulip Action, and reimplement the related helper scripts in Python, since they'd previously mostly shelled out to Python anyway. --- .github/workflows/production-suite.yml | 68 +++++++++++++++++++------- .github/workflows/zulip-ci.yml | 21 ++++++-- tools/ci/generate-failure-message | 22 +++++++++ tools/ci/production-build | 2 +- tools/ci/send-failure-message | 12 ----- 5 files changed, 90 insertions(+), 35 deletions(-) create mode 100755 tools/ci/generate-failure-message delete mode 100755 tools/ci/send-failure-message diff --git a/.github/workflows/production-suite.yml b/.github/workflows/production-suite.yml index 94d0189bd4..be99330bdb 100644 --- a/.github/workflows/production-suite.yml +++ b/.github/workflows/production-suite.yml @@ -47,6 +47,7 @@ jobs: # the top explain how to build and upload these images. # Ubuntu 20.04 ships with Python 3.8.10. container: zulip/ci:focal + steps: - name: Add required permissions run: | @@ -103,11 +104,22 @@ jobs: path: /tmp/production-build retention-days: 14 - - name: Report status - if: failure() - env: - ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }} - run: tools/ci/send-failure-message + - name: Generate failure report string + id: failure_report_string + if: ${{ failure() && github.repository == 'zulip/zulip' }} + run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT + + - name: Report status to CZO + if: ${{ failure() && github.repository == 'zulip/zulip' }} + uses: zulip/github-actions-zulip/send-message@v1 + with: + api-key: ${{ secrets.ZULIP_BOT_KEY }} + email: "github-actions-bot@chat.zulip.org" + organization-url: "https://chat.zulip.org" + to: "automated testing" + topic: ${{ steps.failure_report_string.outputs.topic }} + type: "stream" + content: ${{ steps.failure_report_string.outputs.content }} production_install: # This job installs the server release tarball built above on a @@ -160,7 +172,7 @@ jobs: chmod +x /tmp/production-pgroonga chmod +x /tmp/production-install chmod +x /tmp/production-verify - chmod +x /tmp/send-failure-message + chmod +x /tmp/generate-failure-message - name: Create cache directories run: | @@ -197,11 +209,22 @@ jobs: if: ${{ matrix.os == 'focal' }} run: sudo /tmp/production-verify ${{ matrix.extra-args }} - - name: Report status - if: failure() - env: - ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }} - run: /tmp/send-failure-message + - name: Generate failure report string + id: failure_report_string + if: ${{ failure() && github.repository == 'zulip/zulip' }} + run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT + + - name: Report status to CZO + if: ${{ failure() && github.repository == 'zulip/zulip' }} + uses: zulip/github-actions-zulip/send-message@v1 + with: + api-key: ${{ secrets.ZULIP_BOT_KEY }} + email: "github-actions-bot@chat.zulip.org" + organization-url: "https://chat.zulip.org" + to: "automated testing" + topic: ${{ steps.failure_report_string.outputs.topic }} + type: "stream" + content: ${{ steps.failure_report_string.outputs.content }} production_upgrade: # The production upgrade job starts with a container with a @@ -254,7 +277,7 @@ jobs: # of the tarball uploaded by the upload artifact fix those. chmod +x /tmp/production-upgrade chmod +x /tmp/production-verify - chmod +x /tmp/send-failure-message + chmod +x /tmp/generate-failure-message - name: Create cache directories run: | @@ -271,8 +294,19 @@ jobs: # - name: Verify install # run: sudo /tmp/production-verify - - name: Report status - if: failure() - env: - ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }} - run: /tmp/send-failure-message + - name: Generate failure report string + id: failure_report_string + if: ${{ failure() && github.repository == 'zulip/zulip' }} + run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT + + - name: Report status to CZO + if: ${{ failure() && github.repository == 'zulip/zulip' }} + uses: zulip/github-actions-zulip/send-message@v1 + with: + api-key: ${{ secrets.ZULIP_BOT_KEY }} + email: "github-actions-bot@chat.zulip.org" + organization-url: "https://chat.zulip.org" + to: "automated testing" + topic: ${{ steps.failure_report_string.outputs.topic }} + type: "stream" + content: ${{ steps.failure_report_string.outputs.content }} diff --git a/.github/workflows/zulip-ci.yml b/.github/workflows/zulip-ci.yml index fcc0d1b295..5f234d0873 100644 --- a/.github/workflows/zulip-ci.yml +++ b/.github/workflows/zulip-ci.yml @@ -233,8 +233,19 @@ jobs: - name: Check development database build run: ./tools/ci/setup-backend - - name: Report status - if: failure() - env: - ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }} - run: tools/ci/send-failure-message + - name: Generate failure report string + id: failure_report_string + if: ${{ failure() && github.repository == 'zulip/zulip' }} + run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT + + - name: Report status to CZO + if: ${{ failure() && github.repository == 'zulip/zulip' }} + uses: zulip/github-actions-zulip/send-message@v1 + with: + api-key: ${{ secrets.ZULIP_BOT_KEY }} + email: "github-actions-bot@chat.zulip.org" + organization-url: "https://chat.zulip.org" + to: "automated testing" + topic: ${{ steps.failure_report_string.outputs.topic }} + type: "stream" + content: ${{ steps.failure_report_string.outputs.content }} diff --git a/tools/ci/generate-failure-message b/tools/ci/generate-failure-message new file mode 100755 index 0000000000..1686c2f692 --- /dev/null +++ b/tools/ci/generate-failure-message @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import os + + +def get_build_url_from_environment() -> str: + server = os.environ["GITHUB_SERVER_URL"] + repo = os.environ["GITHUB_REPOSITORY"] + run_id = os.environ["GITHUB_RUN_ID"] + return f"{server}/{repo}/actions/runs/{run_id}" + + +if __name__ == "__main__": + branch = os.environ.get("GITHUB_REF", "unknown branch").split("/")[-1] + topic = f"{branch} failing" + build_url = get_build_url_from_environment() + github_actor = os.environ.get("GITHUB_ACTOR", "unknown user") + content = f"[Build]({build_url}) triggered by {github_actor} on branch `{branch}` has failed." + + # Output in the key-value pair format GitHub Actions outputs are expected + # to be in. + print(f"topic={topic}\ncontent={content}") diff --git a/tools/ci/production-build b/tools/ci/production-build index 130e55b2b9..bedfec147e 100755 --- a/tools/ci/production-build +++ b/tools/ci/production-build @@ -39,7 +39,7 @@ cp -a \ tools/ci/production-upgrade \ tools/ci/production-pgroonga \ tools/ci/production-upgrade-pg \ - tools/ci/send-failure-message \ + tools/ci/generate-failure-message \ package.json yarn.lock \ /tmp/production-build diff --git a/tools/ci/send-failure-message b/tools/ci/send-failure-message deleted file mode 100755 index 5aa2274b43..0000000000 --- a/tools/ci/send-failure-message +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -if [[ "$ZULIP_BOT_KEY" != "" && "$GITHUB_REPOSITORY" == "zulip/zulip" ]]; then - BRANCH="$(python3 -c 'import sys; print(sys.argv[1].split("/")[-1])' "$GITHUB_REF")" - URI_ESCAPED_TOPIC="$(python3 -c 'import sys; import urllib.parse; print(urllib.parse.quote(sys.argv[1]))' "$BRANCH failing")" - curl -fL -H "Content-Type: application/json" \ - -X POST -i 'https://chat.zulip.org/api/v1/external/circleci?api_key='"$ZULIP_BOT_KEY"'&stream=automated%20testing&topic='"$URI_ESCAPED_TOPIC" \ - -d '{"payload": { "branch": "'"$BRANCH"'", "reponame": "'"$GITHUB_REPOSITORY"'", "status": "failed", "build_url": "'"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"'", "username": "'"$GITHUB_ACTOR"'"}}' -fi