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
72 changes: 56 additions & 16 deletions .github/workflows/ingest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,28 @@ on:
- cron: "20 8 * * *"
workflow_dispatch:

permissions:
contents: write
pull-requests: write
defaults:
run:
shell: bash -xeuo pipefail {0}

concurrency:
group: ingest

env:
HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1

permissions: {}

jobs:
match:
if: github.ref == 'refs/heads/main'
name: Match advisory candidates
if: github.repository_owner == 'Homebrew' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write # Push the bot-owned candidate branch.
pull-requests: write # Open a pull request for that branch.
# Local Aug 2026 measurement with --no-history and the trimmed
# data/repology.json (select_ecosystems + overrides.yml skip applied):
# 90820 records in 126.4 min, peak RSS 1.68 GB.
Expand All @@ -33,15 +47,15 @@ jobs:
uses: Homebrew/actions/setup-ruby@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
bundler-cache: true
portable-ruby: true

- name: Runner diagnostics
run: free -m && df -h

- name: Match advisories
# Step-scoped: setup-homebrew unsets this so brew install can use the API.
env:
HOMEBREW_NO_AUTO_UPDATE: "1"
HOMEBREW_NO_INSTALL_FROM_API: "1"
HOMEBREW_DEVELOPER: "1"
HOMEBREW_NO_INSTALL_FROM_API: 1
# --no-history: the FormulaVersions walk for every :fixed hit across
# ~8500 formulae would exceed the job limit. New records get
# `fixed: <current pkg_version>` which reviewers tighten per
Expand All @@ -54,26 +68,52 @@ jobs:
- name: Concatenate advisories
run: bundle exec rake advisories:concat

- name: Open pull request
- name: Configure git
uses: Homebrew/actions/git-user-config@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
username: github-actions[bot]

- name: Commit advisories
id: commit
env:
GITHUB_TOKEN: ${{ github.token }}
BRANCH: matched-advisories
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add advisories/ data/
if git diff --cached --quiet; then
echo "No changes."
exit 0
fi
gh auth setup-git --hostname github.com --force
git checkout -b "$BRANCH"
git checkout -b "${BRANCH}"
git commit -m "Matched advisory candidates"
git push --force origin "HEAD:refs/heads/$BRANCH"
if [ -n "$(gh pr list --head "$BRANCH" --state open --json number --jq '.[].number')" ]; then
{
echo "branch=${BRANCH}"
echo "committed=true"
} >> "${GITHUB_OUTPUT}"

- name: Push commits
if: steps.commit.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
token: ${{ github.token }}
branch: ${{ steps.commit.outputs.branch }}
# No lease: rebuilt from main each run, and no remote-tracking ref exists.
force: true
no_lease: true
origin_branch: HEAD

- name: Open pull request
if: steps.commit.outputs.committed == 'true'
env:
GITHUB_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.commit.outputs.branch }}
run: |
open_pr_number="$(gh pr list --head "${BRANCH}" --state open \
--json number,isCrossRepository \
--jq '.[] | select(.isCrossRepository | not) | .number')"
if [[ -n "${open_pr_number}" ]]; then
echo "PR already open."
else
gh pr create --base main --head "$BRANCH" \
gh pr create --base main --head "${BRANCH}" \
--title "Matched advisory candidates" \
--body "Automated candidates via \`brew advisory-match --all\`. See [CONTRIBUTING.md](https://github.com/${GITHUB_REPOSITORY}/blob/HEAD/CONTRIBUTING.md#reviewing-matched-candidates) for the review checklist."
fi
73 changes: 57 additions & 16 deletions .github/workflows/regenerate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,29 @@ on:
- cron: "20 6 * * *"
workflow_dispatch:

permissions:
contents: write
pull-requests: write
defaults:
run:
shell: bash -xeuo pipefail {0}

concurrency:
group: regenerate

env:
HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1

permissions: {}

jobs:
regenerate:
if: github.ref == 'refs/heads/main'
name: Regenerate advisories
if: github.repository_owner == 'Homebrew' && github.ref == 'refs/heads/main'
runs-on: macos-latest
timeout-minutes: 180
permissions:
contents: write # Push the bot-owned regeneration branch.
pull-requests: write # Open a pull request for that branch.
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -25,6 +40,7 @@ jobs:
uses: Homebrew/actions/setup-ruby@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
bundler-cache: true
portable-ruby: true

- name: Run tests
run: bundle exec rake spec
Expand All @@ -33,35 +49,60 @@ jobs:
run: bundle exec rake repology:build

- name: Regenerate advisories
# Step-scoped: setup-homebrew unsets this so brew install can use the API.
env:
HOMEBREW_NO_AUTO_UPDATE: "1"
HOMEBREW_NO_INSTALL_FROM_API: "1"
HOMEBREW_DEVELOPER: "1"
HOMEBREW_NO_INSTALL_FROM_API: 1
run: brew generate-vulns-advisories advisories

- name: Concatenate advisories
run: bundle exec rake advisories:concat

