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
5 changes: 5 additions & 0 deletions .changeset/gentle-grapes-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zemd/gha": patch
---

Add zizmor integration
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ updates:
- "/internal/*"
schedule:
interval: "weekly"
# Match pnpm's release-age policy for npm packages.
cooldown:
default-days: 7 # pnpm-workspace.yaml: minimumReleaseAge / 1440
# Keep exemptions aligned with pnpm-workspace.yaml.
exclude:
- "@zemd/*"
versioning-strategy: "increase" # the workspace pins exact versions (saveExact)
open-pull-requests-limit: 10
groups:
Expand All @@ -24,6 +30,8 @@ updates:
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
open-pull-requests-limit: 10
groups:
github-actions:
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Copy-paste callers for the reusable workflows published from this repository.
| [`release.yml`](./release.yml) | `shared-release.yml` | Release pull request, npm publish, git tags, GitHub release |
| [`codeql.yml`](./codeql.yml) | `shared-codeql.yml` | CodeQL analysis |
| [`scorecard.yml`](./scorecard.yml) | `shared-scorecard.yml` | OpenSSF Scorecard |
| [`zizmor.yml`](./zizmor.yml) | `shared-zizmor.yml` | Blocking security lint for GitHub Actions and Dependabot |
| [`dependabot.yml`](./dependabot.yml) | — | Keeps the pinned SHAs current |

They assume a pnpm workspace with `lint-check`, `format-check`, `typecheck`,
Expand All @@ -17,7 +18,7 @@ those can be renamed or disabled through workflow inputs — see the commented

## Install

1. Copy the four workflow files into `.github/workflows/` of the target
1. Copy the five workflow files into `.github/workflows/` of the target
repository and `dependabot.yml` into `.github/`.

2. Replace the `__SHA__` placeholder with the commit of the release you want:
Expand Down Expand Up @@ -72,6 +73,9 @@ For npm **trusted publishing**:
the same `concurrency.group` on both sides with `cancel-in-progress: true`.
- Permissions can only be narrowed by the called workflow, never widened, which
is why each example declares them on the calling job.
- `shared-zizmor.yml` deliberately uses annotation output instead of SARIF so
any finding fails the job. Its weekly caller also catches advisories published
after an action was pinned; CodeQL remains the stateful code-scanning feed.
- `shared-release.yml` checks out the explicit `shared-tooling-repository` and
`shared-tooling-ref` into `.shared-ci/` to reach the bundled `gha.mjs` CLI.
Keep the ref equal to the SHA that pins the reusable workflow. The checkout is
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows-examples/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ jobs:
name: CodeQL
uses: zemd/js/.github/workflows/shared-codeql.yml@__SHA__ # v1
permissions:
contents: read
actions: read
security-events: write
contents: read # checkout the repository for analysis
actions: read # let CodeQL read workflow-run metadata
security-events: write # upload results to code scanning
# with:
# languages: '["actions", "javascript-typescript"]'
8 changes: 8 additions & 0 deletions .github/workflows-examples/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ updates:
- "/packages/*"
schedule:
interval: "weekly"
# Match pnpm's release-age policy for npm packages.
cooldown:
default-days: 7 # pnpm-workspace.yaml: minimumReleaseAge / 1440
# Keep exemptions aligned with pnpm-workspace.yaml.
exclude:
- "@zemd/*"
versioning-strategy: "increase" # the workspace pins exact versions (saveExact)
open-pull-requests-limit: 10
groups:
Expand All @@ -20,6 +26,8 @@ updates:
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
open-pull-requests-limit: 10
groups:
github-actions:
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows-examples/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ on:
branches:
- main

concurrency: ${{ github.workflow }}-${{ github.ref }}
# A release must finish once started; serialize runs without cancelling one that
# may already be publishing packages or moving tags.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
release:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows-examples/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
name: Scorecard
uses: zemd/js/.github/workflows/shared-scorecard.yml@__SHA__ # v1
permissions:
contents: read
actions: read
security-events: write
id-token: write
contents: read # checkout the repository for analysis
actions: read # inspect workflow runs for dangerous patterns
security-events: write # upload results to code scanning
id-token: write # publish results to the OpenSSF API
# with:
# publish-results: true
# artifact-retention-days: 5
29 changes: 29 additions & 0 deletions .github/workflows-examples/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: zizmor

permissions: {}

on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
# Re-check pinned actions when new advisories or stale-reference data lands.
- cron: "13 6 * * 1"
workflow_dispatch:

concurrency:
group: zizmor-${{ github.ref }}
cancel-in-progress: true

jobs:
zizmor:
name: zizmor
uses: zemd/js/.github/workflows/shared-zizmor.yml@__SHA__ # v1
permissions:
contents: read # checkout and online audits
# with:
# audit-inputs: "."
# persona: regular
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ jobs:
name: CodeQL
uses: ./.github/workflows/shared-codeql.yml
permissions:
contents: read
actions: read
security-events: write
contents: read # checkout the repository for analysis
actions: read # let CodeQL read workflow-run metadata
security-events: write # upload results to code scanning
14 changes: 9 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@ on:
branches:
- main

