0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
150 lines
6.4 KiB
YAML
150 lines
6.4 KiB
YAML
name: release-please-format
|
|
run-name: format CHANGELOG on release PR (${{ github.event.pull_request.head.ref }})
|
|
|
|
# Runs prettier on CHANGELOG files in release-please PRs. Lives in its own
|
|
# workflow (not inside release-please.yml) so it re-runs on every PR
|
|
# synchronize event — release-please force-pushes its PR branch when new
|
|
# commits land on main, which would wipe any formatting commit created
|
|
# inline in the release-please job.
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened]
|
|
paths:
|
|
- '**/CHANGELOG.md'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
format:
|
|
# Branch prefix alone is not a trust boundary. Require: same-repo PR (forks
|
|
# cannot be legitimate release-please PRs), the exact release bot as
|
|
# author, and the release-please branch naming convention.
|
|
if: >-
|
|
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
github.event.pull_request.user.login == 'promptfoobot[bot]' &&
|
|
startsWith(github.event.pull_request.head.ref, 'release-please--')
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
# Pin an explicit Node version so this step does not depend on a
|
|
# PR-controlled .nvmrc — the install below happens before checkout.
|
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
|
with:
|
|
node-version: 'lts/*'
|
|
|
|
# Isolated install before checkout so a PR-controlled .npmrc cannot
|
|
# redirect the registry or inject a package.
|
|
- name: Install prettier (outside PR checkout)
|
|
run: |
|
|
set -euo pipefail
|
|
install_dir="$RUNNER_TEMP/prettier-install"
|
|
mkdir -p "$install_dir"
|
|
cd "$install_dir"
|
|
npm install \
|
|
--no-save --no-audit --no-fund --ignore-scripts \
|
|
--registry=https://registry.npmjs.org/ \
|
|
prettier@3.8.1
|
|
echo "$install_dir/node_modules/.bin" >> "$GITHUB_PATH"
|
|
|
|
# persist-credentials: false keeps GITHUB_TOKEN out of .git/config so it
|
|
# can't be read via a PR-planted pre-push hook. The App token is not
|
|
# created until after the untrusted steps below.
|
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
with:
|
|
ref: ${{ github.event.pull_request.head.ref }}
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- name: Format and commit CHANGELOG files
|
|
id: format
|
|
env:
|
|
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# Ensure base ref is available locally — actions/checkout with
|
|
# fetch-depth: 0 fetches history of the head ref, not other branches.
|
|
git fetch --no-tags --prune origin "${BASE_REF}"
|
|
|
|
# Capture diff output separately so a failing `git diff` does not get
|
|
# swallowed by `|| true` on the downstream grep pipeline.
|
|
changed_paths="$(git diff --name-only --diff-filter=ACMRT "origin/${BASE_REF}...HEAD")"
|
|
|
|
mapfile -t changelog_files < <(
|
|
printf '%s\n' "$changed_paths" | grep -E '(^|/)CHANGELOG\.md$' || true
|
|
)
|
|
|
|
if [[ "${#changelog_files[@]}" -eq 0 ]]; then
|
|
echo "No CHANGELOG files changed in release PR"
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
# --no-config and --no-editorconfig prevent prettier from loading a
|
|
# PR-controlled .prettierrc.js (which would execute arbitrary code) or
|
|
# .editorconfig that could change what gets written.
|
|
prettier --no-config --no-editorconfig --write "${changelog_files[@]}"
|
|
|
|
if git diff --quiet -- "${changelog_files[@]}"; then
|
|
echo "No formatting changes needed"
|
|
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
git add "${changelog_files[@]}"
|
|
# core.hooksPath=/dev/null prevents a PR-planted .git/hooks/pre-commit
|
|
# from tampering with the commit.
|
|
git -c core.hooksPath=/dev/null \
|
|
commit -m "chore: format CHANGELOG files with prettier"
|
|
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
|
|
|
# Refuse to push if the just-created commit touches anything other than
|
|
# CHANGELOG.md files. Runs before the App token is issued.
|
|
- name: Verify commit scope
|
|
if: steps.format.outputs.has_changes == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
mapfile -t touched < <(git diff-tree --no-commit-id --name-only -r HEAD)
|
|
# Match the selector used above (^|/)CHANGELOG\.md$ — basename only,
|
|
# so MY_CHANGELOG.md or CHANGELOG.md.bak are rejected.
|
|
for path in "${touched[@]}"; do
|
|
if [[ "$path" != "CHANGELOG.md" && "$path" != */CHANGELOG.md ]]; then
|
|
echo "::error::Refusing to push: commit touches non-CHANGELOG path: $path"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Create the App token only after untrusted steps so prettier / npm
|
|
# install never had it in reach. Token inherits the App installation's
|
|
# granted permissions — do NOT add `permission-*` inputs here until the
|
|
# App installation is confirmed to grant every requested permission;
|
|
# see the matching note on release-please.yml.
|
|
- name: Create App token for push
|
|
if: steps.format.outputs.has_changes == 'true'
|
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
|
|
id: app-token
|
|
with:
|
|
app-id: ${{ vars.PROMPTFOOBOT_APP_ID }}
|
|
private-key: ${{ secrets.PROMPTFOOBOT_APP_PRIVATE_KEY }}
|
|
|
|
- name: Push formatted CHANGELOG commit
|
|
if: steps.format.outputs.has_changes == 'true'
|
|
env:
|
|
HEAD_REF: ${{ github.event.pull_request.head.ref }}
|
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
run: |
|
|
set -euo pipefail
|
|
# GitHub's Git smart HTTP endpoint expects Basic auth. Build the
|
|
# header just-in-time so credentials are scoped to this invocation
|
|
# instead of being persisted in .git/config.
|
|
basic_auth="$(printf 'x-access-token:%s' "${GH_TOKEN}" | base64 | tr -d '\n')"
|
|
git -c core.hooksPath=/dev/null \
|
|
-c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${basic_auth}" \
|
|
push origin "HEAD:${HEAD_REF}"
|