diff --git a/.github/workflows/check-updates.yml b/.github/workflows/check-updates.yml index 697bfa4..380c121 100644 --- a/.github/workflows/check-updates.yml +++ b/.github/workflows/check-updates.yml @@ -502,6 +502,17 @@ jobs: STATUS_DIR=".status" [[ -d "$STATUS_DIR" ]] || exit 0 + # gh issue list fails in a repository with Issues turned off. A + # fork like that gets a notice, and any other failure of the + # list still fails the step. + if grep -qsE '^(check|update)_failed:' "$STATUS_DIR"/*; then + has_issues=$(gh api "repos/$GITHUB_REPOSITORY" --jq .has_issues) + if [[ "$has_issues" == "false" ]]; then + echo "::notice::Issues are disabled in $GITHUB_REPOSITORY, so failed packages get no issue" + exit 0 + fi + fi + for status_file in "$STATUS_DIR"/*; do [[ -f "$status_file" ]] || continue pkg_name=$(basename "$status_file") diff --git a/docs/SETUP.md b/docs/SETUP.md index 8d68954..a2f442d 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -28,14 +28,14 @@ sudo pacman -S --needed git openssh go-yq curl pacman-contrib namcap github-cli ### Required 1. **Enable GitHub Actions**: open the Actions tab of your fork and enable workflows. GitHub disables Actions on forks by default. -2. **Enable the "Check AUR Package Updates" workflow**: open it in the Actions tab and click "Enable workflow". A fork needs this for every scheduled workflow. -3. **Enable Issues**: Settings > General > Features > Issues. Failures are reported as issues. +2. **Enable the "Check AUR Package Updates" workflow**: open it in the Actions tab and click "Enable workflow". A fork needs this for every scheduled workflow. GitHub also disables a scheduled workflow of a public repository after 60 days without activity in it. The workflow commits only when a status or a version changes, so a fork whose packages stay the same that long loses its schedule and has to enable the workflow again. +3. **Enable Issues**: Settings > General > Features > Issues. Failures are reported as issues. With Issues off, a run prints a notice instead and opens none. 4. **Run setup**: `./scripts/setup.sh` configures identity, SSH, GPG and GitHub Secrets, as described below. ### Recommended - **Enable Dependabot version updates**: Settings > Advanced Security, then Enable next to "Dependabot version updates". GitHub leaves them off on forks. Dependabot then opens pull requests for new action versions and for the digest of the Arch image the workflows run in. -- **Merge Arch image updates automatically** (optional): Settings > Secrets and variables > Actions > Variables > New repository variable, with the name `CI_IMAGE_AUTO_MERGE` and the value `true`. A new image then reaches the jobs with the secrets after the tests and without a review, see [WORKFLOW.md](WORKFLOW.md#63-ci-image-updates). +- **Merge Arch image updates automatically** (optional): Settings > Secrets and variables > Actions > Variables > New repository variable, with the name `CI_IMAGE_AUTO_MERGE` and the value `true`. A new image then reaches the jobs with the secrets after the tests and without a review, see [WORKFLOW.md](WORKFLOW.md#63-ci-image-updates). The merge is a squash merge, so Settings > General > Pull Requests has to allow squash merging. - Set repository topics if your fork is public. ### Badges diff --git a/docs/WORKFLOW.md b/docs/WORKFLOW.md index d1dd129..853b95a 100644 --- a/docs/WORKFLOW.md +++ b/docs/WORKFLOW.md @@ -776,7 +776,9 @@ The message is `chore: update package versions [skip ci]`. `[skip ci]` keeps the ### 5.6 Failure issues -The step runs with `if: always()`. For every `.status/` entry with `check_failed:` or `update_failed:`, it: +The step runs with `if: always()`. When a package failed, it first reads `has_issues` of the repository. `gh issue list` fails in a repository with Issues turned off, so when GitHub answers `false`, the step prints a notice and opens no issue. Any other answer goes on, and a failure to read the answer or to list the issues fails the step. + +For every `.status/` entry with `check_failed:` or `update_failed:`, the step: 1. Creates the `auto-update` label when it is missing. 2. Skips the package when an open `auto-update` issue already has the title `❌ : check failed` or `❌ : update failed`, so a package never gets a second issue while one is open. The step compares the titles of up to 1000 open issues and uses no search, because a search splits `foo-bar` into words and finds the issue of `foo-bar` for `foo`. diff --git a/tests/workflows.bats b/tests/workflows.bats index 8c39dc0..61fc051 100644 --- a/tests/workflows.bats +++ b/tests/workflows.bats @@ -384,7 +384,8 @@ EOF # Runs the issue step of publish in a workspace with the statuses given as # name=status pairs. gh lists the titles in $GH_TITLES, one per line, as # every open issue whatever --search asks for, the first 30 unless --limit -# says otherwise, and logs every call to $GH_LOG. +# says otherwise, answers has_issues with $GH_HAS_ISSUES (true by default) +# or fails it when $GH_API_FAIL is set, and logs every call to $GH_LOG. run_issue_step() { local ws="$BATS_TEST_TMPDIR/ws" bin="$BATS_TEST_TMPDIR/bin" pair mkdir -p "$ws/.status" "$bin" @@ -394,6 +395,11 @@ run_issue_step() { cat >"$bin/gh" <<'EOF' #!/usr/bin/env bash printf '%s\n' "$*" >>"$GH_LOG" +if [[ "$*" == "api repos/$GITHUB_REPOSITORY --jq .has_issues" ]]; then + [[ -z "${GH_API_FAIL:-}" ]] || exit 1 + echo "${GH_HAS_ISSUES:-true}" + exit 0 +fi [[ "$1 $2" == "issue list" ]] || exit 0 [[ -z "${GH_FAIL:-}" ]] || exit 1 limit=30 jq_expr="" @@ -417,7 +423,9 @@ EOF : >"$GH_LOG" step_run publish "Create issues for failed packages" >"$BATS_TEST_TMPDIR/step.sh" run env -C "$ws" PATH="$bin:$PATH" GH_LOG="$GH_LOG" GH_TITLES="${GH_TITLES:-}" \ - GH_FAIL="${GH_FAIL:-}" RUN_URL=https://example.invalid/run sh -e "$BATS_TEST_TMPDIR/step.sh" + GH_FAIL="${GH_FAIL:-}" GH_HAS_ISSUES="${GH_HAS_ISSUES:-}" GH_API_FAIL="${GH_API_FAIL:-}" \ + GITHUB_REPOSITORY=owner/fork \ + RUN_URL=https://example.invalid/run sh -e "$BATS_TEST_TMPDIR/step.sh" } @test "check-updates: an open issue of another package holds back no issue" { @@ -448,6 +456,34 @@ EOF [ "$output" = "0" ] } +# gh issue list exits 1 in a repository with Issues turned off +@test "check-updates: the issue step gives a notice when Issues are disabled" { + GH_HAS_ISSUES=false GH_FAIL=1 run_issue_step foo="update_failed: boom" + [ "$status" -eq 0 ] + [[ "$output" == *"::notice::Issues are disabled in owner/fork"* ]] + run grep -c '^issue ' "$GH_LOG" + [ "$output" = "0" ] +} + +@test "check-updates: the issue step skips issues only when GitHub says Issues are off" { + GH_HAS_ISSUES=null run_issue_step foo="update_failed: boom" + [ "$status" -eq 0 ] + grep -q '^issue create --title ❌ foo: update failed ' "$GH_LOG" +} + +@test "check-updates: the issue step fails when it cannot read whether Issues are on" { + GH_API_FAIL=1 run_issue_step foo="update_failed: boom" + [ "$status" -ne 0 ] + run grep -c '^issue ' "$GH_LOG" + [ "$output" = "0" ] +} + +@test "check-updates: the issue step asks GitHub nothing when no package failed" { + run_issue_step foo=up_to_date bar="new_version: 2.0.0" + [ "$status" -eq 0 ] + [ ! -s "$GH_LOG" ] +} + @test "check-updates: verify runs as builder and hands over as prepare does" { run step_run verify "Verify checksums" [[ "$output" == *"sudo -u builder ./scripts/check-all.sh --verify handoff"* ]]