ci: migrate to netresearch/.github reusable container workflows#11
Merged
Conversation
Replaces the inline hadolint container-run and ludeeus/action-shellcheck step with a single `uses:` of netresearch/.github/.github/workflows/lint-container.yml. Container-lint logic is now shared with phpbu-docker and other future container repos. Pinned to feat/reusable-container-workflows because PR netresearch/.github#141 is mergeable but BLOCKED on review at the time of this commit; a follow-up commit on this branch will flip the ref to @main once that PR merges. compose-validate (docker compose config with .env.example placeholder substitution) and yamllint stay inline — both depend on caller-shaped inputs that don't generalise to the reusable. Refs: netresearch/.github#141 Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Replaces the inline buildx --load + container-structure-test steps in the `image-surface` job with a single `uses:` of netresearch/.github/.github/workflows/smoke-test-container.yml. Same behaviour (amd64 build at the `runtime` target, GHA cache scope `smoke-test`, cst config at tests/container-structure-test.yaml) — now shared with phpbu-docker and other future container repos. Pinned to feat/reusable-container-workflows because PR netresearch/.github#141 is mergeable but BLOCKED on review at the time of this commit; a follow-up commit on this branch will flip the ref to @main once that PR merges. The other three jobs stay inline — all snipe-it-specific: - compose-up — stack boot with placeholder-substituted .env and HTTP probe of the known login route - init-idempotency — verifies bin/init.sh's APP_KEY / random-PW generation contract (must not re-roll on second run) - upstream-tests — builds the `tester` Dockerfile stage which runs the upstream Snipe-IT phpunit suite Refs: netresearch/.github#141 Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Replaces the four-step inline OpenSSF Scorecard job (checkout + scorecard-action + upload-artifact + upload-sarif) with a single `uses:` of netresearch/.github/.github/workflows/scorecard.yml@main. The reusable's job is functionally equivalent: same scorecard-action version, same publish_results=true, same SARIF upload to GitHub code-scanning. The only behavioural change is that the per-run raw results.sarif is no longer kept as a workflow artifact for 5 days — the SARIF is still uploaded to code-scanning (the canonical surface), and re-running the workflow regenerates it on demand. This reusable is already on `main` in netresearch/.github (predates the container-workflows PR), so no ref-flip follow-up is needed for this file. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
|
Note Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported. |
There was a problem hiding this comment.
Pull request overview
Migrates selected GitHub Actions workflows in this repository to org-wide reusable container workflows hosted in netresearch/.github, reducing duplication as part of the container-CI consolidation effort.
Changes:
- Delegate container linting (hadolint + shellcheck) from
.github/workflows/lint.ymltonetresearch/.githubreusable. - Delegate the smoke-test “image surface” (build + container-structure-test) job from
.github/workflows/smoke-test.ymlto a reusable workflow. - Delegate OpenSSF Scorecard workflow from
.github/workflows/scorecard.ymlto the org reusable.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| .github/workflows/lint.yml | Replaces inline hadolint + shellcheck jobs with a reusable lint-container.yml invocation. |
| .github/workflows/smoke-test.yml | Replaces inline image-surface job steps with a reusable smoke-test-container.yml invocation. |
| .github/workflows/scorecard.yml | Replaces inline scorecard steps with a reusable scorecard.yml invocation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The netresearch/.github reusable lint-container.yml on branch
feat/reusable-container-workflows (HEAD 1a56c99) pins hadolint to
v2.12.0-alpine by digest. That's exactly the version the original
snipe-it lint.yml warned against — it predates Docker 25's
HEALTHCHECK --start-interval flag and crashes on the snipe-it
Dockerfile's healthcheck line:
/dev/stdin:228:5 invalid flag: --start-interval
Process completed with exit code 1.
The reusable's docstring still claims latest-alpine, so this is an
upstream regression between PR review and the current branch HEAD.
Reverting the lint.yml migration until netresearch/.github either:
- re-pins to a hadolint version >= v2.13 (which supports
--start-interval), or
- adds a hadolint-image input so callers can override.
The shellcheck migration is reverted together with hadolint — they
share the same caller-job wrapping.
Refs: netresearch/.github#141
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
PR netresearch/.github#141 merged at 2026-05-21T20:58:39Z with merge commit 7477e5e. Two follow-ups in this commit: 1. smoke-test.yml: ref flip @feat/reusable-container-workflows → @main 2. lint.yml: re-apply the container-lint migration that was reverted in f78c9e5. The revert was needed because the reusable's initial hadolint pin (v2.12.0-alpine) was the version that crashes on HEALTHCHECK --start-interval — exactly the bug the reusable's DESIGN NOTES warned about. The reusable's pin was corrected to v2.14.0 in netresearch/.github commit a4a763e (also part of the merged PR 141), so the migration now works end-to-end. Inline yamllint job stays as-is (the snipe-it repo has no .yamllint.yml so the contract is local — caller-specific, doesn't generalise to the reusable). Verified locally: actionlint clean on both files. CI should pick up the new state on push. TODOs still open (from the Phase 2 sub-agent's report): - build.yml not migrated. build-container.yml needs six additional inputs (custom tags fan-out, build-args, target, OCI labels, per-cell cache-scope, provenance/sbom) before the snipe-it track×composer matrix can call it. Follow-up PR upstream. - security.yml::trivy not migrated. Needs a tolerate-pull-failure step-level input on security-container.yml so callers can keep `continue-on-error: ${{ matrix.tag == 'rolling' }}` semantics (GitHub forbids continue-on-error on reusable-caller jobs). Follow-up PR upstream. - security.yml::osv-scanner stays inline (composer.lock extraction is snipe-it-specific). Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
SonarCloud's quality gate fails on 3 LOW hotspots — one per reusable call — with message "Use full commit SHA hash for this dependency". This is the same org-policy that already SHA-pins third-party actions in this repo; SonarCloud applies it to internal reusable workflow refs as well. Pinned all three to netresearch/.github main SHA 5ce9b7d44245a76416317ff3af38589f475e055f (current main, includes the v2.14.0 hadolint fix from PR 141 + one subsequent merge). Trade-off: SHA pin loses the auto-update benefit of `@main`. Two follow-ups make this less painful: 1. Renovate's github-actions manager can be configured to bump these refs — `netresearch/.github/.github/workflows/...@<sha>` matches its default detection patterns. 2. If `netresearch/.github` adopts tagged releases (`@v1`, `@v1.2`), we can switch to those and let `v1` be the moving major. Org-wide decision; the open question raised in PR 141's discovery is still on the table. For now, SHA pin satisfies SonarCloud + matches the existing third-party action convention in this repo. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
This reverts b38104d. Hard org policy from user: first-party reusable workflows (anything under netresearch/) are called with @main, never SHA-pinned. SHA-pinning defeats the central-reusables architecture by freezing every consumer to a snapshot — every reusable improvement would require a per-consumer SHA-bump PR. This is distinct from third-party actions (actions/checkout, docker/build-push-action, etc.) which DO get SHA-pinned per supply-chain policy. Different trust models. SonarCloud's 3 LOW hotspots ("Use full commit SHA hash for this dependency") are NOT addressed by this revert — they need to be addressed at the SonarCloud config layer: - Mark each as REVIEWED + SAFE via SonarCloud web UI (one click each; requires a project admin), OR - Disable the rule at Quality Profile level for this project, OR - Get the rule's hotspot equivalent in the project's Quality Gate configured so that org-internal reusable refs don't count. I cannot do any of those without a SonarCloud admin token. Surfacing this to the user as the next manual step. Captured in memory feedback (feedback_no_sha_pin_own_reusables.md) so this mistake doesn't repeat. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
|
Merged
3 tasks
CybotTM
added a commit
to netresearch/.github
that referenced
this pull request
May 22, 2026
…ure) (#143) ## Summary Two atomic commits, both unblock the Phase 2 caller migration in netresearch/snipe-it-docker-compose-stack#11 (build.yml + security.yml currently cannot delegate to these reusables because of input gaps). ### Commit 1 — build-container.yml: +7 inputs | Input | Type | Purpose | |---|---|---| | `target` | string | Multi-stage build target (snipe-it: `runtime`) | | `build-args` | string (multi-line) | Newline-separated KEY=VALUE for Dockerfile ARGs | | `cache-scope` | string | GHA cache scope name — parallel matrix cells stay separate | | `provenance` | string | Buildx provenance mode (snipe-it: `mode=max`) | | `sbom` | boolean | In-image SBOM (default false, backward compat) | | `metadata-tags` | string (multi-line) | Override metadata-action's `tags:` for bespoke fan-out | | `metadata-labels` | string (multi-line) | OCI labels appended to auto-generated set | Backward compatible: every new input has a safe default that preserves current behavior. The metadata-action's default 5 tag patterns are now computed in a shell step gated on `metadata-tags == ''`, then passed as a step output. Keeps the YAML expression-syntax simple without losing flexibility. ### Commit 2 — security-container.yml: +tolerate-pull-failure Boolean input. When true, the Trivy step gets `continue-on-error: true`. Use case: caller fans a matrix over tags where some images may not exist (rolling-variants blocked by composer audit). Job-level `continue-on-error:` on a reusable-caller is forbidden by GitHub, so only step-level (inside the reusable) works. Off by default → no behavioral change for existing callers. ## Caller migration sketch (snipe-it Phase 2 follow-up) ```yaml jobs: build: uses: netresearch/.github/.github/workflows/build-container.yml@main permissions: contents: read packages: write security-events: write id-token: write attestations: write with: image-name: snipe-it-php-fpm ref: ${{ steps.ref.outputs.ref }} target: runtime build-args: | SNIPE_IT_VERSION=${{ steps.ref.outputs.ref }} BUILD_DATE=${{ steps.ref.outputs.build_date }} VCS_REF=${{ github.sha }} ROLLING_DEPS=${{ matrix.composer == 'rolling' }} provenance: mode=max sbom: true cache-scope: ${{ matrix.track.name }}-${{ matrix.composer }} metadata-tags: ${{ steps.tags.outputs.tags }} attest: true sign: true security: uses: netresearch/.github/.github/workflows/security-container.yml@main permissions: contents: read security-events: write packages: read with: image-ref: ghcr.io/.../snipe-it-php-fpm:${{ matrix.tag }} tolerate-pull-failure: ${{ matrix.composer == 'rolling' }} ``` ## Verification - [x] `actionlint` clean on both modified files - [x] All new inputs default to backward-compatible values - [x] Signed commits + DCO + conventional-commit prefix ## After this lands - snipe-it-docker-compose-stack#11 can absorb the build.yml + security.yml migration as a follow-up commit. Realistic line-count for build.yml: ~301 → ~150 (matrix + ref-resolution + per-cell tag computation stay in the caller).
CybotTM
added a commit
that referenced
this pull request
May 22, 2026
…le (#13) ## Phase 3 of the container-CI consolidation Migrates `.github/workflows/security.yml`'s `trivy` job to the Phase-2.5-extended `security-container.yml@main` reusable in `netresearch/.github`. ## What migrated **`security.yml::trivy`** — now calls `netresearch/.github/.github/workflows/security-container.yml@main` with `tolerate-pull-failure: ${{ matrix.tag == 'rolling' }}`. The reusable's pre-flight `docker manifest inspect` probe replaces the previous job-level `continue-on-error: ${{ matrix.tag == 'rolling' }}` (which GitHub forbids on reusable-caller jobs anyway — actionlint rejects it). The behavioural contract is preserved: a missing rolling image short-circuits the Trivy + SARIF-upload steps and exits the job green, while legitimate Trivy finding-based failures (caller `exit-code: '1'`) still propagate normally because the reusable does NOT slap a broad `continue-on-error` on Trivy itself. Defaults of the reusable line up 1:1 with the previous inline values: `exit-code: 0`, `ignore-unfixed: true`, `vuln-type: os,library`, `severity: HIGH,CRITICAL`, `limit-severities-for-sarif: true`, `scanners: vuln`. No behavioural change beyond replacing the `continue-on-error` mechanism. SARIF category remains `trivy-${{ matrix.tag }}` so the GitHub Security tab grouping is unchanged. Line counts: `security.yml` 135 → 118 (-17). The `trivy` job block itself shrank from ~50 lines (steps: checkout + trivy-action + upload-sarif) to ~26 (matrix + `with:` block + permissions). ## What stays inline (and why) **`security.yml::osv-scanner`** — Per the explicit task constraint #11: composer.lock extraction (`docker pull` + `docker create` + `docker cp /var/www/html/composer.lock`) is Snipe-IT-specific (path + lock-file location are not generalisable) and the osv-scanner action itself doesn't fit the container reusable's surface. The job retains its own `continue-on-error: ${{ matrix.tag == 'rolling' }}` since it is NOT a reusable-caller job and the keyword is legal at the regular-job level. **`build.yml` — left inline as a follow-up upstream item.** Honest report: two independent blockers prevent a clean migration to `build-container.yml@main` right now. 1. **Job-level `continue-on-error: ${{ matrix.composer == 'rolling' }}` is forbidden on reusable-caller jobs** (same GitHub restriction we just worked around for trivy). The build-container reusable does not currently expose a `tolerate-build-failure` knob analogous to `tolerate-pull-failure` — and unlike the security side, rolling-build failures aren't a manifest-not-found case the reusable can pre-flight cheaply; they're caused by `composer audit` blocking inside the docker build, which is a build-time failure mode that needs different plumbing. 2. **Pre-build ref resolution + tag fan-out can't sit alongside `uses:`.** A reusable-caller job allows only `name`, `uses`, `with`, `secrets`, `needs`, `if`, `permissions`, `concurrency`, `strategy` — no inline `steps:`. The current `build.yml` does meaningful work in steps *before* the metadata + build calls: reads `.snipe-it-version` (tag track), calls `gh api repos/grokability/snipe-it/commits/{master,develop}` (branch tracks), computes the `{version, major, major_minor, date_tag, build_date}` outputs, then computes a custom tag-fan-out list (`8.5.0 / 8.5 / 8 / latest`, with `-rolling` suffixes when applicable). Refactoring this into a separate `compute` matrix job whose outputs feed the `build` matrix job via `needs:` + `outputs:` + `fromJSON` gymnastics would make the workflow MORE complex than the inline version, not less. Task description explicitly authorises leaving build.yml inline in this case. Proposed follow-up upstream PR on `netresearch/.github` (does not block this PR): add a `tolerate-build-failure: bool` input to `build-container.yml` that wraps the `Build and push` step in equivalent semantics (e.g. `continue-on-error: true` on the build step + a `steps.build.outcome != 'failure'` gate on attest/sign). Once that's available, the `build.yml` migration can be revisited — though the second blocker (caller-side ref resolution as steps) will likely keep build.yml inline regardless. The `metadata-tags` + `metadata-labels` + `build-args` + `cache-scope` + `target` + `provenance` + `sbom` inputs added in Phase 2.5 are all the reusable-side surface this caller would consume, and they're complete. ## Hard-constraint compliance `uses: netresearch/.github/.github/workflows/security-container.yml@main` — pinned to `@main`, no SHA pin on the org's own reusable (rule #3). All third-party action SHAs preserved verbatim (no new third-party action references introduced; we deleted some). SPDX header retained with "Netresearch DTT GmbH". Conventional-commit prefix on the commit. Signed + signed-off commit matching `git config user.name` / `user.email`. ## Verification - `actionlint .github/workflows/*.yml` — clean across all workflows. - `yamllint` with the snipe-it project config — only pre-existing comment-spacing warnings on SHA-pin comments (no new findings; net warnings down from 5 to 2 since 3 inline action references were removed). - `tail -c 2 .github/workflows/security.yml | xxd -p` → `6b0a` (single trailing newline, no double). - `git show --stat HEAD` confirms only `.github/workflows/security.yml` changed. CI run will exercise the new caller against the published `:latest` (present) and `:rolling` (currently failing builds → manifest absent → pre-flight skip path).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Phase 2 of the container-CI consolidation. Phase 1 reusables (lint-container, security-container, smoke-test-container) are now on
mainin netresearch/.github — PR netresearch/.github#141 merged at 7477e5e.What's migrated
lint.yml::container-lintlint-container.yml@mainsmoke-test.yml::image-surfacesmoke-test-container.yml@mainscorecard.ymlscorecard.yml@mainWhat STAYS in this caller (snipe-it-specific, doesn't generalise):
lint.yml::compose-validate—.env.exampleplaceholder substitution +docker compose config --quietlint.yml::yamllint— no.yamllint.ymlconfig in this repo, rules passed viaconfig_datasmoke-test.yml::{stack-boots-healthy,init.sh-is-idempotent,upstream-tests}— depend on snipe-it's.envshape + HTTP probesbuild.yml— track×composer matrix +.snipe-it-versionref resolution + tag fan-out +continue-on-error: rollingsecurity.yml::trivy— needscontinue-on-error: ${{ matrix.tag == 'rolling' }}which GitHub forbids on reusable-caller jobssecurity.yml::osv-scanner— composer.lock extraction is snipe-it-specificOpen dependencies (separate PRs upstream)
To migrate
build.ymlto the reusable,netresearch/.github/.github/workflows/build-container.ymlneeds six additional inputs: customtagsfan-out,build-args,target, OCIlabels, per-cellcache-scope,provenance: mode=max/sbom: true. Tracking as follow-up.To migrate
security.yml::trivy,security-container.ymlneeds a step-leveltolerate-pull-failureboolean input so callers can keep rolling-tag-may-not-exist semantics without using job-levelcontinue-on-error. Tracking as follow-up.Manual action required from a SonarCloud admin
The reusable refs use
@main(org policy: first-party reusables are NOT SHA-pinned). SonarCloud'sgithubactions:S7637rule ("Use full commit SHA hash for this dependency") flags these as 3 LOW security hotspots. Tried SHA-pinning in b38104d; reverted in 5aa57b9 per maintainer feedback ("WIR PINNEN UNSERE EIGENEN RE-USABLE WORKFLOWS NICHT").These cannot be marked via API without a SonarCloud admin token (not in this repo's secrets). Please mark them as REVIEWED + SAFE in the SonarCloud UI:
https://sonarcloud.io/project/security_hotspots?id=netresearch_snipe-it-docker-compose-stack&pullRequest=11
Or deactivate the rule for this project in its Quality Profile.
Test plan
HEALTHCHECK --start-intervalcorrectly)