Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/0-local-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ jobs:
permissions:
contents: read # baseline for checkout
security-events: write # zizmor SARIF upload to GHAS

lint-renovate:
uses: $/.github/workflows/lint-renovate.yml
84 changes: 84 additions & 0 deletions .github/workflows/lint-codegen-fabrica.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC
# SPDX-License-Identifier: MIT

name: lint-codegen-fabrica

# Reusable workflow that fails when a Fabrica project's committed generated
# code has drifted, by running the caller's `make generate-check` with a
# Fabrica built from source (passed as LOCAL_FABRICA). Fabrica stamps its
# version into generated code and only a source build carries that version;
# a `go run` build reports "dev" and always fails the check.

on:
workflow_call:
inputs:
go-version:
description: 'Go version to use (e.g. "1.26.7", "stable"). Mutually exclusive with go-version-file.'
required: false
type: string
go-version-file:
description: 'Path to a go.mod or .go-version file containing the Go version. Mutually exclusive with go-version.'
required: false
type: string
fabrica-ref:
description: 'Fabrica tag, branch, or commit SHA to build (default: version in go.mod)'
required: false
type: string
default: ''

permissions:
contents: read # baseline for checkout

jobs:
lint-codegen-fabrica:
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ inputs.go-version || (inputs.go-version-file == '' && 'stable' || '') }}
go-version-file: ${{ inputs.go-version-file || '' }}

