Skip to content

docs(#14): point the dry/fan unlock prerequisite at the real integrat… #189

docs(#14): point the dry/fan unlock prerequisite at the real integrat…

docs(#14): point the dry/fan unlock prerequisite at the real integrat… #189

Workflow file for this run

name: QA
# Hardware-free gate: the same checks the pre-commit hook runs (host codec + Matter<->A/C mapping +
# virtual-AC round-trip, .zap endpoint contiguity, softwareVersion sanity via `ota-release.sh lint`),
# plus a PR-only check that firmware/src/version.txt strictly increases. No SDK, Pi, or chip.
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
# Least privilege: this gate only reads the tree (checkout + host scripts), never writes.
permissions:
contents: read
jobs:
host-qa:
# GitHub-only: Gitea mirrors this repo and auto-reads .github/workflows, but has no
# ubuntu-latest runner (its self-hosted runner is sdk-builder). Skip on Gitea so the job
# doesn't queue forever there; the Gitea build lives in .gitea/workflows/build.yaml.
if: ${{ github.server_url == 'https://github.com' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # PR version-diff needs base history
# Static lint first (cheap, fails fast). Run these same two commands locally for parity.
# shellcheck ships on the runner image; --severity=warning gates real bugs (quoting, unset
# vars, logic) and skips the info/style nits the scripts intentionally use. ruff reads the
# committed ruff.toml; it's pinned via pipx (bump with the local version + Dependabot).
- name: Shell lint (shellcheck)
run: |
shellcheck --version
shellcheck --severity=warning firmware/scripts/*.sh firmware/test/*.sh \
firmware/.githooks/pre-commit firmware/.githooks/prepare-commit-msg
- name: Python lint (ruff)
run: pipx run ruff==0.15.20 check .
- name: ESP32 version consistency
run: bash firmware/scripts/esp32-lint.sh
- name: Host QA + lint
run: bash firmware/scripts/ota-release.sh lint
- name: softwareVersion must increase vs base (when firmware changed)
if: ${{ github.event_name == 'pull_request' }}
env:
BASE: ${{ github.base_ref }}
run: |
# Scope to firmware/src (the shipped image is built from it + the .zap under sdk-edits).
# firmware/test is host-only QA that never changes the image, so a test-tooling edit must
# NOT force a softwareVersion bump.
# Compare against the MERGE-BASE, not the base tip. Against the tip, a branch that has
# merely fallen behind main sees main's own firmware commits as its own and is told to
# bump a version it never touched. That fired twice on docs-only PRs. The merge-base is
# the fork point, so the diff is only ever what this branch actually changed.
git fetch --no-tags origin "$BASE" || true
MERGE_BASE=$(git merge-base FETCH_HEAD HEAD 2>/dev/null || echo FETCH_HEAD)
# Exclude markdown: firmware/src carries docs (INTEGRATION.md, UART_PINS.md,
# sdk-edits/README.md) that cannot reach the built image, so editing them must not demand
# a firmware version bump. Scoping to the whole directory made a docs-only pass fail.
if git diff --quiet "$MERGE_BASE" -- firmware/src ':(exclude)firmware/src/**/*.md'; then
echo "no firmware/src code change vs $BASE (merge-base $(git rev-parse --short "$MERGE_BASE")) -- bump not required"; exit 0
fi
new=$(bash firmware/scripts/ota-release.sh verint "$(cat firmware/src/version.txt)")
oldsem=$(git show "$MERGE_BASE:firmware/src/version.txt" 2>/dev/null | tr -d '[:space:]' || true)
old=$(bash firmware/scripts/ota-release.sh verint "${oldsem:-0}" 2>/dev/null || echo 0)
echo "softwareVersion int: base($BASE)=$old head=$new"
if [ "${new:-0}" -le "$old" ]; then
echo "::error::softwareVersion must strictly increase ($new <= $old) -- bump firmware/src/version.txt"
exit 1
fi