- name: Open pull request
- name: Configure git
uses: Homebrew/actions/git-user-config@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
username: github-actions[bot]

- name: Commit advisories
id: commit
env:
GITHUB_TOKEN: ${{ github.token }}
BRANCH: regenerate-advisories
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add advisories/ data/
if git diff --cached --quiet; then
echo "No changes."
exit 0
fi
gh auth setup-git --hostname github.com --force
git checkout -b "$BRANCH"
git checkout -b "${BRANCH}"
git commit -m "Regenerate advisories"
git push --force origin "HEAD:refs/heads/$BRANCH"
if [ -n "$(gh pr list --head "$BRANCH" --state open --json number --jq '.[].number')" ]; then
{
echo "branch=${BRANCH}"
echo "committed=true"
} >> "${GITHUB_OUTPUT}"

- name: Push commits
if: steps.commit.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
token: ${{ github.token }}
branch: ${{ steps.commit.outputs.branch }}
# No lease: rebuilt from main each run, and no remote-tracking ref exists.
force: true
no_lease: true
origin_branch: HEAD

- name: Open pull request
if: steps.commit.outputs.committed == 'true'
env:
GITHUB_TOKEN: ${{ github.token }}
BRANCH: ${{ steps.commit.outputs.branch }}
run: |
open_pr_number="$(gh pr list --head "${BRANCH}" --state open \
--json number,isCrossRepository \
--jq '.[] | select(.isCrossRepository | not) | .number')"
if [[ -n "${open_pr_number}" ]]; then
echo "PR already open."
else
gh pr create --base main --head "$BRANCH" \
gh pr create --base main --head "${BRANCH}" \
--title "Regenerate advisories" \
--body "Automated regeneration via \`brew generate-vulns-advisories\`."
fi
60 changes: 46 additions & 14 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,70 @@ name: Validate

on:
push:
branches:
- main
pull_request:
merge_group:

permissions:
contents: read
defaults:
run:
shell: bash -xeuo pipefail {0}

concurrency:
group: "validate-${{ github.ref }}"
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions: {}

jobs:
schema:
name: Validate advisory schema
if: github.repository_owner == 'Homebrew'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
python-version: "3.x"
core: false
cask: false

- name: Install check-jsonschema
run: pip install check-jsonschema
uses: Homebrew/actions/cache-homebrew-prefix@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
install: check-jsonschema
workflow-key: validate-schema

- name: Fetch OSV schema
run: curl -sSfL -o osv-schema.json https://raw.githubusercontent.com/ossf/osv-schema/main/validation/schema.json
# OSV schema v1.9.0, which includes the Homebrew ecosystem and BREW- id registrations.
run: >-
curl --fail --location --retry 3 --show-error --silent
--output "${RUNNER_TEMP}/osv-schema.json"
https://raw.githubusercontent.com/ossf/osv-schema/f3f826310aeca8e324baabd195632f2229952abe/validation/schema.json

- name: Validate advisories against OSV schema
run: check-jsonschema --schemafile osv-schema.json advisories/*.json
run: |
if ! find advisories -type f -name '*.json' -print -quit | grep -q .; then
echo "No advisory files found."
exit 1
fi
find advisories -type f -name '*.json' -print0 |
xargs -0 -r -n 500 check-jsonschema --schemafile "${RUNNER_TEMP}/osv-schema.json"

test:
name: Test Ruby code
if: github.repository_owner == 'Homebrew'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -42,11 +78,7 @@ jobs:
uses: Homebrew/actions/setup-ruby@fd832223f9f99ebf0244dd20658680e5d4aca049 # 2026.08.03.2
with:
bundler-cache: true
portable-ruby: true

- name: Run tests
run: bundle exec rake spec

# RuboCop is not run: the org-synced .rubocop.yml sets
# `AllCops: Include: ["**/*.rbi"]` which replaces (not extends) the
# default .rb globs, so it scans nothing in this repository. Fix belongs
# in the Homebrew/.github sync source.
- name: Run tests and style checks
run: bundle exec rake
17 changes: 17 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ Do not merge a `matched` record over an existing `source: "generated"` record fo

Records here describe vulnerabilities in software Homebrew distributes, scoped to the Homebrew formula name and version. They are not a substitute for the upstream project's own advisory; the purpose is to let tools that read `pkg:brew` purls or `Homebrew` OSV queries answer "is this installed formula affected". Casks are out of scope for now.

## Development

The required Ruby version is recorded in `.ruby-version`. Install the development dependencies and run the same Ruby checks as CI with:

```sh
bundle install
bundle exec rake
```

Workflow changes should also pass Homebrew's standard workflow checks:

```sh
brew install actionlint shellcheck zizmor
actionlint
zizmor .
```

## Code of Conduct

This project follows the [Homebrew Code of Conduct](https://github.com/Homebrew/.github/blob/HEAD/CODE_OF_CONDUCT.md).
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@

source "https://rubygems.org"

ruby file: ".ruby-version"

gem "rake"
gem "rspec"
gem "rubocop"
Loading
Loading