concurrency: ${{ github.workflow }}-${{ github.ref }}
# A release must finish once started; serialize runs without cancelling one that
# may already be publishing packages or moving tags.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
release:
name: Release
uses: ./.github/workflows/shared-release.yml
permissions:
contents: write
pull-requests: write
id-token: write
contents: write # release branch, git tags and GitHub releases
pull-requests: write # open and refresh the release pull request
id-token: write # npm trusted publishing (OIDC)
with:
shared-tooling-repository: ${{ github.repository }}
shared-tooling-ref: ${{ github.sha }}
Expand All @@ -31,7 +35,7 @@ jobs:
if: needs.release.outputs.pending == 'false'
runs-on: ubuntu-latest
permissions:
contents: write
contents: write # publish the shared workflow tags and GitHub release

steps:
- name: Checkout Repo
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
name: Scorecard
uses: ./.github/workflows/shared-scorecard.yml
permissions:
contents: read
actions: read
security-events: write
id-token: write
contents: read # checkout the repository for analysis
actions: read # inspect workflow runs for dangerous patterns
security-events: write # upload results to code scanning
id-token: write # publish results to the OpenSSF API
6 changes: 3 additions & 3 deletions .github/workflows/shared-codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
name: "Analyze: ${{ matrix.language }}"
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
security-events: write
contents: read # checkout the caller repository for analysis
actions: read # let CodeQL read workflow-run metadata
security-events: write # upload results to code scanning

strategy:
fail-fast: false
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/shared-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ jobs:
name: Version
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
contents: write # create or update the release branch
pull-requests: write # open and refresh the release pull request
outputs:
pending: ${{ steps.version.outputs.pending }}
steps:
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/shared-scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ jobs:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
contents: read
# Read the workflow run history that the Dangerous-Workflow checks rely on.
actions: read
security-events: write
# Publish the result to the OpenSSF REST API.
id-token: write
contents: read # checkout the caller repository for analysis
actions: read # inspect workflow runs for dangerous patterns
security-events: write # upload results to code scanning
id-token: write # publish results to the OpenSSF REST API

steps:
- name: Checkout Repo
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/shared-zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Shared zizmor

# Blocking GitHub Actions security linting for workflows, custom actions and
# Dependabot configuration. Call it from a repository with:
# uses: zemd/js/.github/workflows/shared-zizmor.yml@<sha> # v1

permissions: {}

on:
workflow_call:
inputs:
audit-inputs:
description: Whitespace-separated repository paths for zizmor to audit.
type: string
default: "."
persona:
description: zizmor audit persona; regular is the recommended CI default.
type: string
default: "regular"

jobs:
audit:
name: Audit GitHub Actions
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read # checkout and online audits, including private callers

steps:
- name: Checkout Repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# Plain/annotation output preserves zizmor's non-zero finding exit codes.
# SARIF mode always exits zero for findings and is therefore not a merge gate.
- name: Run zizmor
uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2
with:
inputs: ${{ inputs.audit-inputs }}
collect: default
online-audits: true
persona: ${{ inputs.persona }}
version: "1.29.0"
advanced-security: false
annotations: true
fail-on-no-inputs: true
30 changes: 30 additions & 0 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: zizmor

permissions: {}

on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
# Re-check pinned actions when new advisories or stale-reference data lands.
- cron: "13 6 * * 1"
workflow_dispatch:

concurrency:
group: zizmor-${{ github.ref }}
cancel-in-progress: true

jobs:
zizmor:
name: zizmor
uses: ./.github/workflows/shared-zizmor.yml
permissions:
contents: read # checkout and online audits
with:
# This provider keeps its own workflow contract free of code smells as
# well as regular security findings. Consumers default to regular.
persona: pedantic
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ yarn-error.log*

# release
pnpm-publish-summary.json
.pnpm-store
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ All tasks are orchestrated by [Turborepo](https://turborepo.com) and run across
| `pnpm format-check` | Verify formatting without writing changes |
| `pnpm lint` | Run type-aware linting and auto-fix with `oxlint` |
| `pnpm lint-check` | Run type-aware linting and fail on warnings |
| `pnpm lint-actions` | Audit GitHub Actions with `zizmor` |
| `pnpm lint-publish` | Validate publishable package metadata (`publint`) |

`pnpm lint-actions` requires [`zizmor`](https://docs.zizmor.sh/installation/)
1.29.0, matching the exact version pinned by CI. Set `GH_TOKEN` (for example,
from `gh auth token`) to include online audits when running it locally.

To run a script for a single package, use the workspace filter:

```sh
Expand All @@ -72,7 +77,7 @@ To report a vulnerability, follow [`SECURITY.md`](SECURITY.md).

## Contributing

Issues and pull requests are welcome. Before opening a PR, please make sure that `pnpm lint-check`, `pnpm format-check`, `pnpm typecheck`, and `pnpm test` all pass.
Issues and pull requests are welcome. Before opening a PR, please make sure that `pnpm lint-check`, `pnpm lint-actions`, `pnpm format-check`, `pnpm typecheck`, and `pnpm test` all pass.

## License

Expand Down
Loading