You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three conflicts, plus one semantic clash the auto-merge hid.
.github/workflows/ci.yml -- took develop's pipeline (PR #474 cut it from
~7:20 to ~2:00 and folded check-submodules, build-emulator, unit-tests and
python-integration-tests into build-and-test) and re-applied what this branch
adds on top:
- permissions: contents: read at the workflow level. develop has no
permissions block, so code-scanning rule
actions/missing-workflow-permissions had one alert open per job.
- generate-test-report restored as its OWN job rather than folded into
build-and-test. develop's fold is correct for develop's report script,
which only needs directories that job already has. This branch's
generate-test-report.py also consumes test-reports/dylib-junit.xml and the
ARM manifest -- produced by other jobs, on other runners -- and fail()s
hard when either is missing. Folded, the report could never succeed.
- the report's provenance env (both source SHAs, run URL, both PR URLs).
develop passes only KK_BUILD_LABEL, which this branch's script does not
read; the fields it does read are release gates for 7.14.2.
- the report artifact is a directory again. The script emits
test-report/test-report.pdf beside test-report-manifest.json and
test-report.pdf.sha256; develop uploaded a bare test-report.pdf, which
would have found no files.
- release-evidence-gate, rewired to develop's folded job names, so a release
still has one required check that every evidence-producing job succeeded.
.gitleaks.toml -- union. Kept develop's header and its docs-SHA allowlist,
which is broader than and subsumes this branch's python-keepkey-pin rule, plus
this branch's U2F/vendored-deps allowlist and the note recording why no
first-party test tree is exempted.
scripts/emulator/python-keepkey.Dockerfile -- took develop's parameterised
deps-stage version wholesale.
scripts/emulator/Dockerfile did NOT conflict: only this branch had changed it
(base -> digest), so git kept the digest silently. That defeats develop's GHCR
mirror, which tags the mirrored image as kktech/firmware:v15 -- a digest FROM
ignores that tag and pulls from Docker Hub on the heaviest job in the run.
Parameterised it the way python-keepkey.Dockerfile already is, defaulting to
the digest so a release build still names an immutable base, with CI passing
the resolved mirror. kktech/firmware:v15 resolves to exactly that digest today.
Verified: emulator image builds both with the default and with an explicit
--build-arg; 153/153 unit tests pass; gitleaks 8.30.1 finds no leaks with the
merged config; clang-format clean.
# Mirrors the firmware build base image from Docker Hub into this org's GHCR.
2
+
#
3
+
# Why: every CI job that compiles anything starts by pulling ~650 MB of base
4
+
# image. Served from Docker Hub that measured ~34s per job; GHCR serves it to
5
+
# GitHub-hosted runners over the same network and does not apply Docker Hub's
6
+
# anonymous pull limits.
7
+
#
8
+
# CI treats the mirror as optional -- ci.yml falls back to Docker Hub with a
9
+
# warning if the pull fails -- so this workflow never becomes a hard
10
+
# dependency of the build. Run it once to populate the mirror, and again
11
+
# whenever BASE_IMAGE in ci.yml is bumped.
12
+
name: Mirror base image
13
+
14
+
on:
15
+
workflow_dispatch:
16
+
inputs:
17
+
source_image:
18
+
description: 'Docker Hub image to mirror (must match BASE_IMAGE in ci.yml)'
19
+
required: true
20
+
type: string
21
+
default: 'kktech/firmware:v15'
22
+
23
+
permissions:
24
+
contents: read
25
+
packages: write
26
+
27
+
jobs:
28
+
mirror:
29
+
runs-on: ubuntu-latest
30
+
timeout-minutes: 20
31
+
steps:
32
+
- name: Log in to GHCR
33
+
uses: docker/login-action@v4
34
+
with:
35
+
registry: ghcr.io
36
+
username: ${{ github.actor }}
37
+
password: ${{ secrets.GITHUB_TOKEN }}
38
+
39
+
- name: Pull, tag and push
40
+
env:
41
+
SOURCE: ${{ inputs.source_image }}
42
+
run: |
43
+
set -euo pipefail
44
+
45
+
# The source is constrained to the upstream base image, and the
46
+
# destination name is fixed rather than derived from the input.
47
+
#
48
+
# Both matter. ci.yml pulls BASE_IMAGE_MIRROR and builds firmware
49
+
# from it, so whatever lands at ghcr.io/<owner>/firmware:<tag> is
50
+
# trusted by every subsequent build. Deriving the destination from
51
+
# the input -- as this previously did, via ${SOURCE##*/} -- meant a
52
+
# dispatch of `anyone/firmware:v15` would resolve to that same
53
+
# destination and overwrite the image CI trusts. Dispatch needs
54
+
# write access, but "a writer can typo" and "a writer can silently
55
+
# replace the firmware build base" are different blast radii.
56
+
if [[ ! "${SOURCE}" =~ ^kktech/firmware:[A-Za-z0-9._-]+$ ]]; then
57
+
echo "::error::refusing to mirror '${SOURCE}'. This workflow only mirrors kktech/firmware:<tag>, because ci.yml builds firmware from whatever it publishes."
0 commit comments