From 5834179be6cead008542effa7381025d18ebaacf Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 20 Oct 2026 16:48:47 +0000 Subject: [PATCH] ci: start app tests only by hand (#7777) --- .github/workflows/desktop-linux.yml | 24 ++++-------------------- .github/workflows/ios-sim.yml | 21 +++------------------ scripts/ci/README.md | 28 ++++++++++++++-------------- scripts/ci/desktop-linux/README.md | 2 +- scripts/ci/ios-sim/README.md | 4 ++-- 5 files changed, 24 insertions(+), 55 deletions(-) diff --git a/.github/workflows/desktop-linux.yml b/.github/workflows/desktop-linux.yml index d1186018aa..82725791f5 100644 --- a/.github/workflows/desktop-linux.yml +++ b/.github/workflows/desktop-linux.yml @@ -1,14 +1,6 @@ name: desktop-linux -# A push runs the jobs only when its head commit's message asks for them: see scripts/ci/desktop-linux/README.md. on: - push: - branches: - # only f/ branches, so other branches' pull requests don't list skipped runs; elsewhere, run it by hand - - "f/*" - # a squash merge's message lists the merged commits' subjects, with their tags - - "!master" - - "!stable" workflow_dispatch: inputs: claude: @@ -29,8 +21,7 @@ permissions: actions: read concurrency: - # a push that asks for no run must not cancel one that does - group: desktop-linux-${{ github.ref }}-${{ (github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[app-ci]') || contains(github.event.head_commit.message, '[app-ci:desktop]') || contains(github.event.head_commit.message, '[claude-test]') || contains(github.event.head_commit.message, '[claude-test:desktop]')) && 'requested' || github.run_id }} + group: desktop-linux-${{ github.ref }} cancel-in-progress: true env: @@ -43,13 +34,6 @@ env: jobs: plan: name: choose jobs, find earlier builds - # the concurrency group repeats this test, as it can't read job outputs - if: >- - github.event_name == 'workflow_dispatch' || - contains(github.event.head_commit.message, '[app-ci]') || - contains(github.event.head_commit.message, '[app-ci:desktop]') || - contains(github.event.head_commit.message, '[claude-test]') || - contains(github.event.head_commit.message, '[claude-test:desktop]') runs-on: ubuntu-24.04 timeout-minutes: 10 outputs: @@ -65,9 +49,9 @@ jobs: - name: Choose jobs id: jobs env: - CLAUDE: ${{ inputs.claude || contains(github.event.head_commit.message, '[claude-test]') || contains(github.event.head_commit.message, '[claude-test:desktop]') }} - BACKEND: ${{ inputs.backend || contains(github.event.head_commit.message, '[ci-backend]') }} - RELEASE: ${{ inputs.release || contains(github.event.head_commit.message, '[ci-release]') }} + CLAUDE: ${{ inputs.claude }} + BACKEND: ${{ inputs.backend }} + RELEASE: ${{ inputs.release }} run: | echo "claude=$CLAUDE" | tee -a "$GITHUB_OUTPUT" echo "backend=$BACKEND" | tee -a "$GITHUB_OUTPUT" diff --git a/.github/workflows/ios-sim.yml b/.github/workflows/ios-sim.yml index a275bb82d6..08502674d9 100644 --- a/.github/workflows/ios-sim.yml +++ b/.github/workflows/ios-sim.yml @@ -1,13 +1,6 @@ name: ios-sim on: - push: - branches: - # only f/ branches, so other branches' pull requests don't list skipped runs; elsewhere, run it by hand - - 'f/*' - # a squash merge's message lists the merged commits' subjects, with their tags - - '!master' - - '!stable' workflow_dispatch: inputs: claude: @@ -24,8 +17,7 @@ permissions: actions: read concurrency: - # a push that asks for no run must not cancel one that does - group: ios-sim-${{ github.ref }}-${{ (github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[app-ci]') || contains(github.event.head_commit.message, '[app-ci:ios]') || contains(github.event.head_commit.message, '[claude-test]') || contains(github.event.head_commit.message, '[claude-test:ios]')) && 'requested' || github.run_id }} + group: ios-sim-${{ github.ref }} cancel-in-progress: true env: @@ -41,13 +33,6 @@ env: jobs: plan: name: choose jobs, find earlier builds - # the concurrency group repeats this test, as it can't read job outputs - if: >- - github.event_name == 'workflow_dispatch' || - contains(github.event.head_commit.message, '[app-ci]') || - contains(github.event.head_commit.message, '[app-ci:ios]') || - contains(github.event.head_commit.message, '[claude-test]') || - contains(github.event.head_commit.message, '[claude-test:ios]') runs-on: ubuntu-24.04 timeout-minutes: 10 outputs: @@ -62,8 +47,8 @@ jobs: - name: Choose jobs id: jobs env: - CLAUDE: ${{ inputs.claude || contains(github.event.head_commit.message, '[claude-test]') || contains(github.event.head_commit.message, '[claude-test:ios]') }} - BACKEND: ${{ inputs.backend || contains(github.event.head_commit.message, '[ci-backend]') }} + CLAUDE: ${{ inputs.claude }} + BACKEND: ${{ inputs.backend }} run: | echo "claude=$CLAUDE" | tee -a "$GITHUB_OUTPUT" echo "backend=$BACKEND" | tee -a "$GITHUB_OUTPUT" diff --git a/scripts/ci/README.md b/scripts/ci/README.md index 2f5660dfc1..cb625e5254 100644 --- a/scripts/ci/README.md +++ b/scripts/ci/README.md @@ -2,26 +2,26 @@ Two workflows build the apps from a branch's own code and test them, only when asked: `ios-sim` (the iOS app in a simulator on a macOS runner) and `desktop-linux` (the desktop app on a Linux runner). Each runs a scripted smoke test and, on request, a Claude session that follows a test plan, and a test backend (relay, directory, names server, peers). Details: [iOS](ios-sim/README.md), [desktop](desktop-linux/README.md). -## Run tags +## Starting a run -Put a tag in the message of the commit you push to a branch named `f/…`. Tags combine: each workflow runs everything its tags ask for. +Pushes start nothing: a run is started by hand, on any branch, with inputs that are off by default and combine. -| Tag | iOS | Desktop | +| Input | iOS | Desktop | |---|---|---| -| `[app-ci]` | scripted test | scripted test | -| `[app-ci:ios]` | scripted test | — | -| `[app-ci:desktop]` | — | scripted test | -| `[claude-test]` | scripted test, then Claude | scripted test, then Claude | -| `[claude-test:ios]` | scripted test, then Claude | — | -| `[claude-test:desktop]` | — | scripted test, then Claude | -| `[ci-backend]`, with one of the above | also the test backend | also the test backend | -| `[ci-release]`, with one of the above | — | also the latest release's onboarding, to tell a branch's failure from the runner's | +| no input | scripted test | scripted test | +| `claude` | scripted test, then Claude | scripted test, then Claude | +| `backend` | also the test backend | also the test backend | +| `release` | — | also the latest release's onboarding, to tell a branch's failure from the runner's | -Only the pushed head commit counts, and a tag counts anywhere in its message, body included: never write one in a message unless that push should run it. A push that asks for nothing starts no job and doesn't cancel a running test; a newer requested run on the same branch cancels the older one. Tags start runs only on `f/…` branches, so pull requests from other branches don't list skipped runs; on any other branch, master and stable included, run a workflow by hand. +In the Actions tab: `ios-sim` or `desktop-linux` → Run workflow, choose the branch and tick the inputs. With the GitHub CLI, each input is a field: -## Running a workflow by hand +```sh +gh workflow run ios-sim.yml --ref +gh workflow run ios-sim.yml --ref -f claude=true +gh workflow run desktop-linux.yml --ref -f claude=true -f backend=true -f release=true +``` -Actions → `ios-sim` or `desktop-linux` → Run workflow, on any branch, with checkboxes that are off by default: `claude` (the Claude session), `backend` (the test backend) and, on desktop, `release` (the latest release's onboarding). +A newer run of a workflow on the same branch cancels the older one. ## How long a run takes diff --git a/scripts/ci/desktop-linux/README.md b/scripts/ci/desktop-linux/README.md index be0586558a..2363068a63 100644 --- a/scripts/ci/desktop-linux/README.md +++ b/scripts/ci/desktop-linux/README.md @@ -4,7 +4,7 @@ ## Running it -The workflow runs only when asked: by a run tag in a commit pushed to an `f/…` branch, or by hand from the Actions tab on any branch. [App tests on GitHub's runners](../README.md) lists the tags and inputs. +The workflow runs only when started by hand, on any branch, from the Actions tab or with `gh workflow run`: [App tests on GitHub's runners](../README.md) says how and lists the inputs. Every run builds the core library, and the backend when it's asked for, from the branch's own Haskell code. It reuses an earlier build only when the sources are unchanged, as an artifact of the same branch named after a hash of its sources (30 days): for the core `src/**`, `cabal.project`, `simplex-chat.cabal`, `PRIVACY.md` and the build scripts, for the backend `src/**`, the CLI's and the directory's sources, `cabal.project`, `simplex-chat.cabal` and its build script. So a branch that changes core and app code together tests both. The workflow saves no Actions caches, which this repository evicts within hours and shares with `build.yml`. diff --git a/scripts/ci/ios-sim/README.md b/scripts/ci/ios-sim/README.md index 2e98b029a3..f72c6cb0b2 100644 --- a/scripts/ci/ios-sim/README.md +++ b/scripts/ci/ios-sim/README.md @@ -4,7 +4,7 @@ ## Running it -The workflow runs only when asked: by a run tag in a commit pushed to an `f/…` branch, or by hand from the Actions tab on any branch. [App tests on GitHub's runners](../README.md) lists the tags and inputs. +The workflow runs only when started by hand, on any branch, from the Actions tab or with `gh workflow run`: [App tests on GitHub's runners](../README.md) says how and lists the inputs. Results: the job logs, the Claude job's summary (Claude's usage) and the artifacts `ios-sim-smoke-test` (a screenshot, a 1000-px view and an accessibility tree per step, the app log), `ios-sim-backend-logs` and `ios-sim-claude-test` (the Claude job's smoke test in `smoke-test/`, and per session: `prompt.md`, `report.md`, `shots/`, `transcript.jsonl`, `usage.json`). Read them with `gh run view --log` and `gh run download -n `. @@ -40,7 +40,7 @@ Haiku 5.5 drives the app well: the smoke plan takes a few dozen turns and cents; ## The test backend -`backend.sh start ` (with `[ci-backend]` or the `backend` input) starts, on the runner, against the preset SMP and XFTP servers: +`backend.sh start ` (with the `backend` input) starts, on the runner, against the preset SMP and XFTP servers: - a chat relay for channels, and a SimpleX Directory whose address it writes to `/directory-link`; - a CLI peer `ci_admin` that creates, registers and gets approved groups and channels with the profile JSON the app sends: `ci_group` and `ci_channel` ("ci seed"), `ci_cards`, six entries with app-size avatars made by `avatar.swift` ("ci avatar"), a long name, markdown in a description, and `cinews`, `cinews_digest`, `cinews_weekly`;