Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
3cbe717
Add workflow to auto-update dependent repos on new version publish
HarwinBorger Mar 3, 2026
51cbccb
Merge branch 'master' of github.com:athombv/jsdoc-template
HarwinBorger Mar 3, 2026
897ba42
Fix script injection vulnerabilities in update-dependents workflow
HarwinBorger Mar 3, 2026
8fc6311
Use HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN in update-dependen…
HarwinBorger Mar 5, 2026
9d5abca
Fix git push auth in update-dependents workflow
HarwinBorger Mar 5, 2026
64b2cb3
Update publishing instructions in README
HarwinBorger Mar 5, 2026
a85b4ff
Allow re-running update-dependents to update existing PRs
HarwinBorger Mar 5, 2026
c2fabc0
Fix npm auth for GitHub Packages in update-dependents workflow
HarwinBorger Mar 5, 2026
84dcc69
Add @athombv registry config for npm in update-dependents workflow
HarwinBorger Mar 5, 2026
0c9aae3
Skip install scripts when updating lockfile in update-dependents work…
HarwinBorger Mar 5, 2026
b725074
chore: prepare package for public distribution
RobinBol May 18, 2026
5b6dcc8
chore: address copilot review feedback
RobinBol May 18, 2026
63b8c7d
Merge pull request #22 from athombv/chore/make-package-public
RobinBol May 18, 2026
ba5fb0f
chore: publish to npmjs.org via OIDC
RobinBol May 18, 2026
2c469d3
chore: address copilot review feedback
RobinBol May 18, 2026
d0a0b51
chore: address copilot review feedback
RobinBol May 18, 2026
ed2c316
Merge pull request #23 from athombv/chore/publish-to-npmjs
RobinBol May 18, 2026
d38e482
1.7.0
github-actions[bot] May 18, 2026
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
46 changes: 0 additions & 46 deletions .github/workflows/gpr-publish.yaml

This file was deleted.

67 changes: 67 additions & 0 deletions .github/workflows/publish-package-npm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Publish to NPM

# Publishes the package to npmjs.org using OIDC (Trusted Publisher).
#
# Requirements:
# - The `@athombv/jsdoc-template` package must have a Trusted Publisher
# configured on npmjs.org pointing at this repository and workflow file.
# - Bump the version on `master` via the Version workflow before merging to
# `production`.
#
# Steps:
# 1. Verifies a `files` array is present in package.json.
# 2. Installs dependencies and runs `npm run build` if it exists.
# 3. On `workflow_dispatch`: runs `npm publish --dry-run`.
# 4. On push to `production`: publishes to npmjs.org.

on:
workflow_dispatch:
push:
branches:
- production

permissions:
id-token: write
contents: read

jobs:
publish:
name: Publish
runs-on: ubuntu-latest
steps:
- name: Checkout git repository
uses: actions/checkout@v4

- name: Set up node
uses: actions/setup-node@v4
with:
# Node 24 bundles npm >= 11.5.1, required for OIDC `npm publish`.
node-version: '24'
registry-url: 'https://registry.npmjs.org/'

- name: Verify files field in package.json
run: |
if ! jq -e .files package.json > /dev/null; then
echo "Missing 'files' array in package.json."
exit 1
fi

- name: Install dependencies
run: npm ci --ignore-scripts --audit=false

- name: Build
run: |
if jq --exit-status '.scripts | has("build")' package.json > /dev/null; then
echo "Running npm run build..."
npm run build
else
echo "No build script; skipping."
fi

- name: Publish dry run
if: github.event_name == 'workflow_dispatch'
run: npm publish --dry-run --provenance

- name: Publish
if: github.event_name == 'push' && github.ref == 'refs/heads/production'
run: npm publish --provenance
240 changes: 240 additions & 0 deletions .github/workflows/update-dependents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
name: Update Dependent Repos

on:
workflow_run:
workflows: ["Publish to NPM"]
types:
- completed

workflow_dispatch:
inputs:
dry_run:
description: 'Discover dependents only, do not create PRs'
required: false
default: false
type: boolean
version_override:
description: 'Override version (e.g. 1.6.3) instead of reading from package.json'
required: false
type: string

permissions:
contents: read

jobs:
update-dependents:
name: Update Dependent Repos
runs-on: ubuntu-latest
if: >
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
steps:
- name: Checkout production branch
uses: actions/checkout@v4
with:
ref: production

- name: Extract version
id: version
env:
VERSION_OVERRIDE: ${{ inputs.version_override }}
run: |
if [ -n "$VERSION_OVERRIDE" ]; then
VERSION="$VERSION_OVERRIDE"
else
VERSION=$(jq -r .version package.json)
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Package version: $VERSION"

- name: Discover dependent repos
id: discover
env:
GH_TOKEN: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }}
SOURCE_REPO: ${{ github.repository }}
run: |
echo "Searching for repos that depend on @athombv/jsdoc-template..."

REPOS=$(gh api -X GET /search/code \
--paginate \
-f q='org:athombv "@athombv/jsdoc-template" filename:package.json' \
--jq '.items[].repository.full_name' | sort -u)

# Filter out this repo itself
REPOS=$(echo "$REPOS" | grep -v "^${SOURCE_REPO}$" || true)

if [ -z "$REPOS" ]; then
echo "No dependent repos found."
echo "repos=" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "Found dependent repos:"
echo "$REPOS"
echo "repos<<EOF" >> "$GITHUB_OUTPUT"
echo "$REPOS" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

- name: Create PRs in dependent repos
if: steps.discover.outputs.repos != ''
env:
GH_TOKEN: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
REPOS: ${{ steps.discover.outputs.repos }}
run: |
BRANCH_NAME="chore/update-jsdoc-template-${VERSION}"