- name: Resolve Fabrica ref
id: fabrica-ref
env:
FABRICA_REF: ${{ inputs.fabrica-ref }}
run: |
version="$FABRICA_REF"
if [[ -z "$version" ]]; then
version=$(go mod edit -json | jq -r '
.Require[]?
| select(.Path == "github.com/openchami/fabrica")
| .Version
')
if [[ -z "$version" ]]; then
echo "::error::fabrica-ref not set and no github.com/openchami/fabrica version found in go.mod"
exit 1
fi
fi
# Resolve the tag, branch, commit, or pseudo-version to the commit it names
if ! ref=$(go list -mod=mod -m -json "github.com/openchami/fabrica@${version}" |
jq -er '.Origin.Hash | select(type == "string" and test("^[0-9a-f]{40}$"))'); then
echo "::error::Could not resolve Fabrica ref: ${version}"
exit 1
fi
echo "Using Fabrica ref: ${ref}"
echo "ref=${ref}" >> "$GITHUB_OUTPUT"
- name: Checkout Fabrica
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: openchami/fabrica
ref: ${{ steps.fabrica-ref.outputs.ref }}
Comment thread
synackd marked this conversation as resolved.
path: fabrica
fetch-depth: 0 # full history + tags so `git describe` stamps the same version as a local build
persist-credentials: false
- name: Build Fabrica
working-directory: fabrica
run: make build
- name: Verify generated code is committed
run: |
make generate-check \
LOCAL_FABRICA="$GITHUB_WORKSPACE/fabrica" \
FABRICA_SOURCE_ARG="--fabrica-source $GITHUB_WORKSPACE/fabrica --force"
46 changes: 46 additions & 0 deletions .github/workflows/lint-renovate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC
# SPDX-License-Identifier: MIT

name: lint-renovate

# Reusable workflow that validates the caller's Renovate config with
# renovate-config-validator. With no config-file, the validator checks every
# config file it finds in the repository (renovate.json, .github/renovate.json,
# renovate.json5, .renovaterc, ...).

on:
workflow_call:
inputs:
renovate-version:
description: 'Renovate npm version that provides renovate-config-validator'
required: false
type: string
default: '44.115.13'
config-file:
description: 'Config file to validate (default: every Renovate config file found in the repo)'
required: false
type: string
default: ''

permissions:
contents: read # baseline for checkout

jobs:
lint-renovate:
runs-on: ubuntu-slim
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
- name: Validate Renovate config
env:
RENOVATE_VERSION: ${{ inputs.renovate-version }}
CONFIG_FILE: ${{ inputs.config-file }}
run: |
# --no-global: validate as repository config, not self-hosted config.
npx --yes --package "renovate@${RENOVATE_VERSION}" -- \
renovate-config-validator --no-global ${CONFIG_FILE:+"$CONFIG_FILE"}
92 changes: 92 additions & 0 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# SPDX-FileCopyrightText: © 2026 OpenCHAMI a Series of LF Projects, LLC
# SPDX-License-Identifier: MIT

name: stale

# Reusable workflow that marks and closes inactive issues and PRs with the
# org-default actions/stale policy. Callers own the schedule (a reusable
# workflow can't schedule itself).

on:
workflow_call:
inputs:
days-before-stale:
description: 'Days of inactivity before an issue or PR is marked stale'
required: false
type: number
default: 35
days-before-close:
description: 'Days after being marked stale before an issue or PR is closed'
required: false
type: number
default: 7
stale-issue-label:
description: 'Label applied to stale issues'
required: false
type: string
default: 'stale'
stale-pr-label:
description: 'Label applied to stale PRs'
required: false
type: string
default: 'stale'
exempt-issue-labels:
description: 'Comma-separated labels that exempt an issue from going stale'
required: false
type: string
default: 'pinned,security,help wanted'
exempt-pr-labels:
description: 'Comma-separated labels that exempt a PR from going stale'
required: false
type: string
default: 'pinned,security'
operations-per-run:
description: 'Maximum GitHub API operations per run'
required: false
type: number
default: 500
stale-issue-message:
description: 'Comment posted when an issue is marked stale'
required: false
type: string
default: >-
This issue has been automatically marked as stale due to inactivity.
Please add a comment or label to keep it open; otherwise it will close in 7 days.
close-issue-message:
description: 'Comment posted when a stale issue is closed'
required: false
type: string
default: 'Closing due to inactivity. Feel free to reopen with new information.'
stale-pr-message:
description: 'Comment posted when a PR is marked stale'
required: false
type: string
default: 'This PR has been marked stale due to inactivity. Comment or push changes to keep it open.'
close-pr-message:
description: 'Comment posted when a stale PR is closed'
required: false
type: string
default: 'Closing due to inactivity. Please reopen when it’s ready again.'

permissions:
issues: write # label, comment on, and close stale issues
pull-requests: write # label, comment on, and close stale PRs

jobs:
stale:
runs-on: ubuntu-slim
steps:
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
with:
days-before-stale: ${{ inputs.days-before-stale }}
days-before-close: ${{ inputs.days-before-close }}
stale-issue-label: ${{ inputs.stale-issue-label }}
stale-pr-label: ${{ inputs.stale-pr-label }}
exempt-issue-labels: ${{ inputs.exempt-issue-labels }}
exempt-pr-labels: ${{ inputs.exempt-pr-labels }}
operations-per-run: ${{ inputs.operations-per-run }}
remove-stale-when-updated: true
stale-issue-message: ${{ inputs.stale-issue-message }}
close-issue-message: ${{ inputs.close-issue-message }}
stale-pr-message: ${{ inputs.stale-pr-message }}
close-pr-message: ${{ inputs.close-pr-message }}
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Reusable GitHub Actions for CI/CD.
- `.github/workflows/trivy-image-scan.yml`: Reusable workflow that scans built container images for CVEs
- `.github/workflows/scorecard.yml`: Reusable workflow that runs the OpenSSF Scorecard supply-chain analysis
- `.github/workflows/pr-registry-cleanup.yml`: Deletes the GHCR container images a PR published, once it closes
- `.github/workflows/stale.yml`: Reusable workflow that marks and closes inactive issues and PRs (org-default policy)
- `.github/workflows/lint-codegen-fabrica.yml`: Reusable workflow that fails when a Fabrica project's committed generated code is out of date

### Workflow naming

Expand Down Expand Up @@ -369,6 +371,80 @@ jobs:
# tag-prefix: pr-
```

### stale (Reusable Workflow)
Marks issues and PRs stale after a period of inactivity and closes them if nothing changes, using the org-default `actions/stale` policy (stale after 35 days, closed 7 days later; `pinned`/`security` items exempt). Updating an item removes the stale label. The caller owns the schedule.

**Usage:**
```yaml
name: Stale
on:
schedule:
- cron: '23 3 * * *' # daily at 03:23 UTC
workflow_dispatch:

jobs:
stale:
uses: OpenCHAMI/github-actions/.github/workflows/stale.yml@v4.0
permissions:
issues: write
pull-requests: write
# Optional overrides:
# with:
# days-before-stale: 35
# days-before-close: 7
# stale-issue-label: stale
# stale-pr-label: stale
# exempt-issue-labels: pinned,security,help wanted
# exempt-pr-labels: pinned,security
# operations-per-run: 500
# stale-issue-message: ...
# close-issue-message: ...
# stale-pr-message: ...
# close-pr-message: ...
```

### lint-codegen-fabrica (Reusable Workflow)
Fails when a Fabrica project's committed generated code is out of date by running the caller's `make generate-check` with Fabrica built from source (passed as `LOCAL_FABRICA`), at the version pinned in `go.mod` unless `fabrica-ref` (tag, branch, or commit SHA) is set. A source build is required: Fabrica stamps its version into generated code, and a `go run` build reports `dev` instead.

**Usage:**
```yaml
name: Lint Codegen
on:
pull_request:
branches: [main]
workflow_dispatch:

jobs:
lint-codegen:
uses: OpenCHAMI/github-actions/.github/workflows/lint-codegen-fabrica.yml@v4.0
# Optional overrides:
# with:
# go-version: stable # mutually exclusive with go-version-file
# go-version-file: go.mod
# fabrica-ref: v0.4.5 # tag, branch, or SHA; default: version in go.mod
```

### lint-renovate (Reusable Workflow)
Validates the caller's Renovate config with `renovate-config-validator` (as repository config). With no `config-file`, it checks every Renovate config file it finds (`renovate.json`, `.github/renovate.json`, `renovate.json5`, `.renovaterc`, ...).

**Usage:**
```yaml
name: Lint Renovate
on:
pull_request:
paths:
- renovate.json
- .github/workflows/lint-renovate.yml

jobs:
lint-renovate:
uses: OpenCHAMI/github-actions/.github/workflows/lint-renovate.yml@v4.0
# Optional overrides:
# with:
# renovate-version: 44.115.13
# config-file: renovate.json
```

## Actions

### gpg-configure-release-keys
Expand Down
16 changes: 16 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,21 @@
"extends": [
"github>OpenCHAMI/.github//renovate-config/default",
"config:recommended"
],
"customManagers": [
{
"customType": "regex",
"description": "Default renovate-config-validator version in lint-renovate and its README example",
"managerFilePatterns": [
"/^\\.github/workflows/lint-renovate\\.yml$/",
"/^README\\.md$/"
],
"matchStrings": [
"renovate-version:\\s*\\n(?:\\s+[a-z]+:.*\\n)*?\\s+default: '(?<currentValue>\\d+\\.\\d+\\.\\d+)'",
"#\\s+renovate-version: (?<currentValue>\\d+\\.\\d+\\.\\d+)"
],
"depNameTemplate": "renovate",
"datasourceTemplate": "npm"
}
]
}
Loading