Skip to content

[CI] Avoid unnecessary heavy CI and Pages artifact generation for non-impacting changes #215

Description

@miso-develop

Goal

Reduce GitHub Actions execution and Artifact Storage usage by avoiding expensive Web / Pages / firmware CI when a change cannot affect those surfaces.

Examples that should normally not trigger expensive product builds/deployments include documentation- and agent-process-only changes such as:

  • README.md / README.ja.md
  • ordinary docs/** changes that do not feed a generated/deployed artifact
  • .agent/**, .agents/**, agent/**, and other development-process-only files

The design must be dependency-aware rather than using a simplistic allow/deny list that can accidentally skip validation for a real product/release dependency.

Current motivation

Pages artifact/storage

Current .github/workflows/pages.yml runs on every push to main and uploads a GitHub Pages staging artifact with actions/upload-pages-artifact.

Current workflow already:

  • uses retention-days: 1;
  • deletes the consumed Pages artifact immediately after deployment.

Recent logs show a typical Pages staging artifact is roughly 1.6–1.8 MB and is deleted after deployment, so this is transient rather than durable occupancy. However, unnecessary Pages runs still create temporary Artifact Storage usage and perform a full production firmware + Web build.

Release artifacts

Current .github/workflows/release-authorized.yml uses two bounded Actions artifacts as cross-job handoffs:

  • raw firmware build handoff;
  • independently verified release package handoff.

Both use retention-days: 1 and the cleanup job deletes them by exact artifact ID. These handoffs are part of the hardened build/verify/attest/publish trust boundary and must not be removed merely to save storage unless an equally strong design is explicitly approved.

Scope

Review all current product CI/workflow entrypoints, at minimum:

  • .github/workflows/foundation.yml
    • Web tests/build
    • Windows Chrome QR smoke
    • firmware native/security/build/package validation
  • .github/workflows/pages.yml
    • production firmware build for Web Flasher
    • Web build
    • Pages staging artifact
    • Pages deployment
  • .github/workflows/security.yml
  • specialized product/test workflows such as issue117-screen-snapshot.yml
  • release workflows where relevant to dependency classification

Define a maintainable change-impact model so only the jobs affected by the changed paths run.

Possible designs may include:

  • splitting Web and firmware CI into separate workflows;
  • keeping one workflow but gating individual jobs;
  • a lightweight change-classification job followed by conditional jobs;
  • path-scoped Pages deployment;
  • another deterministic approach that preserves current required-check semantics.

Specification should select the design after evaluating the trade-offs.

Important merge-gate constraint

Do not apply workflow-level paths: filters blindly to any workflow/check that is required by repository rules.

A required check that is never created because the entire workflow was skipped can leave a PR permanently pending depending on GitHub ruleset semantics.

The final design must verify the current repository Rulesets / required check contexts and ensure that non-impacting changes still reach an unambiguous mergeable state. Prefer a stable lightweight required context or equivalent design where expensive jobs may skip while the required gate still resolves correctly.

Dependency classification requirements

The design must explicitly classify files by the product surfaces they can affect. Examples:

Web / Pages candidates

Likely includes, subject to repository inspection:

  • web/**
  • firmware/release metadata and packaging inputs copied into the deployed Web Flasher
  • scripts used by Pages build/package/validation
  • workflow itself
  • dependency/toolchain locks used by the Pages build

Firmware candidates

Likely includes, subject to repository inspection:

  • firmware/**
  • firmware/package/security validation scripts
  • firmware-native tests
  • build-image/toolchain pinning
  • workflow itself

Shared security/release inputs

Changes to security contracts, packaging, release-profile validation, CI supply-chain scripts, workflow definitions, dependency pins, or similar shared inputs must trigger every affected validation surface even if they are not under web/** or firmware/**.

Non-product/process-only candidates

README, ordinary documentation, agent contracts, work-tracking/process metadata, etc. should not trigger expensive firmware/Web builds unless the specific file is actually consumed by one of those builds or security validations.

Acceptance criteria

  • Current workflows, repository Rulesets, and required check contexts are inspected before design is finalized.
  • A documented/deterministic change-impact classification exists for Web, firmware, Pages, security/release/shared, and process/docs-only changes.
  • README-only and agent/process-only changes do not run expensive firmware builds.
  • README-only and agent/process-only changes do not build/deploy Pages or create a Pages staging artifact.
  • Web-only changes do not run unrelated heavy firmware validation unless a documented shared dependency requires it.
  • Firmware-only changes do not run unrelated Web validation unless a documented shared dependency requires it.
  • Changes to shared security/release/toolchain/build inputs trigger all validations that depend on them.
  • Required status/check semantics remain reliable: no PR is left indefinitely pending because a whole required workflow was path-filtered out.
  • Pages deployment remains correct for all files that can affect deployed content, including bundled firmware/manifest inputs.
  • Existing Pages artifact immediate-delete behavior remains in place for deployments that actually run.
  • Authorized Release artifact handoffs and their security/provenance boundary are preserved unless a separate security-reviewed equivalent is explicitly approved.
  • Existing release authorization, attestation, secret-handling, and supply-chain controls are not weakened.
  • Regression tests or contract tests cover representative path classes and expected job/deployment decisions.

Non-goals

  • Do not remove CI solely to optimize billing if doing so weakens a security or release gate.
  • Do not remove the release build/verify artifact handoff without an independently reviewed replacement.
  • Do not change Product / Protocol / Storage Schema / Vault Format behavior as part of this optimization.

Expected workflow

  1. Specification inspects current Rulesets/check requirements and defines the CI impact-routing contract.
  2. Specification splits implementation work if appropriate (for example Pages/Web vs firmware/shared CI).
  3. Infra Implementation updates workflows/tests.
  4. Review independently verifies path-routing and required-check behavior.
  5. Integration confirms repository Rulesets/checks still operate correctly before merge.

Specification resolution — 2026-09-19

State

BLOCKED_DEPENDENCY

Human sequencing decision supersedes the earlier post-release serialization.

Required order:

  1. [Task][Infra] Set canonical Product/Firmware version to 1.0.0 #214 integrates the canonical Product/Firmware 1.0.0 change first.
  2. [Task][Infra] Add dependency-aware CI impact routing and release-oriented Pages deploys #216 then becomes implementation-ready and is integrated before the v1.0.0 tag.
  3. [Release] Prepare M5Authenticator v1.0.0 #213 performs a Human-approved exact-main manual candidate Pages deployment and production-host validation under the new cadence.
  4. Only then may the remaining [Release] Prepare M5Authenticator v1.0.0 #213 pre-tag gate authorize protected v1.0.0 creation.

Current blocker for #215/#216 implementation: #214 integration, not #213 completion.

Revalidated repository state

Specification inspected current main = bc5c3b90f57952f04a80c8ddfcb55b6d384c882e.

Current active Protect main Ruleset:

  • target: default branch;
  • required check contexts: exactly one:
    • security:scan
    • GitHub Actions integration ID 15368;
  • Foundation Web/Firmware checks are not currently required status contexts;
  • Pages checks are not currently required status contexts.

Current workflows:

  • .github/workflows/foundation.yml
  • .github/workflows/security.yml
  • .github/workflows/pages.yml
  • .github/workflows/issue117-screen-snapshot.yml
  • hardened .github/workflows/release-authorized.yml
  • retired .github/workflows/release.yml tombstone.

Current Pages runs on every push to main, every v*.*.* tag push, and manual dispatch; each deployment performs a production firmware build, production Web build, Pages staging-artifact upload, deploy, and exact artifact deletion.

Current release artifact handoffs remain security-critical and are out of optimization scope.

Selected architecture

Use a fail-safe deterministic impact classifier + conditional heavy jobs, while preserving one always-created required security context.

Do not solve #215 primarily with workflow-level paths: / paths-ignore: on required/security workflows.

Required-check invariant

.github/workflows/security.yml remains triggered for:

  • every pull request;
  • every push to main.

The job name/context must remain exactly security:scan.

Do not put a job-level if: on security:scan that could cause it not to be created.

For this optimization, retain the existing full security/release contract suite in security:scan. It is fast relative to firmware/Windows/Pages builds and is the repository's only protected-main required context.

This deliberately prioritizes merge/release certainty over shaving the final small amount of security-check runtime.

Foundation routing

Keep foundation.yml triggered on every PR and every main push, but make only a lightweight impact/classification job unconditional.

Heavy Foundation jobs become conditional:

  • web runs only for Web or shared-impact changes;
  • web QR Windows Chrome runs only for Web or shared-impact changes;
  • firmware runs only for Firmware or shared-impact changes.

For docs/process-only changes:

  • classifier runs;
  • Web job is skipped;
  • Windows Chrome job is skipped;
  • firmware job is skipped;
  • required security:scan still completes normally.

Foundation itself is not a required Ruleset context, so conditional skipped jobs do not create a protected-main pending-check problem.

Pages cadence — selected option

Adopt release-oriented Pages deployment plus explicit/manual pre-release candidate deployment.

After implementation, pages.yml must no longer deploy on ordinary main pushes.

Automatic Pages deployment trigger:

  • protected SemVer tag push matching v*.*.* only.

Manual trigger:

  • retain workflow_dispatch, but make it explicitly a pre-release/candidate deployment action rather than an implicit routine-main deploy.
  • manual candidate deployment must be visibly intentional in the workflow input/summary.
  • it deploys the selected/current authorized repository ref as a candidate and records its exact source SHA/build identity.
  • no new automatic main-push deployment is permitted.

Do not move Pages deployment inside release-authorized.yml and do not add Pages write/OIDC authority to the hardened publisher. The release build/verify/attest/publish privilege boundary from #127/#199 remains unchanged.

The protected release tag is considered the normal release-stage Pages publication trigger. The Authorized Release GitHub Release publication remains a separate hardened workflow.

Why manual candidate deployment remains available

Historical #75 demonstrated that actual hosted production behavior can expose defects not obvious in unit tests, including CSP/image-loading behavior.

Therefore removing routine Pages deploys is allowed only with two compensating controls:

  1. deterministic local production-equivalent browser coverage in CI;
  2. an explicit manual Pages candidate path when a Human Gate specifically needs the actual GitHub Pages origin/environment.

Routine Web/Firmware Human Gates should use local production-equivalent output unless an Issue explicitly requires hosted Pages.

Deterministic change-impact model

Implement one repository-owned classifier, not duplicated ad-hoc YAML glob logic across jobs.

Preferred source:

scripts/ci_change_impact.py

with deterministic tests, for example:

tests/ci_change_impact_test.py

The classifier accepts changed repository paths and emits stable booleans/categories usable through GITHUB_OUTPUT.

Categories

At minimum:

  • web
  • firmware
  • pages
  • security_release_shared
  • snapshot_contract
  • snapshot_build
  • process_docs_only

A changed set may belong to multiple categories.

Fail-safe rule

Unknown/unclassified paths must fail heavy, not fail open.

If a changed path is not explicitly recognized as harmless or surface-specific:

  • classify it as shared impact;
  • run both heavy Web and Firmware Foundation validation;
  • mark Pages/shared validation impact as applicable.

This prevents a future new build input from silently bypassing CI because the classifier's allowlist was not updated yet.

Harmless/process-doc classification

These are normally non-product and must not trigger heavy Foundation Web/Firmware or automatic Pages deployment:

  • README.md
  • README.ja.md
  • README presentation assets under docs/assets/**
  • ordinary docs/**
  • .agent/**
  • .agents/**
  • agent/**
  • ordinary repository process/work-tracking metadata;
  • AGENTS.md for product builds.

These files still pass the always-required security:scan.

Specialized contract tests may still run when a doc/process file is intentionally consumed by those tests; that does not make the file a production firmware/Web input.

Web impact

At minimum:

  • web/**;
  • Web-specific build/config/tooling inputs outside web/**, if any are added later;
  • the classifier itself / Foundation workflow when routing semantics change.

Web impact runs:

  • Linux Web test/build;
  • Windows Chrome QR/Argon2 smoke;
  • local production-equivalent hosted-site smoke described below.

It does not by itself run the heavy ESP-IDF Foundation firmware build.

Firmware impact

At minimum:

  • firmware/**;
  • firmware native/runtime test sources under root tests/** when they exercise firmware contracts;
  • ESP-IDF build-image/toolchain pinning;
  • isolated firmware build/package/verification scripts used by Foundation.

Firmware impact runs:

  • native firmware tests/contracts;
  • isolated ESP-IDF build;
  • image verification;
  • package validation.

It does not by itself run unrelated Web unit/Windows browser suites.

Security / release / shared impact

Inputs whose meaning crosses Web/Firmware/release boundaries must conservatively trigger every affected product validation.

Examples include:

  • .github/workflows/foundation.yml
  • .github/workflows/security.yml
  • .github/workflows/pages.yml
  • hardened release workflow/contracts when their changes can affect build/package security
  • release-profile/package/validation scripts shared by Pages/Foundation/Release
  • CI supply-chain scripts;
  • security scanner/contract tests;
  • build-image provenance scripts;
  • shared release/packaging metadata contracts.

Shared impact runs:

  • Web heavy jobs;
  • Windows Chrome job;
  • Firmware heavy job;
  • always-required Security;
  • production-site/local Pages-equivalent validation.

Tests

Do not classify all tests/** as docs/process.

Test changes must run the production surface they validate:

  • Web tests colocated under web/** => Web;
  • firmware/runtime/release-package tests => Firmware or Shared as appropriate;
  • security/release authorization/attestation tests => Security/Shared;
  • classifier tests => Shared because they control CI routing.

When ownership of a new test is ambiguous, fail-safe Shared applies.

Event diff semantics

The routing decision must be based on the complete changed-path set.

For pull requests:

  • compare PR base SHA to PR head SHA, not only the checkout merge commit's working tree.

For push to main:

  • compare event before to event after.

Renames/deletions count as changes and must be classified using their changed paths.

If the base SHA is missing, all-zero, unavailable, history is insufficient, or diff computation fails:

  • set Shared/all-heavy impact;
  • do not silently skip jobs.

Use repository-owned Git/Python logic rather than a new third-party change-filter action unless a separate supply-chain review explicitly approves one.

Production-equivalent Web/Pages CI compensation

Routine main pushes will no longer deploy public Pages, so CI must exercise the static production Web shape without using Vite dev mode.

For Web/Pages/shared impact, add a local production-equivalent smoke path that:

  • runs a real Vite production build (npm run build or an equivalent production-mode command);
  • uses the production base path /m5authenticator/;
  • exercises the production CSP;
  • enables the normal Firmware Flash UI surface;
  • provides synthetic/non-secret same-origin firmware manifest/assets sufficient to test route/fetch/layout behavior without requiring an unrelated ESP-IDF build for a Web-only change;
  • serves the resulting web/dist through a local static/preview server;
  • opens it in Chrome;
  • validates Provisioner/Firmware/Help routes and same-origin firmware-manifest fetch under the production base path;
  • preserves existing QR/Argon2 production-bundle coverage.

Do not use vite dev as the release-sensitive compensation.

Synthetic firmware fixtures must never be published as production firmware and must be unmistakably test-only.

A firmware-only change is validated by Firmware package/image contracts and does not have to run the unrelated Windows/Web suites merely because Pages eventually bundles the firmware.

Changes to the Web/Firmware manifest contract or other true shared deployment boundary are Shared and run both.

Issue 117 specialized workflow

The current specialized workflow is not a required Ruleset context, so path scoping is allowed, but it currently couples documentation/process contract checks to an expensive ESP-IDF diagnostics build.

Refine it into two impact levels:

Snapshot contract-only

For changes such as:

  • docs/testing/screen-snapshot-diagnostics.md;
  • AGENTS.md;
  • Windows helper scripts;
  • diagnostics host helper;
  • snapshot contract tests;

run the relevant lightweight Python contract tests.

Do not build diagnostics firmware merely because AGENTS.md or the procedure document changed.

Snapshot build

Run the diagnostics-ON ESP-IDF build only when inputs capable of changing that firmware/profile change, including:

  • relevant firmware CMake/sdkconfig/main/device/time/session/vault-runtime sources;
  • ESP-IDF image pin/build input;
  • the specialized workflow's build semantics themselves;
  • tests/build contracts whose purpose requires compiling that profile.

The classifier/contracts must pin this distinction.

Pages deployment contract

Automatic release-stage deployment

For a vX.Y.Z tag event:

  • preserve current release-profile/tag-version match check;
  • build production firmware using the immutable ESP-IDF contract;
  • validate/package firmware;
  • copy exact package output into the static Web site;
  • build production Web;
  • upload one Pages staging artifact;
  • deploy;
  • immediately delete the consumed staging artifact by exact artifact ID;
  • retain retention-days: 1 as defense in depth;
  • exact release identity remains governed by the existing tag/source logic.

Manual candidate deployment

Manual candidate deployment:

  • is Human-initiated only;
  • is not a release publication;
  • must display/record exact source SHA;
  • must render build identity as non-exact release unless an already-authorized matching release tag truly points at that SHA;
  • uses the same production firmware/package/Web build path;
  • preserves artifact immediate deletion;
  • may be used when an Issue/Human Gate explicitly requires actual GitHub Pages hosting behavior.

Do not make a PR automatically overwrite public Pages.

No routine main deployment

A normal merge/push to main:

  • must not start build-pages;
  • must not start deploy-pages;
  • must not upload a Pages staging artifact;
  • must not overwrite the public Pages site.

The public site therefore represents the most recently deployed release/candidate, not necessarily current main.

Documentation/build identity must not imply otherwise.

Release workflow artifacts

No changes to the Authorized Release build/verify artifact handoff design are allowed under #215.

Preserve:

  • raw build handoff;
  • independently verified release package handoff;
  • exact artifact-ID linkage;
  • retention-days: 1;
  • checksum revalidation;
  • attestation-before-publish;
  • cleanup job exact-ID deletion.

These are trust-boundary artifacts, not disposable CI convenience artifacts.

Required contract tests

Add deterministic tests that cover at least these changed-path matrices:

Changed paths Web Windows Web Firmware Pages auto deploy Security
README.md only skip skip skip no run
README.ja.md + docs/assets/** skip skip skip no run
.agent/** / agent/** only skip skip skip no run
ordinary docs/** only skip skip skip no run
web/src/** only run run skip no run
firmware/** only skip skip run no run
release/package shared script run run run no run
Foundation/Pages/Security workflow routing change run run run no run
unknown new top-level path run run run no run

Also test:

  • diff failure => Shared/all-heavy;
  • classifier change => Shared/all-heavy;
  • required security:scan workflow has no workflow-level path filter and no skip condition;
  • Pages has no ordinary-main push trigger;
  • Pages retains tag + explicit manual candidate triggers;
  • Pages upload retains 1-day retention and exact-ID deletion;
  • Authorized Release artifact handoff remains unchanged by this task;
  • snapshot docs/AGENTS do not imply diagnostics ESP-IDF build;
  • relevant snapshot firmware changes do imply diagnostics build.

Documentation

Document the impact model in a durable repository location close to CI/release operations.

Preferred:

docs/CI.md

or an equivalent existing CI/development document if one already owns this subject.

Document:

  • category model;
  • fail-safe unknown-path behavior;
  • required-check invariant;
  • why Security always runs;
  • Pages release/manual-candidate cadence;
  • local production-equivalent Web Human Gate guidance;
  • when actual hosted Pages candidate deployment is required;
  • release artifact exception.

Do not duplicate internal Agent process contracts into product docs.

Integration / rollout gates

Because #215 changes workflow routing, Integration must verify on the exact implementation head and post-merge main:

  1. active Protect main still requires only the intended stable security:scan context unless a separately approved Ruleset change is made;
  2. PR exact head produces successful security:scan;
  3. shared workflow-change PR itself runs Web + Windows + Firmware heavy validation;
  4. post-merge main produces successful security:scan and the expected Foundation routing;
  5. the merge push does not create a routine Pages build/deploy;
  6. no Pages staging artifact is created from that ordinary main push;
  7. legacy Release workflow retirement remains unchanged;
  8. Authorized Release contract/security tests stay green.

A one-time manual Pages candidate deployment after integration is recommended to verify the retained manual path and artifact cleanup. It requires Human approval because it overwrites the public Pages site.

Do not close #215 until the post-merge routing evidence is durable.

Release sequencing

Human explicitly requires this CI/Pages change before the v1.0.0 release.

Dependency:

Before claiming #216:

#213 has been revised so ordinary-main Pages deployment is no longer a pre-tag requirement after #216 integrates. Instead, #213 requires one exact-main Human-approved manual candidate Pages deployment plus production-host validation before tag creation.

Acceptance

  • Current Rulesets/required contexts are rechecked immediately before implementation.
  • security:scan remains always-created and required.
  • Deterministic repository-owned change-impact classifier exists with fail-safe Shared fallback.
  • README/docs/agent/process-only changes skip heavy Web, Windows, Firmware, and Pages deployment.
  • Web-only changes run Web + Windows browser validation but skip heavy firmware build.
  • Firmware-only changes run Firmware validation but skip unrelated Web/Windows suites.
  • Shared/release/security/build-routing inputs conservatively run all affected validation.
  • Unknown paths fail safe to Shared/all-heavy.
  • Routine main pushes no longer deploy Pages or upload a Pages staging artifact.
  • Protected SemVer tag pushes retain automatic production Pages deployment.
  • Explicit manual candidate Pages deployment remains available.
  • Web/shared changes receive local production-build + Chrome smoke coverage for CSP/base-path/same-origin firmware behavior.
  • Issue117 docs/process changes run lightweight contracts without diagnostics ESP-IDF build.
  • Issue117 firmware/profile-impact changes still run diagnostics ESP-IDF build.
  • Pages release/candidate deployments retain 1-day staging retention + immediate exact-ID deletion.
  • Authorized Release artifact handoffs and privilege/provenance boundary remain unchanged.
  • Representative routing matrix is regression-tested.
  • CI impact/cadence documentation is durable.
  • Integration records post-merge evidence that required checks resolve and routine main no longer deploys Pages.
  • No Product / Protocol / Storage Schema / Vault Format semantics change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions