Skip to content

ci(release): nightly build against the latest master of every submodule - #1448

Merged
ErikBjare merged 5 commits into
masterfrom
ci/nightly-submodule-tips
Sep 18, 2026
Merged

ErikBjare merged 5 commits into
masterfrom
ci/nightly-submodule-tips

Conversation

@ErikBjare

Copy link
Copy Markdown
Member

A true nightly, as discussed: pull only, nothing committed, nothing published. Every submodule moved to its upstream master, then build + test — so integration breakage between the repos' masters surfaces the next morning instead of when someone bumps the bundle. Skips itself when nothing moved.

Shape (a flag on the existing build jobs, not a parallel workflow)

  • Triggers: a second cron 0 3 * * * (identified via github.event.schedule; the weekly dev-release cron is untouched), plus a workflow_dispatch input submodules: pinned|latest for on-demand runs.
  • nightly-submodules — a cheap, always-run resolver job (so needs: never short-circuits the build jobs). On the nightly cron or submodules=latest it runs git submodule update --init --recursive --remote and outputs moved plus the full sha path list (recursively, incl. nested aw-webui and media). On normal runs it outputs latest=false and does nothing else.
  • The four build jobs (research-edition-checks, build-qt, build-qt-manylinux-2-28, build-tauri) need it and, on nightly, run only when moved == true. Right after their recursive checkout they check out exactly the resolver's SHAs, so every leg builds the same tips even when they start minutes apart.
  • build-tauri additionally relocks src-tauri/Cargo.lock to the moved aw-server-rust revision (cargo update -p aw-server --precise <sha>), so Tauri genuinely builds latest and the existing check_tauri_server.py verification still passes. That step installs a Rust toolchain because the job only sets one up later; the action is idempotent.
  • preflight / create-tag are excluded from the nightly cron and from submodules=latest, so neither path can mint a dev prerelease. release-notes / release remain tag-push only.

Verified

  • YAML parses; actionlint clean for the changed regions (the 7 remaining findings are all in pre-existing scripts: preflight, manylinux, release-notes, release).
  • Resolver logic rehearsed end-to-end in a throwaway shallow clone: $displaypath under foreach --recursive, --remote --depth 1 on initialised submodules, the before/after diff producing moved=true, and the consume step fetching + checking out every SHA. It also surfaced a drifted aw-qt/media — exactly the class of thing this is for.

Companion: scripts/bump-submodules.sh (separate PR) is the human-driven counterpart that does commit.

A true nightly: pull only, nothing committed or published. Catches
integration breakage between the submodules' masters before anyone bumps
the bundle, instead of at bump time.

- new cron 0 3 * * * (the weekly dev-release cron is unchanged), plus a
  workflow_dispatch input submodules=pinned|latest for on-demand runs
- nightly-submodules: an always-run resolver job that, on the nightly cron
  or submodules=latest, moves every submodule (recursively) to its
  upstream master and reports whether anything moved relative to the
  committed pointers; skips the build entirely when nothing did
- the four build jobs need it and, on nightly, run only when something
  moved; each checks out exactly the resolver's SHAs so every leg tests
  the same tips even minutes apart
