Shared GitHub Actions workflows and default community health files
(SECURITY.md) for every repository under this account. Every job writes a
report to the run's step summary.
Publishes a multi-platform image to ghcr.io/<owner>/<repo>. Create
.github/workflows/build-and-push-image.yml file:
name: Build and push image
on:
push:
tags: ['*']
workflow_dispatch:
jobs:
build-and-push-image:
permissions:
contents: read
packages: write
uses: chenwei791129/.github/.github/workflows/build-and-push-image.yml@mainimage-name overrides the default <owner>/<repo> path, enable-semver-tags
turns off the built-in semver rules so additional-tags can define a different
shape, and build-args is passed straight through to the Dockerfile:
jobs:
build-and-push-image:
permissions:
contents: read
packages: write
uses: chenwei791129/.github/.github/workflows/build-and-push-image.yml@main
with:
image-name: chenwei791129/yourip
enable-semver-tags: false
additional-tags: |
type=semver,pattern=v{{version}}
type=raw,value=alpine,enable={{is_default_branch}}
build-args: |
BASE_IMAGE=php
IMAGE_VERSION=8.4.10-alpine3.22Other inputs: enable-branch-tag, enable-latest-tag, context, platforms
(default linux/amd64,linux/arm64) and runs-on.
file selects a Dockerfile other than <context>/Dockerfile. Call the workflow
once per variant, and give each variant's tags a per-rule suffix= so they do not
collide with the default image:
jobs:
build-fat:
permissions:
contents: read
packages: write
uses: chenwei791129/.github/.github/workflows/build-and-push-image.yml@main
with:
file: Dockerfile.fat
enable-branch-tag: false
enable-latest-tag: false
enable-semver-tags: false
additional-tags: |
type=semver,pattern={{version}},suffix=-fat
type=raw,value=fat,enable={{is_default_branch}}Images are pushed to ghcr.io only — Docker Hub support was removed deliberately,
so no registry secrets are needed beyond the automatic GITHUB_TOKEN.
sign-image: true keylessly signs the pushed digest with cosign. The calling job
must additionally grant id-token: write, which cosign exchanges for an
ephemeral certificate from the sigstore community Fulcio instance:
jobs:
build-and-push-image:
permissions:
contents: read
packages: write
id-token: write # cosign keyless signing
uses: chenwei791129/.github/.github/workflows/build-and-push-image.yml@main
with:
sign-image: trueSigning is skipped on pull_request, where nothing is pushed. cosign-version
pins the cosign release to install (default v3.1.3).
Create .github/workflows/trivy.yml file:
name: Trivy Security Scan
on:
pull_request:
branches:
- main
schedule:
- cron: "17 6 * * 1"
workflow_dispatch:
jobs:
trivy:
permissions:
contents: read # checkout the repository
security-events: write # upload SARIF results to the Security tab
uses: chenwei791129/.github/.github/workflows/trivy-scan.yml@main
with:
scanners: vuln
severity: HIGH,CRITICAL
upload-sarif: trueupload-sarif: true runs an extra non-failing pass and uploads the SARIF
report to the Security tab. The calling job must grant security-events: write,
and private repositories additionally need GitHub Advanced Security.
SARIF uploads use category trivy-<scan-type> by default (for example,
trivy-fs and trivy-image), so repository and image scans from the same
calling workflow do not overwrite one another. Existing callers need no changes.
The optional string input category overrides this value; omitting it or passing
an empty string uses the default. It only affects SARIF uploads, not the gating
scan or job summary.
The default category does not include the calling workflow, so it is shared
across the whole repository. Whenever the same scan type uploads SARIF more
than once — within one workflow (for example, two images) or from different
workflows (for example, a vulnerability scan in trivy.yml and a secret scan
in another workflow) — give each call a unique, stable category:
with:
scan-type: image
scan-ref: ghcr.io/owner/app:latest
upload-sarif: true
category: trivy-image-appIf a category is uploaded on the default branch but skipped on pull requests
(such as an image job guarded by if: github.event_name != 'pull_request'),
code scanning may warn on pull requests that a configuration from the default
branch was not found. This is expected and does not affect the uploaded results.
After adopting this change, verify the distinct analysis categories in the caller's Security tab after a scheduled or manual run. The analysis uploaded under the previous default category is not replaced, and its alerts stay open on the default branch. Once the new categories appear, delete the old configuration under Security → Code scanning → Tool status.
Create .github/workflows/secret-scan.yml file:
name: Secret Scan
on:
push:
branches: [main]
pull_request:
jobs:
trivy:
permissions:
contents: read
uses: chenwei791129/.github/.github/workflows/trivy-scan.yml@main
with:
scanners: secret
severity: CRITICAL,HIGHRuns release-please and exposes its outputs so build/upload jobs can chain on them. Create .github/workflows/release-please.yml file:
name: Release
on:
push:
branches: [main]
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
release-please:
permissions:
contents: write # create the release and tag
issues: write # label the release PR
pull-requests: write # open/update the release PR
uses: chenwei791129/.github/.github/workflows/release-please.yml@main
with:
release-type: go
build:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-26.04
steps:
- run: echo "Building ${{ needs.release-please.outputs.tag_name }}"Leave release-type empty to use the repository's release-please-config.json
and .release-please-manifest.json (manifest mode). target-branch is needed
only when the default branch is not the one that triggered the workflow (e.g.
master). Pass secrets: { token: ${{ secrets.MY_RELEASE_PLEASE_TOKEN }} }
when the branch is protected or when the created release must trigger other
workflows; the default GITHUB_TOKEN cannot do either.
Outputs: release_created, tag_name, version, sha, html_url,
upload_url, prs_created, pr.
Create .github/workflows/go-test.yml file:
name: Test
on:
push:
branches-ignore: [main]
pull_request:
branches: [main]
jobs:
test:
permissions:
contents: read
uses: chenwei791129/.github/.github/workflows/go-test.yml@mainInputs: go-version-file (default go.mod), working-directory, test-args
(default ./...; -count=1 is always added), vet (run go vet first),
cache and runs-on.