From 854637165c2b16d61ecd5395b915ecd2fa4c0238 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 24 Mar 2026 18:20:19 -0400 Subject: [PATCH 1/8] feat(ci): add updating skill and weekly-update workflow - Add updating skill for npm dependency updates - Add weekly-update.yml workflow for automated updates --- .claude/skills/updating/SKILL.md | 167 ++++++++++++++++++++++++++ .github/workflows/weekly-update.yml | 175 ++++++++++++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 .claude/skills/updating/SKILL.md create mode 100644 .github/workflows/weekly-update.yml diff --git a/.claude/skills/updating/SKILL.md b/.claude/skills/updating/SKILL.md new file mode 100644 index 00000000..1fa54abe --- /dev/null +++ b/.claude/skills/updating/SKILL.md @@ -0,0 +1,167 @@ +--- +name: updating +description: Updates all npm dependencies to their latest versions. Triggers when user asks to "update dependencies", "update packages", or prepare for a release. +user-invocable: true +allowed-tools: Bash, Read, Grep, Glob, Edit +--- + +# updating + + +Your task is to update all npm dependencies to their latest versions, ensuring all builds and tests pass. + + + +**What is this?** +This skill updates npm packages for security patches, bug fixes, and new features. + +**Update Targets:** +- npm packages via `pnpm run update` or `pnpm update` + + + +**Requirements:** +- Start with clean working directory (no uncommitted changes) + +**CI Mode** (detected via `CI=true` or `GITHUB_ACTIONS`): +- Create atomic commits, skip build validation (CI validates separately) +- Workflow handles push and PR creation + +**Interactive Mode** (default): +- Validate updates with build/tests before proceeding +- Report validation results to user + +**Actions:** +- Update npm packages +- Create atomic commits +- Report summary of changes + + + + +## Process + +### Phase 1: Validate Environment + + +Check working directory is clean and detect CI mode: + + +```bash +# Detect CI mode +if [ "$CI" = "true" ] || [ -n "$GITHUB_ACTIONS" ]; then + CI_MODE=true + echo "Running in CI mode - will skip build validation" +else + CI_MODE=false + echo "Running in interactive mode - will validate builds" +fi + +# Check working directory is clean +git status --porcelain +``` + + +- Working directory must be clean +- CI_MODE detected for subsequent phases + + +--- + +### Phase 2: Update npm Packages + + +Run pnpm update to update npm dependencies: + + +```bash +# Update npm packages (use pnpm run update if script exists, otherwise pnpm update) +if grep -q '"update"' package.json; then + pnpm run update +else + pnpm update +fi + +# Check if there are changes +if [ -n "$(git status --porcelain pnpm-lock.yaml package.json)" ]; then + git add pnpm-lock.yaml package.json + git commit -m "chore: update npm dependencies + +Updated npm packages via pnpm update." + echo "npm packages updated" +else + echo "npm packages already up to date" +fi +``` + +--- + +### Phase 3: Final Validation + + +Run build and test suite (skip in CI mode): + + +```bash +if [ "$CI_MODE" = "true" ]; then + echo "CI mode: Skipping final validation (CI will run builds/tests separately)" + echo "Commits created - ready for push by CI workflow" +else + echo "Interactive mode: Running full validation..." + pnpm run check + pnpm test +fi +``` + +--- + +### Phase 4: Report Summary + + +Generate update report: + + +``` +## Update Complete + +### Updates Applied: + +| Category | Status | +|----------|--------| +| npm packages | Updated/Up to date | + +### Commits Created: +- [list commits if any] + +### Validation: +- Build: SUCCESS/SKIPPED (CI mode) +- Tests: PASS/SKIPPED (CI mode) + +### Next Steps: +**Interactive mode:** +1. Review changes: `git log --oneline -N` +2. Push to remote: `git push origin main` + +**CI mode:** +1. Workflow will push branch and create PR +2. CI will run full build/test validation +3. Review PR when CI passes +``` + + + +## Success Criteria + +- All npm packages checked for updates +- Full build and tests pass (interactive mode) +- Summary report generated + +## Context + +This skill is useful for: + +- Weekly maintenance (automated via weekly-update.yml) +- Security patch rollout +- Pre-release preparation + +**Safety:** Updates are validated before committing. Failures stop the process. diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml new file mode 100644 index 00000000..0466e9a2 --- /dev/null +++ b/.github/workflows/weekly-update.yml @@ -0,0 +1,175 @@ +name: 🔄 Weekly Dependency Update + +on: + schedule: + # Run weekly on Monday at 9 AM UTC + - cron: '0 9 * * 1' + workflow_dispatch: + inputs: + dry-run: + description: 'Check for updates without creating PR' + required: false + type: boolean + default: false + +permissions: + contents: read + +jobs: + check-updates: + name: Check for dependency updates + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + has-updates: ${{ steps.check.outputs.has-updates }} + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version-file: .node-version + cache: '' + + - name: Setup pnpm + uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Check for npm updates + id: check + run: | + echo "Checking for npm package updates..." + HAS_UPDATES=false + NPM_UPDATES=$(pnpm outdated 2>/dev/null || true) + if [ -n "$NPM_UPDATES" ] && ! echo "$NPM_UPDATES" | grep -q "No outdated"; then + echo "npm packages have updates available" + HAS_UPDATES=true + fi + echo "has-updates=$HAS_UPDATES" >> $GITHUB_OUTPUT + + apply-updates: + name: Apply updates with Claude Code + needs: check-updates + if: needs.check-updates.outputs.has-updates == 'true' && inputs.dry-run != true + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version-file: .node-version + cache: '' + + - name: Setup pnpm + uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Install Claude Code + run: npm install -g @anthropic-ai/claude-code + + - name: Create update branch + id: branch + run: | + BRANCH_NAME="weekly-update-$(date +%Y%m%d)" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout -b "$BRANCH_NAME" + echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: Run updating skill with Claude Code + id: claude + timeout-minutes: 30 + env: + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + CI: 'true' + GITHUB_ACTIONS: 'true' + run: | + if [ -z "$ANTHROPIC_API_KEY" ]; then + echo "⚠️ ANTHROPIC_API_KEY not set - skipping automated update" + echo "success=false" >> $GITHUB_OUTPUT + exit 0 + fi + + claude --print --dangerously-skip-permissions \ + --model sonnet \ + "/updating - Run the updating skill to update all dependencies. Create atomic commits for each update. You are running in CI mode - skip builds and tests. Do not push or create a PR." \ + 2>&1 | tee claude-output.log + + if [ $? -eq 0 ]; then + echo "success=true" >> $GITHUB_OUTPUT + else + echo "success=false" >> $GITHUB_OUTPUT + fi + + - name: Check for changes + id: changes + run: | + if [ -n "$(git status --porcelain)" ] || [ "$(git rev-list --count HEAD ^origin/main)" -gt 0 ]; then + echo "has-changes=true" >> $GITHUB_OUTPUT + else + echo "has-changes=false" >> $GITHUB_OUTPUT + fi + + - name: Push branch + if: steps.claude.outputs.success == 'true' && steps.changes.outputs.has-changes == 'true' + env: + BRANCH_NAME: ${{ steps.branch.outputs.branch }} + run: git push origin "$BRANCH_NAME" + + - name: Create Pull Request + if: steps.claude.outputs.success == 'true' && steps.changes.outputs.has-changes == 'true' + env: + GH_TOKEN: ${{ github.token }} + BRANCH_NAME: ${{ steps.branch.outputs.branch }} + run: | + COMMITS=$(git log --oneline origin/main..HEAD) + COMMIT_COUNT=$(git rev-list --count origin/main..HEAD) + + gh pr create \ + --title "chore(deps): weekly dependency update ($(date +%Y-%m-%d))" \ + --body "## Weekly Dependency Update + +Automated weekly update of npm packages. + +### Commits (${COMMIT_COUNT}) + +
+View commit history + +\`\`\` +${COMMITS} +\`\`\` + +
+ +--- + +Generated by [weekly-update.yml](.github/workflows/weekly-update.yml)" \ + --draft \ + --head "$BRANCH_NAME" \ + --base main + + - name: Upload Claude output + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: claude-output-${{ github.run_id }} + path: claude-output.log + retention-days: 7 From 68a6fc1e0cfd0c6768756fc7612964d50dea1851 Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 24 Mar 2026 18:35:13 -0400 Subject: [PATCH 2/8] fix(skill): update updating skill to use pnpm run update and check --all - Use `pnpm run update` instead of fallback to `pnpm update` - Add `pnpm run fix --all` before validation - Change `pnpm run check` to `pnpm run check --all` --- .claude/skills/updating/SKILL.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.claude/skills/updating/SKILL.md b/.claude/skills/updating/SKILL.md index 1fa54abe..f97d5548 100644 --- a/.claude/skills/updating/SKILL.md +++ b/.claude/skills/updating/SKILL.md @@ -16,7 +16,7 @@ Your task is to update all npm dependencies to their latest versions, ensuring a This skill updates npm packages for security patches, bug fixes, and new features. **Update Targets:** -- npm packages via `pnpm run update` or `pnpm update` +- npm packages via `pnpm run update` @@ -71,23 +71,19 @@ git status --porcelain ### Phase 2: Update npm Packages -Run pnpm update to update npm dependencies: +Run pnpm run update to update npm dependencies: ```bash -# Update npm packages (use pnpm run update if script exists, otherwise pnpm update) -if grep -q '"update"' package.json; then - pnpm run update -else - pnpm update -fi +# Update npm packages +pnpm run update # Check if there are changes if [ -n "$(git status --porcelain pnpm-lock.yaml package.json)" ]; then git add pnpm-lock.yaml package.json git commit -m "chore: update npm dependencies -Updated npm packages via pnpm update." +Updated npm packages via pnpm run update." echo "npm packages updated" else echo "npm packages already up to date" @@ -108,7 +104,8 @@ if [ "$CI_MODE" = "true" ]; then echo "Commits created - ready for push by CI workflow" else echo "Interactive mode: Running full validation..." - pnpm run check + pnpm run fix --all + pnpm run check --all pnpm test fi ``` From 65f147bab52e036b358e767092426093e978c8ff Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 24 Mar 2026 23:09:24 -0400 Subject: [PATCH 3/8] fix(ci): update pnpm/action-setup to Node 24 (58e6119) --- .github/workflows/weekly-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml index 0466e9a2..07a561a2 100644 --- a/.github/workflows/weekly-update.yml +++ b/.github/workflows/weekly-update.yml @@ -37,7 +37,7 @@ jobs: cache: '' - name: Setup pnpm - uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0 + uses: pnpm/action-setup@58e6119fe4f3092a76a7771efb55e04d25b6b26f # v5 - name: Install dependencies run: pnpm install --frozen-lockfile @@ -76,7 +76,7 @@ jobs: cache: '' - name: Setup pnpm - uses: pnpm/action-setup@b307475762933b98ed359c036b0e51f26b63b74b # v5.0.0 + uses: pnpm/action-setup@58e6119fe4f3092a76a7771efb55e04d25b6b26f # v5 - name: Install dependencies run: pnpm install --frozen-lockfile From 8c5b0e81c6ce28ae6d256590821d01c61a1a5e1a Mon Sep 17 00:00:00 2001 From: jdalton Date: Tue, 24 Mar 2026 23:18:34 -0400 Subject: [PATCH 4/8] chore(deps): update @socketsecurity/lib to 5.11.2 --- .claude/skills/updating/reference.md | 76 ++++++++++++++++++++++++++++ package.json | 2 +- pnpm-lock.yaml | 10 ++-- 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 .claude/skills/updating/reference.md diff --git a/.claude/skills/updating/reference.md b/.claude/skills/updating/reference.md new file mode 100644 index 00000000..254f5964 --- /dev/null +++ b/.claude/skills/updating/reference.md @@ -0,0 +1,76 @@ +# updating Reference Documentation + +## Table of Contents + +1. [How the Update Script Works](#how-the-update-script-works) +2. [Files Changed After Update](#files-changed-after-update) +3. [Validation Commands](#validation-commands) +4. [Troubleshooting](#troubleshooting) + +--- + +## How the Update Script Works + +`pnpm run update` runs `scripts/update.mjs` which performs: + +```bash +# 1. Run taze recursively with write mode +pnpm exec taze -r -w + +# 2. Force-update Socket scoped packages (bypasses taze maturity period) +pnpm update @socketsecurity/* @socketregistry/* @socketbin/* --latest -r + +# 3. pnpm install runs automatically to reconcile lockfile +``` + +### Repo Structure + +- **Single package** (not a monorepo, no `packages/` directory) +- Has both `dependencies` and `devDependencies` (published package) +- Runtime deps: `@socketregistry/packageurl-js`, `@socketsecurity/lib`, `form-data` +- Dependencies pinned to exact versions in `package.json` + +--- + +## Files Changed After Update + +- `package.json` - Dependency version pins (both deps and devDeps) +- `pnpm-lock.yaml` - Lock file + +--- + +## Validation Commands + +```bash +# Fix lint issues +pnpm run fix --all + +# Run all checks (lint + type check) +pnpm run check --all + +# Run tests +pnpm test +``` + +--- + +## Troubleshooting + +### taze Fails to Detect Updates + +**Cause:** taze has a maturity period for new releases. +**Solution:** Socket packages are force-updated separately via `pnpm update --latest`. + +### Lock File Conflicts + +**Solution:** +```bash +rm pnpm-lock.yaml +pnpm install +``` + +### SDK Regeneration + +If `@socketsecurity/lib` is updated, the generated SDK types may need +regeneration via `pnpm run generate-sdk`. Check if API types in `types/` +are still valid after updating. diff --git a/package.json b/package.json index be5966b1..729178e0 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ }, "dependencies": { "@socketregistry/packageurl-js": "1.3.5", - "@socketsecurity/lib": "5.11.1", + "@socketsecurity/lib": "5.11.2", "form-data": "4.0.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e2bd2cb..91c0223a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: 1.3.5 version: 1.3.5 '@socketsecurity/lib': - specifier: 5.11.1 - version: 5.11.1(typescript@5.9.3) + specifier: 5.11.2 + version: 5.11.2(typescript@5.9.3) form-data: specifier: 4.0.5 version: 4.0.5 @@ -919,8 +919,8 @@ packages: resolution: {integrity: sha512-Fl4GNUJ/z3IBJBGj4IsJfuRGUBCRMgX0df0mb5x5buaCPDKC+NhMhAFuxpc3viLSHV12CO2rGaNCf4fBYWI0FA==} engines: {node: '>=18', pnpm: '>=10.16.0'} - '@socketsecurity/lib@5.11.1': - resolution: {integrity: sha512-07KCWdNGit1Q5B1D+AQbl1aqR0EHOrGNGpTFS5VqRTaFyG0t2Jf1qvmVVi9dKrqnbqE0tFF+aMcAWBR3vbX9Lg==} + '@socketsecurity/lib@5.11.2': + resolution: {integrity: sha512-TS6oTeakMCbOrz73mSin/0lOhAyAr6+tlvzAvaASnMhjhrcQ9tPP816be1ZgtDRYolvQHMT+WPSmajlTHTQHjw==} engines: {node: '>=22', pnpm: '>=10.25.0'} peerDependencies: typescript: '>=5.0.0' @@ -2458,7 +2458,7 @@ snapshots: '@socketregistry/packageurl-js@1.3.5': {} - '@socketsecurity/lib@5.11.1(typescript@5.9.3)': + '@socketsecurity/lib@5.11.2(typescript@5.9.3)': optionalDependencies: typescript: 5.9.3 From b555496fce352456cb6bb7958bb9c885ee00b62f Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 25 Mar 2026 09:49:41 -0400 Subject: [PATCH 5/8] fix(ci): fix invalid YAML syntax in weekly-update workflow The inline multi-line PR body string caused YAML parsing failures because `### Commits` was interpreted as a YAML mapping key. Moved to a heredoc. Also fixed: removed persist-credentials: false from apply-updates job (was blocking git push), corrected inputs.dry-run to use github.event.inputs context, and added set -o pipefail so claude failures are properly captured through the tee pipe. --- .github/workflows/weekly-update.yml | 44 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml index 07a561a2..16f1cbdb 100644 --- a/.github/workflows/weekly-update.yml +++ b/.github/workflows/weekly-update.yml @@ -27,7 +27,6 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - fetch-depth: 0 persist-credentials: false - name: Setup Node.js @@ -57,7 +56,7 @@ jobs: apply-updates: name: Apply updates with Claude Code needs: check-updates - if: needs.check-updates.outputs.has-updates == 'true' && inputs.dry-run != true + if: needs.check-updates.outputs.has-updates == 'true' && github.event.inputs.dry-run != 'true' runs-on: ubuntu-latest permissions: contents: write @@ -67,7 +66,6 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - persist-credentials: false - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 @@ -101,18 +99,17 @@ jobs: CI: 'true' GITHUB_ACTIONS: 'true' run: | + set -o pipefail if [ -z "$ANTHROPIC_API_KEY" ]; then echo "⚠️ ANTHROPIC_API_KEY not set - skipping automated update" echo "success=false" >> $GITHUB_OUTPUT exit 0 fi - claude --print --dangerously-skip-permissions \ + if claude --print --dangerously-skip-permissions \ --model sonnet \ "/updating - Run the updating skill to update all dependencies. Create atomic commits for each update. You are running in CI mode - skip builds and tests. Do not push or create a PR." \ - 2>&1 | tee claude-output.log - - if [ $? -eq 0 ]; then + 2>&1 | tee claude-output.log; then echo "success=true" >> $GITHUB_OUTPUT else echo "success=false" >> $GITHUB_OUTPUT @@ -142,26 +139,33 @@ jobs: COMMITS=$(git log --oneline origin/main..HEAD) COMMIT_COUNT=$(git rev-list --count origin/main..HEAD) - gh pr create \ - --title "chore(deps): weekly dependency update ($(date +%Y-%m-%d))" \ - --body "## Weekly Dependency Update + BODY=$(cat < + View commit history -
-View commit history + \`\`\` + ${COMMITS} + \`\`\` -\`\`\` -${COMMITS} -\`\`\` +
- + --- ---- + Generated by [weekly-update.yml](.github/workflows/weekly-update.yml) + EOF + ) + # Strip leading whitespace from heredoc lines + BODY=$(echo "$BODY" | sed 's/^ //') -Generated by [weekly-update.yml](.github/workflows/weekly-update.yml)" \ + gh pr create \ + --title "chore(deps): weekly dependency update ($(date +%Y-%m-%d))" \ + --body "$BODY" \ --draft \ --head "$BRANCH_NAME" \ --base main From 1da4fcf8b4660517e14e376baf16543c771624ab Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 25 Mar 2026 11:33:13 -0400 Subject: [PATCH 6/8] chore(ci): add zizmor config to disable secrets-outside-env The weekly-update workflow intentionally passes ANTHROPIC_API_KEY outside the env block. Disable the zizmor secrets-outside-env audit. --- .github/zizmor.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/zizmor.yml diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 00000000..944e1474 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,2 @@ +secrets-outside-env: + disable: true From 15784a8fff77da7b4d25c1e77a99b860f5b93e2a Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 25 Mar 2026 11:43:54 -0400 Subject: [PATCH 7/8] fix(ci): nest zizmor config under rules key --- .github/zizmor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 944e1474..39d1b180 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -1,2 +1,3 @@ -secrets-outside-env: - disable: true +rules: + secrets-outside-env: + disable: true From f5c1eabbd91e79847f5b4bc4b4bbc447d69ee1a3 Mon Sep 17 00:00:00 2001 From: jdalton Date: Wed, 25 Mar 2026 11:44:57 -0400 Subject: [PATCH 8/8] fix(ci): add persist-credentials: false and use token URL for push --- .github/workflows/weekly-update.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/weekly-update.yml b/.github/workflows/weekly-update.yml index 16f1cbdb..faf341dc 100644 --- a/.github/workflows/weekly-update.yml +++ b/.github/workflows/weekly-update.yml @@ -66,6 +66,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 @@ -127,8 +128,11 @@ jobs: - name: Push branch if: steps.claude.outputs.success == 'true' && steps.changes.outputs.has-changes == 'true' env: + GITHUB_TOKEN: ${{ github.token }} BRANCH_NAME: ${{ steps.branch.outputs.branch }} - run: git push origin "$BRANCH_NAME" + run: | + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.git" + git push origin "$BRANCH_NAME" - name: Create Pull Request if: steps.claude.outputs.success == 'true' && steps.changes.outputs.has-changes == 'true'