- build-tauri relocks src-tauri/Cargo.lock to the moved aw-server-rust
  revision so Tauri really builds latest and check_tauri_server.py still
  holds (installs a Rust toolchain for that step; the action is idempotent
  with the job's later setup)
- preflight/create-tag are excluded from the nightly cron and from
  submodules=latest, so a nightly can never mint a dev prerelease
@ErikBjare

Copy link
Copy Markdown
Member Author

@greptileai review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2bdbc87549

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

git -C "$path" fetch -q origin "$sha"
git -C "$path" checkout -q "$sha"
done
git submodule status --recursive

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move safe-directory setup before nightly Git use

For nightly or submodules=latest runs in the manylinux container, this invokes top-level Git before the following safe.directory workaround. The adjacent workflow comment documents that the mounted workspace is not trusted until that configuration runs; unlike the later version probe, git submodule status --recursive exits nonzero under dubious ownership, so this build leg aborts before testing anything. Configure the workspace immediately after checkout, ahead of this step.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 16cc23a. Nested init now runs git submodule --quiet foreach 'git submodule update --init --recursive -q' — inside each direct submodule, so the direct tips survive. In the manylinux job the step moved after "Configure git safe directory" and carries a step-scoped safe.directory=* (GIT_CONFIG_* env), since the global entry covers the workspace but not the submodule worktrees the step runs git in.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T15:21:54.475553Z 16cc23a New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 3/5

The PR is not safe to merge until nightly builds stop exposing Tauri signing credentials to unreviewed upstream submodule code.

Findings

  1. P1 Security Signing Secrets Reach Upstream Code
  2. P2 Security Mutable Toolchain Action Reference
  3. P2 Nested Submodules Remain Uninitialized
  4. P2 Normal Builds Clone Submodules Twice

Summary

This PR extends the release workflow with scheduled and manually dispatched integration builds against current recursive submodule tips.

  • Adds a resolver that records a consistent recursive set of upstream submodule revisions.
  • Gates the four build jobs on whether latest-mode submodules moved.
  • Prevents latest-mode runs from creating development releases.
  • Relocks the Tauri server dependency to the resolved Rust server revision.
  • The latest-mode path exposes signing credentials to unreviewed third-party submodule code and needs isolation before merging.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  T{Workflow trigger}
  T -->|Nightly cron or submodules=latest| R[Resolve recursive upstream tips]
  T -->|Normal push, PR, or pinned dispatch| P[Pinned mode]
  R --> M{Any revision moved?}
  M -->|No| S[Skip integration builds]
  M -->|Yes| C[Replay exact SHAs in four build jobs]
  P --> C
  C --> Q[Research Edition checks]
  C --> QT[Qt builds]
  C --> ML[Manylinux Qt build]
  C --> TA[Relock and build Tauri]
  T -->|Weekly cron or pinned dispatch| PF[Preflight and create tag]
  R -. excluded .-> PF
Loading

Reviews (1) · Last reviewed commit: "ci(release): nightly build against the l..."

Comment thread .github/workflows/release.yml Outdated
Comment on lines +308 to +311
# Move each submodule (and nested submodules) to the tip of its
# upstream default branch. awatcher is third-party but is included:
# a nightly is exactly where its drift should surface.
git submodule update --init --recursive --remote --depth 1 2>&1 | tail -20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Signing Secrets Reach Upstream Code

The nightly resolver advances the third-party awatcher submodule to an unreviewed upstream tip. The Linux Tauri jobs then execute that revision through the recursive build while exposing TAURI_SIGNING_PRIVATE_KEY and its password. A compromised upstream revision could therefore exfiltrate the signing credentials. Nightly jobs should withhold these secrets or avoid executing mutable third-party code.

How this was verified: The resolver includes awatcher, its resolved SHA is replayed into build-tauri, and the resulting submodule build executes in steps whose environment contains the Tauri signing key and password.

Comment thread .github/workflows/release.yml Outdated
# which this job only installs later — the toolchain action is idempotent.
- name: Set up Rust for the nightly relock
if: needs.nightly-submodules.outputs.latest == 'true'
uses: dtolnay/rust-toolchain@stable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security Mutable Toolchain Action Reference

The new dtolnay/rust-toolchain@stable reference is mutable, unlike the three existing uses of this action that are pinned to a commit SHA. A repointed action could modify the workspace or toolchain later consumed by secret-bearing Tauri build steps. Pin this invocation to the reviewed commit as well.

How this was verified: This is the only mutable reference to this third-party action, and it executes before Tauri build steps that expose signing credentials.

Comment thread .github/workflows/release.yml Outdated
Comment on lines +360 to +364
printf '%s\n' "$SUBMODULE_SHAS" | while read -r sha path; do
[ -n "$path" ] || continue
git -C "$path" fetch -q --depth 1 origin "$sha"
git -C "$path" checkout -q "$sha"
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Nested Submodules Remain Uninitialized

Consumers replay the resolver's recursive output onto a checkout initialized from the pinned submodule topology, using only git -C "$path" fetch and checkout. If an updated parent introduces a nested submodule, the resolver exports its new path, but that path does not exist in the consumer checkout. git -C then fails and aborts the affected nightly job. Synchronize and initialize submodules after updating parent revisions before replaying nested revisions.

Comment on lines +287 to +290
- uses: actions/checkout@v7
with:
submodules: 'recursive'
fetch-depth: 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Normal Builds Clone Submodules Twice

The resolver recursively checks out every submodule before it evaluates the LATEST guard. On ordinary pushes and pull requests, it then exits without using that checkout, while every build job waits for it through needs. This adds a complete redundant submodule checkout to every normal build. Initialize submodules only for latest-mode runs so the always-run resolver remains cheap.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@TimeToBuildBob

TimeToBuildBob commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

🤖 AI code review

Adds a nightly integration-build path to the release workflow: a second cron and a workflow_dispatch input select a 'latest' mode in which a new nightly-submodules job resolves every first-party submodule to its upstream master tip and the four build jobs check out those exact SHAs. The preflight/create-tag jobs are excluded from latest mode so no dev prerelease is minted, and build-tauri relocks its Cargo.lock to the moved aw-server-rust revision.

Not safe to merge — 1 P1 open

Confidence 3/5

ℹ️ Consensus was degraded on this run: 2 of 3 passes answered, so findings were filtered at 2-of-2 agreement rather than 2-of-3 — less filtered than usual; 2 of 3 fan-out jobs answered, so the findings above were filtered against less evidence than the threshold assumes.

⚠️ 1 of 1 changed files were not fully read. Claims that an identifier is never assigned, used, or called are discarded unless verification names only fully preloaded files. This coverage describes the bounded context preload; the diff was reviewed.

1 finding · ❌ 1 P1 · 🔒 1 security

❌ P1 high · 🔒 security.github/workflows/release.yml:320

The resolver's firstparty list is built with git submodule --quiet foreach 'echo $sm_path' | grep -vx awatcher, which only filters top-level submodules whose path is exactly awatcher. Nested submodules under a first-party parent (e.g. aw-qt/media) are included in firstparty and passed to git submodule update --remote --recursive -- $firstparty. The --remote flag moves every listed submodule to the tip of its upstream default branch, including aw-qt/media if it is a third-party repo. The comment claims awatcher is the only third-party submodule and that it is left pinned, but the filter does not protect nested third-party submodules. If any nested submodule is third-party, the nightly will execute its unreviewed code in jobs that carry signing secrets, violating the stated security boundary. The fix is to filter the full recursive path list (e.g. grep -vx 'awatcher' plus grep -v '^awatcher/') or to exclude nested submodules of awatcher explicitly.

Use `git submodule status --recursive` for before/after so nested submodule SHAs are compared, e.g. `before=$(git submodule status --recursive)` and `after=$(git submodule status --recursive)`.

How this was verified: Traced the resolver: before/after are built from git submodule foreach --recursive --quiet "$tips" (lines 313-314, 326), which prints each submodule's own HEAD and displaypath. --remote updates submodules to their upstream default branch, but the comparison only captures the parent submodule's HEAD, not the nested submodule's recorded SHA. The PR description's own rehearsal found a drifted aw-qt/media, which would not change aw-qt's HEAD.

Consensus: 2/2 passes agreed
Distinct keys: 1 (general)

Files changed (1) — the diff as I read it
  • .github/workflows/release.yml — Adds nightly cron and submodules dispatch input, a nightly-submodules resolver job, latest-submodule checkout steps in four build jobs, and preflight exclusions for latest mode.
Previous review passes
commit score findings engine when
2bdbc87549fd 4/5 1 llm 2026-09-17 12:56 UTC
16cc23a2f869 3/5 1 llm 2026-09-17 17:12 UTC

Reviewed fba29279bdd0 · openrouter/deepseek/deepseek-v4-flash-0731 · llm engine · 310s · about this reviewer

Maintainer commands

@TimeToBuildBob review (own line) — fresh review · @TimeToBuildBob fix — a worker acts on the findings. Once per comment; 👀 = received.

Comment thread .github/workflows/release.yml Outdated
# Move each submodule (and nested submodules) to the tip of its
# upstream default branch. awatcher is third-party but is included:
# a nightly is exactly where its drift should surface.
git submodule update --init --recursive --remote --depth 1 2>&1 | tail -20

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ P2 — The nightly-submodules resolver runs git submodule update --init --recursive --remote --depth 1 and then captures after=$(git submodule foreach --recursive --quiet "$tips"). The tips command is echo "$(git rev-parse HEAD) $displaypath". For a submodule whose upstream tip has not changed, git submodule update --remote leaves the working tree at the committed SHA, so before and after are equal and moved=false. However, the resolver's before is captured from the committed pointers, and the build jobs' Use latest submodule tips step checks out the resolved SHAs only when latest == 'true'. On a normal push/PR/dispatch with submodules=pinned, latest=false and the build jobs use the committed pointers — correct. The bug is that the resolver's moved comparison is done against the committed pointers, but the build jobs' if condition also requires moved == 'true' for the nightly cron. If a submodule's upstream tip moved but the resolver's git submodule update --remote fails to update it (e.g., because the submodule's remote is not configured or the default branch is not master), after equals before, moved=false, and the nightly build is skipped even though the submodule did move. This is a silent skip: the nightly integration build does not run, and the drift is not surfaced. The PR description says the resolver was rehearsed, but the failure mode of a submodule whose upstream default branch is not master (or whose remote is not origin) is not handled; git submodule update --remote uses the branch config or defaults to the remote's HEAD, and if that is not the intended upstream, the comparison is against the wrong tip.

…nit, exclude third-party awatcher

- pin dtolnay/rust-toolchain to the commit the file already uses elsewhere
- resolver job checks out without submodules; initialises them only in
  latest mode, so ordinary pushes/PRs no longer pay a recursive clone
- consumers run two passes (direct, then `submodule update --init`, then
  nested) so a parent revision that introduces a new nested submodule
  cannot make `git -C <new path>` fail
- the nightly moves only first-party submodules; awatcher (third-party)
  stays at its pinned revision so unreviewed upstream code never runs in
  jobs that carry Tauri signing secrets
@ErikBjare

Copy link
Copy Markdown
Member Author

Review findings addressed in 97742d7:

  • Mutable toolchain action reference — pinned to 3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9, the commit the file already uses at its three other call sites.
  • Normal builds clone submodules twice — the resolver now checks out without submodules and initialises them only in latest mode, so ordinary pushes/PRs pay nothing beyond a shallow checkout.
  • Nested submodules remain uninitialized — consumers now run two passes: direct submodules, then git submodule update --init --recursive (which materialises any nested submodule a moved parent newly declares), then nested paths.
  • Signing secrets reach upstream code — the nightly now moves only first-party submodules; awatcher (third-party, 2e3s/) stays at its pinned revision, so no unreviewed third-party code executes in jobs carrying TAURI_SIGNING_PRIVATE_KEY. First-party masters are the same trust domain as the pinned pointers, which the normal push build already executes unreviewed with the same secrets. Blanking the key on nightly runs would be belt-and-braces, but it interacts with the --config override that keys on the variable being set (:1074), so I have left that as a maintainer decision rather than change signing behaviour blind — a nightly never publishes, so a signed-but-unpublished artifact has no consumer either way.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97742d7a65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/release.yml Outdated
done
}
pass direct
git submodule update --init --recursive

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve direct submodule tips during nested initialization

Whenever a direct submodule has moved, this command undoes pass direct: the default checkout procedure for git submodule update checks out “the commit recorded in the superproject,” which is the pinned revision. pass nested then skips every path without /, and the final status command only reports the resulting mismatch, so all latest-mode jobs build pinned top-level modules (and the Tauri relock reads the old aw-server-rust SHA). Initialize nested modules from within the moved parents, or otherwise avoid updating the direct paths back to the index revisions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and fixed in 16cc23a. Nested init now runs git submodule --quiet foreach 'git submodule update --init --recursive -q' — inside each direct submodule, so the direct tips survive. In the manylinux job the step moved after "Configure git safe directory" and carries a step-scoped safe.directory=* (GIT_CONFIG_* env), since the global entry covers the workspace but not the submodule worktrees the step runs git in.

…bmodule worktrees in the manylinux container

Review findings (Codex):
- `git submodule update --init --recursive` at the top level checks out
  the superproject-recorded revisions, undoing the direct-tip pass; every
  latest-mode job silently built pinned code. Initialise nested
  submodules from inside each direct submodule instead.
- In the manylinux container the step ran before the safe.directory
  workaround and `git -C <submodule>` runs inside worktrees the global
  entry does not cover. Move it after, with a step-scoped
  safe.directory=* via GIT_CONFIG_*.
…ase gate

Review finding (Bob's reviewer): preflight judges master by the names of
its check-runs, and a nightly run's build jobs carried the same names as
the push build against the same SHA — a red nightly on unreviewed
submodule tips would have cancelled the weekly dev prerelease although
the pinned tree was healthy. Latest-mode jobs are now named
"... [latest submodules]" and the gate excludes that marker and the
resolver job. Also refuse to run the resolver's `submodule update` with
an empty first-party list, which would have moved every submodule,
awatcher included.
@ErikBjare

Copy link
Copy Markdown
Member Author

@TimeToBuildBob P1 confirmed and fixed in 65fa749: the four build jobs are named … [latest submodules] when they run in latest mode (job name takes the needs context), and preflight's gate now excludes that marker plus the resolver job, so a red nightly cannot cancel the weekly dev prerelease. Tested the jq filter against a synthetic check-runs payload: failed nightly build + failed resolver + failed greeting filtered out, the pinned build's success kept. The advisory is taken too: an empty first-party list now refuses instead of dropping -- and moving every submodule.

Also merged master into the branch: the two red research legs were the pre-#1449 patcher failure, not this change.

@ErikBjare

Copy link
Copy Markdown
Member Author

@TimeToBuildBob review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Round 2 review — HEAD fba29279 (after 65fa749 + master merge)

Previously open findings — all confirmed fixed:

  • P1 closed: Nightly can no longer trigger dev prerelease. preflight correctly excludes the 0 3 * * * schedule and submodules=latest dispatch. The check-runs filter in preflight excludes both Resolve latest submodule tips (nightly) and all [latest submodules]-named jobs, so a red nightly doesn't block a dev release that runs against the pinned tree.
  • Mutable toolchain action: pinned to 3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9.
  • Double submodule clone on normal builds: resolver exits immediately on non-nightly — no extra clone paid.
  • Nested submodules uninitialized: two-pass approach (direct → foreach git submodule update --init --recursive → nested SHAs) correctly handles parents that introduce new nested submodules at their latest tip.
  • Signing secrets + unreviewed third-party code: awatcher excluded via grep -vx awatcher; empty first-party list causes hard exit 1 instead of accidentally including it.

New findings: none at P1/P2.

P3 advisory (non-blocking):

  • git -C "$path" fetch -q origin "$sha" in the consumer steps for build-qt, build-qt-manylinux-2-28, and build-tauri omits --depth 1 (research-edition-checks uses it). This is consistent with those jobs' full-history checkouts (fetch-depth: 0) and intentional, but it means full-history fetches on each moved submodule during nightly runs — acceptable for a nightly, just worth noting if runtime becomes a concern.
  • firstparty exclusion hardcodes awatcher via grep -vx. New third-party submodules would need a list update, but that's a known maintainer responsibility.

Verdict: LGTM. Ready to merge.

@ErikBjare

Copy link
Copy Markdown
Member Author

On the automated reviewer's P1: the hardening point is fair as a follow-up, the verification is not. before/after are built with git submodule foreach --recursive, which runs in every nested submodule and prints its HEAD, so a drifted aw-qt/media is compared (that is exactly how the rehearsal found it). On the boundary: --remote --recursive does move nested submodules of first-party parents, and the name filter cannot exclude a nested third-party one — today there is none (every nested submodule is ActivityWatch-org: aw-webui, media), so this is a list-vs-property gap rather than a live hole. Tracked as #1456: select first-party by URL under github.com/ActivityWatch/ and print the excluded set per run.

With Bob's manual round-2 LGTM and CI on fba2927, this is ready to merge.

@ErikBjare
ErikBjare merged commit 012b634 into master Sep 18, 2026
21 checks passed
ErikBjare pushed a commit that referenced this pull request Sep 18, 2026
…1457)

* fix(ci): select nightly first-party submodules by URL, not by name

Filter by whether the URL is under github.com/ActivityWatch/ (case-
insensitive) instead of hard-coding a name exclusion list. This ensures
newly added third-party submodules are excluded automatically, and
prints the excluded set in every job run so the boundary stays visible.

Closes #1456
Follow-up from #1448

Git-Session-Id: dc09

* fix(ci): anchor first-party URL match and derive submodule name from .gitmodules

Two review findings on the URL-based classifier:

- The `*github.com/activitywatch/*` glob matched the string anywhere in
  the URL, so a mirror like `https://mirror.example/github.com/ActivityWatch/x`
  would classify as first-party and get built with the signing key. Anchor
  the match against known URL prefixes instead.
- `$sm` was populated from `git submodule foreach`'s `$sm_path`, but
  `.gitmodules` is keyed by submodule *name*, which git permits to differ
  from path. Read name/path pairs directly from `.gitmodules` instead of
  reusing the path as the name for the url lookup.

Git-Session-Id: 1083368a-3a3e-5b8c-ac1e-c999007d3dc1
ErikBjare added a commit that referenced this pull request Sep 19, 2026
…gger, and name the build legs again (#1458)

* ci(release): skip the nightly submodule resolver outside latest mode

`nightly-submodules` ran on every trigger, including PRs and release tags,
purely so that its dependents' `needs:` would not short-circuit. On a pinned
build it checks out the repo, hits its own guard, writes latest=false and
exits, so every ordinary run queued a runner and made four build jobs wait on
a job that had nothing to do.

Gate the job on the same condition its guard step already uses, and let the
dependents survive a skipped dependency with `!cancelled()`. Their conditions
and `name:` expressions already treat empty outputs as pinned mode, so a
skipped resolver reads exactly like the latest=false it used to write.

Nightly and `submodules=latest` behaviour is unchanged. A failed resolver in
latest mode still cannot pull the build jobs in: their remaining condition
requires latest == 'true' && moved == 'true', which empty outputs never
satisfy.

* ci(release): put the matrix leg back in the build job names

Since #1448 gave build-qt and build-tauri an explicit `name:` for the
`[latest submodules]` suffix, GitHub stopped appending the matrix values it
adds only to unnamed jobs. Every leg rendered identically: four "Build Qt
artifacts" and six "Build Tauri artifacts", so a red run did not say which
platform failed without opening jobs one by one.

Name the OS explicitly, plus the research flag, reusing the idiom the artifact
upload steps already use. os and research fully disambiguate: python_version,
node_version and the skip flags are single-valued in both matrices.

* ci(release): keep a failed resolver blocking, and label the effective edition

Greptile P1: with only !cancelled(), a workflow_dispatch run with
submodules=latest whose resolver FAILED would still satisfy the
workflow_dispatch disjunct, so the full matrix would build the pinned tree and
report success for a run whose whole point was to validate the latest tips.
The PR description claimed otherwise; it was wrong, because that disjunct
short-circuits before the latest/moved check. Gate the dependents on the
resolver's result being success or skipped, which restores the old
failure semantics while keeping the new skip behaviour.

Greptile P2: research tag pushes and edition=research dispatches enable
Research Edition through AW_RESEARCH_EDITION while matrix.research stays
false, so those legs were labelled as ordinary builds. Label the effective
edition, mirroring each job's own AW_RESEARCH_EDITION expression. Applied to
the manylinux job too, which Greptile did not flag but which builds the
research edition on the same triggers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants