From 1ca2d1f8bea6f40066229d81b80aca4dbb5cc204 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sun, 25 Feb 2024 17:38:49 +0100 Subject: [PATCH] ci: Refactor get_cirrusci_freebsd script to GitHub action This should make it more reliable and also easier to re-use, if we need to. Resolves #2555 --- .cirrus.yml | 11 +- .../actions/artifact-from-cirrus/action.yaml | 114 ++++++++++++++++++ .github/get_cirrusci_freebsd | 61 ---------- .github/workflows/build.yaml | 16 +-- nix/tools/style.nix | 5 - 5 files changed, 121 insertions(+), 86 deletions(-) create mode 100644 .github/actions/artifact-from-cirrus/action.yaml delete mode 100755 .github/get_cirrusci_freebsd diff --git a/.cirrus.yml b/.cirrus.yml index f81457e18..b07545ae6 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,23 +2,16 @@ freebsd_instance: image_family: freebsd-14-0 build_task: + # Don't change this name without adjusting .github/workflows/build.yaml name: Build FreeBSD (Stack) install_script: pkg install -y postgresql16-client hs-stack git - # This also includes nix and cabal related files, because the - # Github Actions build workflow will run on those and the - # "Fetch from FreeBSD" job should not fail. only_if: | $CIRRUS_TAG != '' || $CIRRUS_BRANCH == 'main' || $CIRRUS_BRANCH =~ 'v*' || changesInclude( '.github/workflows/build.yaml', - '.github/actions/setup-nix/**', - '.github/scripts/**', - '.github/*', - '*.nix', - 'nix/**', + '.github/actions/artifact-from-cirrus/**', '.cirrus.yml', - 'cabal.project*', 'postgrest.cabal', 'stack.yaml*', '**.hs' diff --git a/.github/actions/artifact-from-cirrus/action.yaml b/.github/actions/artifact-from-cirrus/action.yaml new file mode 100644 index 000000000..ac9fc8980 --- /dev/null +++ b/.github/actions/artifact-from-cirrus/action.yaml @@ -0,0 +1,114 @@ +name: Artifact from Cirrus + +description: Waits for a specific Cirrus CI run to complete, then downloads the artifact and uploads it to the current workflow. This will silently succeed if Cirrus CI did not schedule a task within 2 minutes. + +inputs: + download: + description: Name of Artifact to download from Cirrus CI + required: true + task: + description: Name of Cirrus Task + required: true + token: + description: GitHub Token + required: true + upload: + description: Name of Artifact to upload on GitHub Actions + required: true + +runs: + using: composite + steps: + - shell: bash + run: echo "GH_TOKEN=${{ inputs.token }}" >> "$GITHUB_ENV" + - name: Wait for Check Suite to be created + id: check-suite + env: + # GITHUB_SHA does weird things for pull request, so we roll our own: + COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} + shell: bash + run: | + get_check_runs_url() { + gh api "repos/{owner}/{repo}/commits/${COMMIT}/check-suites" \ + | jq -r '.check_suites[] | select(.app.slug == "cirrus-ci") | .check_runs_url' + } + for _ in $(seq 1 12); do + check_runs_url="$(get_check_runs_url)" + if [ -z "$check_runs_url" ]; then + echo "Cirrus CI task has not started, yet. Waiting..." + sleep 10 + else + echo "check_suite_found=1" >> "$GITHUB_OUTPUT" + echo "check_runs_url=$check_runs_url" >> "$GITHUB_OUTPUT" + exit 0 + fi + done + >&2 echo "Cirrus CI check suite not found. Is Cirrus CI enabled for this repo?" + echo "check_suite_found=0" >> "$GITHUB_OUTPUT" + - name: Find task by name + id: find-task + if: steps.check-suite.outputs.check_suite_found + shell: bash + run: | + get_number_of_tasks() { + gh api "${{ steps.check-suite.outputs.check_runs_url }}" \ + | jq -r '.check_runs | map(select(.name == "${{ inputs.task }}")) | length' + } + tasks="$(get_number_of_tasks)" + case "$tasks" in + 0) + echo "Task not found, assuming it's skipped intentionally..." + exit 0 + ;; + 1) + echo "task_found=1" >> "$GITHUB_OUTPUT" + exit 0 + ;; + *) + >&2 echo "More than 1 task with the same name found. Don't know what to do..." + exit 1 + ;; + esac + - name: Wait for Cirrus CI to complete task + if: steps.find-task.outputs.task_found + shell: bash + run: | + get_conclusion() { + gh api "${{ steps.check-suite.outputs.check_runs_url }}" \ + | jq -r '.check_runs[] | select(.name == "${{ inputs.task }}" and .status == "completed") | .conclusion' + } + while true; do + conclusion="$(get_conclusion)" + if [ -z "$conclusion" ]; then + echo "Cirrus CI task has not completed, yet. Waiting..." + sleep 30 + else + if [ "$conclusion" == "success" ]; then + break + else + exit 1 + fi + fi + done + - name: Download artifact from Cirrus CI + if: steps.find-task.outputs.task_found + id: download + shell: bash + run: | + get_external_id() { + gh api "${{ steps.check-suite.outputs.check_runs_url }}" \ + | jq -er '.check_runs[] | select(.name == "${{ inputs.task }}") | .external_id' + } + archive="$(mktemp)" + artifacts="$(mktemp -d)" + curl --no-progress-meter --fail -o "${archive}" \ + "https://api.cirrus-ci.com/v1/artifact/task/$(get_external_id)/${{ inputs.download }}.zip" + unzip "${archive}" -d "${artifacts}" + echo "artifacts=${artifacts}" >> "$GITHUB_OUTPUT" + - name: Save artifact to GitHub Actions + if: steps.find-task.outputs.task_found + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: ${{ inputs.upload }} + path: ${{ steps.download.outputs.artifacts }} + if-no-files-found: error diff --git a/.github/get_cirrusci_freebsd b/.github/get_cirrusci_freebsd deleted file mode 100755 index 3be837011..000000000 --- a/.github/get_cirrusci_freebsd +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Get the FreeBSD PostgREST executable built by CirrusCI for the given GITHUB_COMMIT in GITHUB_REPOSITORY - -# We use the GitHub API for 'check suites' to find the corresponding CirrusCI job, see: -# https://docs.github.com/en/rest/reference/checks#list-check-suites-for-a-git-reference - -cirrus_artifact_name=bin -gh_auth_header="Authorization: Bearer $GITHUB_TOKEN" -gh_accept_header="Accept: application/vnd.github.v3+json" - -get_gh_check_runs_url() { - gh_checks_list_url="https://api.github.com/repos/$GITHUB_REPOSITORY/commits/$GITHUB_COMMIT/check-suites" - >&2 echo "Getting list of check-suites from $gh_checks_list_url ..." - curl -s --fail -H "$gh_auth_header" -H "$gh_accept_header" "$gh_checks_list_url" \ - | jq -r '.check_suites[] | select(.app.slug == "cirrus-ci") | .check_runs_url' -} - -wait_for_cirrusci() { - >&2 echo "Waiting to CirrusCI run to complete (two hours maximum)..." - for _ in $(seq 1 120); do - gh_check_runs_url="$(get_gh_check_runs_url)" - if [ -z "$gh_check_runs_url" ]; then - echo "CirrusCI task has not started, yet. Waiting..." - else - echo "Checking for CirrusCI task status at $gh_check_runs_url ..." - status=$(curl -s --fail -H "$gh_auth_header" "$gh_check_runs_url" | jq -r '.check_runs[] | .status') - if [ "$status" == "completed" ]; then - break - else - echo "CirrusCI task is still $status, waiting..." - fi - fi - sleep 60 - done -} - -# The CirrusCI taskid can change if a new check run is started for the same commit, -# e.g. when pushing both a branch and tag. We make sure that we have the very -# latest taskid by re-loading the 'gh_check_runs_url' and the 'check run' itself. -get_cirrus_taskid() { - gh_check_runs_url="$(get_gh_check_runs_url)" - >&2 echo "Getting the CirrusCI task id from $gh_check_runs_url ..." - curl --fail -H "$gh_auth_header" -H "$gh_accept_header" "$gh_check_runs_url" \ - | jq -r '.check_runs[] | .external_id' -} - -download_artifact() { - cirrus_task_id="$(get_cirrus_taskid)" - cirrus_artifact_url="https://api.cirrus-ci.com/v1/artifact/task/$cirrus_task_id/$cirrus_artifact_name.zip" - >&2 echo "Attemping to download the CirrusCI artifact from $cirrus_artifact_url ..." - curl --fail "$cirrus_artifact_url" -o freebsd.zip -} - -wait_for_cirrusci -download_artifact - -echo "Unpacking executable..." -unzip freebsd.zip -d . -rm -rf freebsd.zip diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3996d2fdd..b343d5d51 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -144,18 +144,12 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - name: Get FreeBSD executable from CirrusCI - env: - # GITHUB_SHA does weird things for pull request, so we roll our own: - GITHUB_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: .github/get_cirrusci_freebsd - - name: Save executable as artifact - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: ./.github/actions/artifact-from-cirrus with: - name: postgrest-freebsd-x64 - path: postgrest - if-no-files-found: error + token: ${{ github.token }} + task: Build FreeBSD (Stack) + download: bin + upload: postgrest-freebsd-x64 cabal: diff --git a/nix/tools/style.nix b/nix/tools/style.nix index 30ce39442..4bc48c721 100644 --- a/nix/tools/style.nix +++ b/nix/tools/style.nix @@ -7,7 +7,6 @@ , hlint , hsie , nixpkgs-fmt -, shellcheck , silver-searcher , statix , stylish-haskell @@ -58,10 +57,6 @@ let workingDir = "/"; } '' - echo "Linting bash scripts..." - ${shellcheck}/bin/shellcheck \ - .github/get_cirrusci_freebsd \ - echo "Linting workflows..." ${actionlint}/bin/actionlint