SUCCESSES=0
SKIPS=0
FAILURES=0
SUMMARY=""

while IFS= read -r REPO; do
[ -z "$REPO" ] && continue
echo ""
echo "================================================"
echo "Processing: $REPO"
echo "================================================"

# Check if a PR already exists for this branch
EXISTING_PR=$(gh pr list --repo "$REPO" --head "$BRANCH_NAME" --json number --jq '.[0].number' 2>/dev/null || true)

if [ "$DRY_RUN" = "true" ]; then
echo "DRY RUN: Would create PR in $REPO"
SKIPS=$((SKIPS + 1))
SUMMARY="${SUMMARY}\n DRY RUN: ${REPO}"
continue
fi

# Clone the repo
WORK_DIR=$(mktemp -d)
if ! gh repo clone "$REPO" "$WORK_DIR" -- --depth 1 2>&1; then
echo "FAIL: Could not clone $REPO"
FAILURES=$((FAILURES + 1))
SUMMARY="${SUMMARY}\n FAIL: ${REPO} (clone failed)"
rm -rf "$WORK_DIR"
sleep 2
continue
fi

cd "$WORK_DIR"

# Configure git to use the token for pushing
git config credential.helper '!f() { echo "username=x-access-token"; echo "password=${GH_TOKEN}"; }; f'

# Check current version in package.json
CURRENT=$(jq -r '
(.devDependencies // {} | .["@athombv/jsdoc-template"] // empty),
(.dependencies // {} | .["@athombv/jsdoc-template"] // empty)
' package.json 2>/dev/null | head -1)

if [ -z "$CURRENT" ]; then
echo "SKIP: @athombv/jsdoc-template not found in package.json"
SKIPS=$((SKIPS + 1))
SUMMARY="${SUMMARY}\n SKIP: ${REPO} (dependency not found in package.json)"
cd - > /dev/null
rm -rf "$WORK_DIR"
sleep 2
continue
fi

echo "Current version spec: $CURRENT"

# Extract semver prefix (^, ~, or empty)
PREFIX=$(echo "$CURRENT" | sed -E 's/^([^0-9]*).*/\1/')
CURRENT_VERSION=$(echo "$CURRENT" | sed -E 's/^[^0-9]*//')

NEW_SPEC="${PREFIX}${VERSION}"
echo "Updating: $CURRENT -> $NEW_SPEC"

# Create branch
git checkout -b "$BRANCH_NAME"

# Update package.json, checking both dependencies and devDependencies
jq --arg new "$NEW_SPEC" '
if .dependencies["@athombv/jsdoc-template"] then
.dependencies["@athombv/jsdoc-template"] = $new
else . end |
if .devDependencies["@athombv/jsdoc-template"] then
.devDependencies["@athombv/jsdoc-template"] = $new
else . end
' package.json > package.json.tmp && mv package.json.tmp package.json

# Strip any leftover @athombv -> GitHub Packages mapping from .npmrc
# so the new version resolves from npmjs.org. Remove the file when
# nothing meaningful remains.
if [ -f .npmrc ]; then
sed -i '/@athombv:registry/d; /npm.pkg.github.com/d' .npmrc
if [ ! -s .npmrc ] || ! grep -qv '^\s*$' .npmrc; then
rm -f .npmrc
fi
fi

# Update lockfile
npm install --package-lock-only --ignore-scripts

# Commit and push
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Stage the version bump, plus any add/modify/delete to .npmrc
# if it currently exists or is tracked in the repo.
git add -A -- package.json package-lock.json
if [ -e .npmrc ] || git ls-files --error-unmatch .npmrc > /dev/null 2>&1; then
git add -A -- .npmrc
fi
git commit -m "chore: update @athombv/jsdoc-template to ${NEW_SPEC}"

if ! git push --force origin "$BRANCH_NAME" 2>&1; then
echo "FAIL: Could not push to $REPO"
FAILURES=$((FAILURES + 1))
SUMMARY="${SUMMARY}\n FAIL: ${REPO} (push failed)"
cd - > /dev/null
rm -rf "$WORK_DIR"
sleep 2
continue
fi

# Create PR if one doesn't already exist
if [ -n "$EXISTING_PR" ]; then
echo "SUCCESS: Updated existing PR #$EXISTING_PR"
SUCCESSES=$((SUCCESSES + 1))
SUMMARY="${SUMMARY}\n OK: ${REPO} (updated PR #${EXISTING_PR})"
elif PR_URL=$(gh pr create \
--repo "$REPO" \
--head "$BRANCH_NAME" \
--title "chore: update @athombv/jsdoc-template to ${NEW_SPEC}" \
--body "$(cat <<EOF
Automated update of \`@athombv/jsdoc-template\` from \`${CURRENT}\` to \`${NEW_SPEC}\`.

## Checklist
- [ ] Verify the build still works
EOF
)" 2>/dev/null); then
echo "SUCCESS: Created PR -> $PR_URL"
SUCCESSES=$((SUCCESSES + 1))
SUMMARY="${SUMMARY}\n OK: ${REPO} -> ${PR_URL}"
else
echo "FAIL: Could not create PR in $REPO"
FAILURES=$((FAILURES + 1))
SUMMARY="${SUMMARY}\n FAIL: ${REPO} (PR creation failed)"
fi

cd - > /dev/null
rm -rf "$WORK_DIR"
sleep 2
done <<< "$REPOS"

echo ""
echo "================================================"
echo "SUMMARY"
echo "================================================"
echo "Successes: $SUCCESSES"
echo "Skips: $SKIPS"
echo "Failures: $FAILURES"
echo -e "$SUMMARY"

if [ "$FAILURES" -gt 0 ]; then
echo ""
echo "::warning::${FAILURES} repo(s) failed to update"
fi
Loading