diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f96a7b4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: build + +# Build check: GoReleaser snapshot build of everything, publishing nothing, +# then package validation. The `build` job is the required status check. + +on: + pull_request: + +permissions: + contents: read + +jobs: + goreleaser: + uses: OpenCHAMI/github-actions/.github/workflows/build-check-goreleaser.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + go-version-file: go.mod + + validate: + needs: goreleaser + uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + packages: | + - name: testbed-quadlet*.rpm + files: + - /etc/openchami + - /etc/openchami/configs + - /etc/openchami/configs/testbed.yaml + - /usr/share/containers/systemd/testbed.container + - /usr/share/containers/systemd/testbed.container.d + - /usr/share/containers/systemd/testbed.container.d/10-defaults.conf + - /usr/share/licenses/testbed-quadlet + - /usr/share/licenses/testbed-quadlet/MIT.txt + - name: testbed-quadlet*.deb + files: + - /etc/openchami/configs/testbed.yaml + - /usr/share/containers/systemd/testbed.container + - /usr/share/containers/systemd/testbed.container.d/10-defaults.conf + - /usr/share/doc/testbed-quadlet/copyright + + build: + if: ${{ always() }} + needs: [goreleaser, validate] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml new file mode 100644 index 0000000..a94f259 --- /dev/null +++ b/.github/workflows/cleanup.yml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: cleanup + +# Deletes the pr- images when a PR closes. + +on: + pull_request: + types: [closed] + +permissions: + packages: write + +jobs: + cleanup: + uses: OpenCHAMI/github-actions/.github/workflows/pr-registry-cleanup.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..5e3b672 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: dependency-review +on: + pull_request: + +permissions: + contents: read + +jobs: + check: + uses: OpenCHAMI/github-actions/.github/workflows/dependency-review.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + permissions: + contents: read # baseline for checkout + pull-requests: write # summary comment on the PR + + dependency-review: + if: ${{ always() }} + needs: [check] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml new file mode 100644 index 0000000..166afeb --- /dev/null +++ b/.github/workflows/govulncheck.yml @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: govulncheck +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + check: + uses: OpenCHAMI/github-actions/.github/workflows/govulncheck.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + + govulncheck: + if: ${{ always() }} + needs: [check] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..f2ba4de --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: lint + +# All linters under one gate: the `lint` job is the required status check. + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + lint-go: + uses: OpenCHAMI/github-actions/.github/workflows/lint-go.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + go-version-file: go.mod + + lint-ci: + uses: OpenCHAMI/github-actions/.github/workflows/lint-ci.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + permissions: + contents: read # baseline for checkout + security-events: write # zizmor SARIF upload to GHAS + + lint: + if: ${{ always() }} + needs: [lint-go, lint-ci] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6950544 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,94 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: release + +# PR images and releases; build-release-goreleaser picks the mode from the +# event: +# - pull_request: pushes ghcr.io/openchami/github-actions-testbed:pr-. +# - v* tag push: semver images, signed packages, draft release, validation, +# then publish. Safe to tag freely: nothing depends on this repo. + +on: + pull_request: + push: + tags: + - v* + +permissions: + contents: read + +jobs: + # Throwaway signing key, regenerated each run. Not a secret (it travels as + # a job output); fine here, since the packages are only for testing. + test-key: + runs-on: ubuntu-slim + outputs: + gpg-key-b64: ${{ steps.key.outputs.gpg-key-b64 }} + steps: + - name: Generate throwaway GPG key + id: key + run: | + set -euo pipefail + GNUPGHOME=$(mktemp -d) + export GNUPGHOME + gpg --batch --quiet --passphrase '' \ + --quick-gen-key 'github-actions testbed throwaway key ' rsa3072 sign 1d + echo "gpg-key-b64=$(gpg --batch --armor --export-secret-keys | base64 -w0)" >> "$GITHUB_OUTPUT" + + goreleaser: + needs: test-key + permissions: + contents: write # release creation, uploading assets + packages: write # image push, container provenance + id-token: write # Sigstore signing (attest-build-provenance) + attestations: write # build provenance attestations + uses: OpenCHAMI/github-actions/.github/workflows/build-release-goreleaser.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + go-version-file: go.mod + registry-subject-name: ghcr.io/openchami/github-actions-testbed + secrets: + gpg-key: ${{ github.event_name == 'push' && needs.test-key.outputs.gpg-key-b64 || '' }} + + trivy: + # Fork PRs build but don't push, so there is no image to scan. + needs: goreleaser + if: ${{ needs.goreleaser.outputs.digest != '' }} + uses: OpenCHAMI/github-actions/.github/workflows/trivy-image-scan.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + permissions: + contents: read # baseline for checkout + security-events: write # SARIF upload to GHAS + with: + image-ref: ghcr.io/openchami/github-actions-testbed@${{ needs.goreleaser.outputs.digest }} + exit-code: '0' + + validate: + # PR builds produce no packages (they're validated in build.yml). + if: ${{ github.event_name == 'push' }} + needs: goreleaser + uses: OpenCHAMI/github-actions/.github/workflows/validate-packages.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + packages: | + - name: testbed-quadlet*.rpm + files: + - /etc/openchami + - /etc/openchami/configs + - /etc/openchami/configs/testbed.yaml + - /usr/share/containers/systemd/testbed.container + - /usr/share/containers/systemd/testbed.container.d + - /usr/share/containers/systemd/testbed.container.d/10-defaults.conf + - /usr/share/licenses/testbed-quadlet + - /usr/share/licenses/testbed-quadlet/MIT.txt + - name: testbed-quadlet*.deb + files: + - /etc/openchami/configs/testbed.yaml + - /usr/share/containers/systemd/testbed.container + - /usr/share/containers/systemd/testbed.container.d/10-defaults.conf + - /usr/share/doc/testbed-quadlet/copyright + + publish: + if: ${{ github.event_name == 'push' }} + needs: [goreleaser, validate] + permissions: + contents: write # publish the draft GitHub Release + uses: OpenCHAMI/github-actions/.github/workflows/publish-release.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml new file mode 100644 index 0000000..57e41ae --- /dev/null +++ b/.github/workflows/reuse.yml @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: reuse +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + check: + uses: OpenCHAMI/github-actions/.github/workflows/reuse.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + + reuse: + if: ${{ always() }} + needs: [check] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..14b36d4 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: scorecard +on: + branch_protection_rule: + pull_request: + push: + branches: [main] + schedule: + - cron: '39 5 * * 1' + +permissions: + contents: read + +jobs: + check: + permissions: + contents: read # baseline for checkout + security-events: write # SARIF upload to GHAS + id-token: write # publish results to the OpenSSF dashboard + uses: OpenCHAMI/github-actions/.github/workflows/scorecard.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + + scorecard: + if: ${{ always() }} + needs: [check] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..e02ba6b --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: stale +on: + schedule: + - cron: '23 3 * * *' # daily at 03:23 UTC + workflow_dispatch: + +permissions: + contents: read + +jobs: + stale: + uses: OpenCHAMI/github-actions/.github/workflows/stale.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + permissions: + issues: write # label, comment on, and close stale issues + pull-requests: write # label, comment on, and close stale PRs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ad875cf --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +name: test + +# All tests under one gate: the `test` job is the required status check. +# Unit tests also upload coverage to Coveralls (README badge); the repo must +# be enrolled in Coveralls. + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + test-unit-go: + uses: OpenCHAMI/github-actions/.github/workflows/test-unit-go.yml@5b8f3decfae1c29ef4004a6f49f1593d25eccc95 # github-actions under test (seantronsen/feat/redesign-deployment) + with: + go-version-file: go.mod + coverage: true + + test: + if: ${{ always() }} + needs: [test-unit-go] + runs-on: ubuntu-slim + steps: + - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0 + with: { jobs: "${{ toJSON(needs) }}" } diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..6feb306 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,132 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT +# +# Exercises every release effect of the OpenCHAMI/github-actions GoReleaser +# workflows. Annotated reference: +# https://github.com/OpenCHAMI/github-actions/blob/main/.goreleaser.example.yml + +version: 2 + +project_name: github-actions-testbed + +before: + hooks: + - go mod tidy + # Pin the packaged quadlet to the image this run publishes. + - make quadlet-render IMAGE_TAG={{ .Tag }} + +builds: + - id: testbed + main: ./cmd/testbed + binary: testbed + goos: [linux] + goarch: [amd64, arm64] + env: + - CGO_ENABLED=0 + ldflags: + - >- + -s -w + -X main.version={{ .Version }} + -X main.commit={{ .Commit }} + -X main.buildHost={{ .Env.BUILD_HOST }} + +archives: + - id: testbed + ids: [testbed] + formats: [tar.gz] + files: + - LICENSES/* + +checksum: + name_template: "{{ .ProjectName }}_checksums.txt" + +dockers_v2: + - id: testbed + ids: [testbed] + dockerfile: Dockerfile + images: + - ghcr.io/openchami/github-actions-testbed + tags: + - "{{ .Tag }}" # vX.Y.Z or pr-N + - '{{ if ne .Env.IS_PR_BUILD "true" }}{{ .Major }}.{{ .Minor }}{{ end }}' + - '{{ if ne .Env.IS_PR_BUILD "true" }}{{ .Major }}{{ end }}' + - '{{ if ne .Env.IS_PR_BUILD "true" }}latest{{ end }}' + platforms: + - linux/amd64 + - linux/arm64 + labels: + org.opencontainers.image.title: "{{ .ProjectName }}" + org.opencontainers.image.version: "{{ .Version }}" + org.opencontainers.image.revision: "{{ .FullCommit }}" + org.opencontainers.image.created: "{{ .Date }}" + org.opencontainers.image.source: https://github.com/OpenCHAMI/github-actions-testbed + +nfpms: + - id: testbed-quadlet + package_name: testbed-quadlet + meta: true + formats: [rpm, deb] + file_name_template: "{{ .ConventionalFileName }}" + vendor: OpenCHAMI + homepage: https://github.com/OpenCHAMI/github-actions-testbed + maintainer: "Sean Tronsen " + description: Podman Quadlet test package for the OpenCHAMI github-actions workflows. + license: MIT + section: admin + contents: + - dst: /etc/openchami + type: dir + - dst: /etc/openchami/configs + type: dir + - src: packaging/configs/testbed.yaml + dst: /etc/openchami/configs/testbed.yaml + type: "config|noreplace" + - src: build/quadlet/testbed.container + dst: /usr/share/containers/systemd/testbed.container + - dst: /usr/share/containers/systemd/testbed.container.d + type: dir + - src: packaging/systemd/testbed.container.d/10-defaults.conf + dst: /usr/share/containers/systemd/testbed.container.d/10-defaults.conf + - dst: /usr/share/licenses/testbed-quadlet + type: dir + packager: rpm + - src: LICENSES/MIT.txt + dst: /usr/share/licenses/testbed-quadlet/MIT.txt + type: license + packager: rpm + - src: packaging/deb/copyright + dst: /usr/share/doc/testbed-quadlet/copyright + packager: deb + scripts: + postinstall: packaging/scripts/postinstall.sh + preremove: packaging/scripts/preremove.sh + postremove: packaging/scripts/postremove.sh + overrides: + rpm: + release: "1.el9" + dependencies: + - podman >= 5.0.0 + - systemd + deb: + release: "1" + dependencies: + - podman (>= 5.0.0) + - systemd + rpm: + signature: + key_file: "{{ .Env.GPG_KEY_PATH }}" + +release: + disable: '{{ if eq .Env.IS_PR_BUILD "true" }}true{{ else }}false{{ end }}' + name_template: "v{{ .Version }}" + prerelease: auto + footer: | + ## Verifying packages + + ```bash + rpm --import gpg-public-key.asc + rpm -K testbed-quadlet-*.rpm + ``` + +changelog: + use: git diff --git a/packaging/configs/testbed.yaml b/packaging/configs/testbed.yaml new file mode 100644 index 0000000..5884a6c --- /dev/null +++ b/packaging/configs/testbed.yaml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +# Example config shipped as %config(noreplace) / a deb conffile. +greeting: hello diff --git a/packaging/deb/copyright b/packaging/deb/copyright new file mode 100644 index 0000000..298dc4b --- /dev/null +++ b/packaging/deb/copyright @@ -0,0 +1,25 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: github-actions-testbed +Source: https://github.com/OpenCHAMI/github-actions-testbed + +Files: * +Copyright: 2026 OpenCHAMI a Series of LF Projects, LLC +License: MIT + MIT License + . + Copyright (c) 2026 OpenCHAMI a Series of LF Projects, LLC + . + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + associated documentation files (the "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the + following conditions: + . + The above copyright notice and this permission notice shall be included in all copies or substantial + portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO + EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packaging/deb/copyright.license b/packaging/deb/copyright.license new file mode 100644 index 0000000..380948c --- /dev/null +++ b/packaging/deb/copyright.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +SPDX-License-Identifier: MIT diff --git a/packaging/scripts/postinstall.sh b/packaging/scripts/postinstall.sh new file mode 100644 index 0000000..f76766f --- /dev/null +++ b/packaging/scripts/postinstall.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT +# +# Shared by the rpm (%post) and deb (postinst) packages. $1 tells them apart: +# rpm passes the instance count (1 = install, 2+ = upgrade); deb passes +# "configure", with the previously configured version in $2 on upgrade. + +upgrade= +case "$1" in + configure) [ -n "$2" ] && upgrade=1 ;; + [0-9]*) [ "$1" -ge 2 ] && upgrade=1 ;; +esac + +systemctl daemon-reload || : +if [ -n "$upgrade" ]; then + systemctl try-restart testbed.service || : +fi diff --git a/packaging/scripts/postremove.sh b/packaging/scripts/postremove.sh new file mode 100644 index 0000000..ddb517c --- /dev/null +++ b/packaging/scripts/postremove.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT +# +# Shared by the rpm (%postun) and deb (postrm) packages. + +systemctl daemon-reload || : diff --git a/packaging/scripts/preremove.sh b/packaging/scripts/preremove.sh new file mode 100644 index 0000000..50605ee --- /dev/null +++ b/packaging/scripts/preremove.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT +# +# Shared by the rpm (%preun) and deb (prerm) packages. Stop the service only +# on real removal: rpm passes 0, deb passes "remove". + +case "$1" in + 0|remove) + systemctl stop testbed.service >/dev/null 2>&1 || : + ;; +esac diff --git a/packaging/systemd/testbed.container b/packaging/systemd/testbed.container new file mode 100644 index 0000000..74e7ef0 --- /dev/null +++ b/packaging/systemd/testbed.container @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +[Unit] +Description=OpenCHAMI github-actions testbed container + +[Container] +ContainerName=%N +Image=ghcr.io/openchami/github-actions-testbed:@IMAGE_TAG@ + +[Service] +Restart=on-failure + +[Install] +WantedBy=default.target diff --git a/packaging/systemd/testbed.container.d/10-defaults.conf b/packaging/systemd/testbed.container.d/10-defaults.conf new file mode 100644 index 0000000..28dd851 --- /dev/null +++ b/packaging/systemd/testbed.container.d/10-defaults.conf @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT + +[Container] +Environment=TESTBED=1