Skip to content

Show the age of the last update check on the updates panel #981

Show the age of the last update check on the updates panel

Show the age of the last update check on the updates panel #981

name: Canonical Governance
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: read
jobs:
governance:
runs-on: ubuntu-24.04
# The release-control audits resolve the workspace layout from the
# local checkout: the repo directory must be named exactly "pulse"
# (the canonical repo id) and the evidence repos must be checked out
# as siblings, mirroring <workspace>/repos/<repo-id> on dev machines.
defaults:
run:
working-directory: repos/pulse
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
fetch-depth: 0
path: repos/pulse
- name: Checkout pulse-pro evidence repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: rcourtman/pulse-pro
token: ${{ secrets.WORKFLOW_PAT }}
persist-credentials: false
fetch-depth: 1
path: repos/pulse-pro
- name: Checkout pulse-enterprise evidence repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: rcourtman/pulse-enterprise
token: ${{ secrets.WORKFLOW_PAT }}
persist-credentials: false
fetch-depth: 1
path: repos/pulse-enterprise
- name: Resolve pulse-mobile evidence ref
id: pulse-mobile-ref
shell: bash
env:
CANDIDATE_REF: ${{ github.head_ref }}
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}
run: |
set -euo pipefail
resolved_ref="main"
if [ -n "${CANDIDATE_REF}" ]; then
matching_ref="$(gh api \
"repos/rcourtman/pulse-mobile/git/matching-refs/heads/${CANDIDATE_REF}" \
--jq '.[].ref' 2>/dev/null \
| grep --fixed-strings --line-regexp -- "refs/heads/${CANDIDATE_REF}" \
|| true)"
if [ -n "${matching_ref}" ]; then
resolved_ref="${CANDIDATE_REF}"
fi
fi
echo "ref=${resolved_ref}" >> "${GITHUB_OUTPUT}"
echo "Using pulse-mobile ref: ${resolved_ref}"
- name: Checkout pulse-mobile evidence repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: rcourtman/pulse-mobile
ref: ${{ steps.pulse-mobile-ref.outputs.ref }}
token: ${{ secrets.WORKFLOW_PAT }}
persist-credentials: false
fetch-depth: 1
path: repos/pulse-mobile
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: repos/pulse/go.mod
cache: true
cache-dependency-path: repos/pulse/go.sum
- name: Stub embedded frontend assets for Go tests
run: bash scripts/ensure_test_assets.sh
- name: Check Pulse Mobile compatibility contract
run: |
python3 scripts/release_control/generate_mobile_compatibility_test.py
python3 scripts/release_control/mobile_compatibility_test.py
python3 scripts/release_control/generate_mobile_compatibility.py --check --mobile-repo ../pulse-mobile
python3 scripts/release_control/mobile_compatibility.py \
--mobile-repo ../pulse-mobile \
--evidence-out "${RUNNER_TEMP}/pulse-mobile-compatibility.json" \
--pretty
go test ./internal/api \
-run 'Test(RelayMobileRuntimeRouteInventory|RelayMobileAccessScopeAllowsGovernedMobileRuntimeEndpoints|RelayMobileAccessScopeDeniesAdjacentAIRoutes|Contract_PatrolAttentionRoutesAcceptMobileRelayCapability)$' \
-count=1
go test ./internal/relay \
-run 'Test(CanonicalActionOutcomeNotificationMatrix|NewPatrolFindingNotification|NewApprovalRequestNotification|NewActionDecisionNotificationUsesCanonicalActionIdentity|NewFixCompletedNotification|NewActionOutcomeNotificationIsHonestAboutVerification)$' \
-count=1
- name: Upload Pulse Mobile compatibility evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pulse-mobile-compatibility
path: ${{ runner.temp }}/pulse-mobile-compatibility.json
if-no-files-found: error
- name: Determine governance diff range
id: diff
shell: bash
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "pull_request" ]; then
range="${{ github.event.pull_request.base.sha }}...${{ github.sha }}"
elif [ "${{ github.event_name }}" = "push" ]; then
range="${{ github.event.before }}...${{ github.sha }}"
elif git rev-parse --verify HEAD^ >/dev/null 2>&1; then
range="HEAD^...HEAD"
else
range=""
fi
echo "range=${range}" >> "$GITHUB_OUTPUT"
- name: Run canonical completion guard against changed commits
shell: bash
run: |
set -euo pipefail
range="${{ steps.diff.outputs.range }}"
if [ -z "${range}" ]; then
printf '' | python3 scripts/release_control/canonical_completion_guard.py --files-from-stdin
exit 0
fi
base="${range%%...*}"
head_sha="${range##*...}"
# Evaluate each commit the way the commit-time hook did: its own
# file list against its own parent. A range-wide evaluation
# cannot honor per-commit Contract-Neutral trailers (recorded by
# .husky/prepare-commit-msg when the author sets
# PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT), so bypassed commits that
# passed locally would fail here.
if ! commits=$(git rev-list --reverse --no-merges "${base}..${head_sha}" 2>/dev/null); then
echo "Range base ${base} unavailable (force push?); evaluating ${head_sha} against its parent."
commits="${head_sha}"
fi
if [ -z "${commits}" ]; then
echo "No commits to evaluate in range ${range}."
exit 0
fi
status=0
for commit in ${commits}; do
if ! git rev-parse --verify --quiet "${commit}^" >/dev/null; then
echo "Skipping root commit ${commit} (no parent to diff against)."
continue
fi
reason=$(git log -1 --format='%(trailers:key=Contract-Neutral,valueonly,separator=; )' "${commit}" | tr '\n' ' ')
echo "::group::canonical completion guard @ ${commit}"
# Pass the parent as the diff base so the guard compares
# contract texts parent-vs-commit; the CI index equals HEAD,
# so the default index comparison would misreport contract
# updates in earlier commits as insubstantial.
if ! git diff-tree --no-commit-id --name-only -r "${commit}" \
| PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT="${reason}" python3 scripts/release_control/canonical_completion_guard.py \
--files-from-stdin --diff-base "${commit}^"; then
echo "Canonical completion guard failed for commit ${commit}."
status=1
fi
if ! git diff-tree --no-commit-id --name-only -r "${commit}" \
| python3 scripts/release_control/browser_verification_guard.py \
--files-from-stdin --commit "${commit}"; then
echo "Browser verification guard failed for commit ${commit}."
status=1
fi
echo "::endgroup::"
done
exit ${status}
- name: Run status audit
env:
PULSE_REPO_ROOT_PULSE: ${{ github.workspace }}/repos/pulse
PULSE_REPO_ROOT_PULSE_PRO: ${{ github.workspace }}/repos/pulse-pro
PULSE_REPO_ROOT_PULSE_ENTERPRISE: ${{ github.workspace }}/repos/pulse-enterprise
PULSE_REPO_ROOT_PULSE_MOBILE: ${{ github.workspace }}/repos/pulse-mobile
run: python3 scripts/release_control/status_audit.py --check
- name: Validate Pulse Intelligence release-gate schema
run: python3 scripts/release_control/pulse_intelligence_gate.py --validate-only --matrix docs/release-control/v6/internal/pulse-intelligence-release-gate.json
- name: Run Pulse Intelligence release-gate unit tests
run: python3 scripts/release_control/pulse_intelligence_gate_test.py
- name: Run control plane audit
env:
PULSE_REPO_ROOT_PULSE: ${{ github.workspace }}/repos/pulse
PULSE_REPO_ROOT_PULSE_PRO: ${{ github.workspace }}/repos/pulse-pro
PULSE_REPO_ROOT_PULSE_ENTERPRISE: ${{ github.workspace }}/repos/pulse-enterprise
PULSE_REPO_ROOT_PULSE_MOBILE: ${{ github.workspace }}/repos/pulse-mobile
run: python3 scripts/release_control/control_plane_audit.py --check
- name: Run registry audit
run: python3 scripts/release_control/registry_audit.py --check
- name: Run canonical mutation registry audits
run: go test ./internal/mutationregistry ./internal/ai/tools -run 'Test(EveryRegisteredMutationHasDisposition|InfrastructureAPIRoutesResolveToRegistry|TransportCommandCatalogsResolveToRegistry|PatrolJobRegistrationResolvesToRegistry|RuntimeCandidateAuditNegativeFixtures|ActionRouteMethodAuthorityIsExactAndLookalikesFailClosed|NonAdmittingTransportMessagesCannotCarryDispatchAuthority|UnknownTransportLookalikeFailsClosed|RegisteredModelMutationSchemasResolveToClosedRegistry|RetiredMutationAliasesCannotShadowExtensions)' -count=1
- name: Run contract audit
run: python3 scripts/release_control/contract_audit.py --check
- name: Run canonical completion guard unit tests
run: python3 scripts/release_control/canonical_completion_guard_test.py
- name: Run browser verification guard unit tests
run: python3 scripts/release_control/browser_verification_guard_test.py
- name: Run control plane audit unit tests
run: python3 scripts/release_control/control_plane_audit_test.py
- name: Run contract audit unit tests
run: python3 scripts/release_control/contract_audit_test.py
- name: Run staged Go formatter unit tests
run: python3 scripts/release_control/format_staged_go_test.py
- name: Run governance stage guard unit tests
run: python3 scripts/release_control/governance_stage_guard_test.py
- name: Run registry audit unit tests
run: python3 scripts/release_control/registry_audit_test.py
- name: Run repo file IO unit tests
run: python3 scripts/release_control/repo_file_io_test.py
- name: Run release promotion policy unit tests
run: python3 scripts/release_control/release_promotion_policy_test.py
- name: Run status audit unit tests
run: python3 scripts/release_control/status_audit_test.py
- name: Run subsystem contract helper unit tests
run: python3 scripts/release_control/subsystem_contracts_test.py
- name: Run subsystem lookup unit tests
run: python3 scripts/release_control/subsystem_lookup_test.py
- name: Run repo governance guardrail tests
env:
PULSE_REPO_ROOT_PULSE: ${{ github.workspace }}/repos/pulse
PULSE_REPO_ROOT_PULSE_PRO: ${{ github.workspace }}/repos/pulse-pro
PULSE_REPO_ROOT_PULSE_ENTERPRISE: ${{ github.workspace }}/repos/pulse-enterprise
PULSE_REPO_ROOT_PULSE_MOBILE: ${{ github.workspace }}/repos/pulse-mobile
run: go test ./internal/repoctl -count=1
- name: Run active-target automated readiness assertion proofs
run: python3 scripts/release_control/readiness_assertion_guard.py --active-target --proof-type automated
- name: Run active-target hybrid readiness assertion proofs
run: python3 scripts/release_control/readiness_assertion_guard.py --active-target --proof-type hybrid
- name: Run readiness assertion guard unit tests
run: python3 scripts/release_control/readiness_assertion_guard_test.py