From 85b6cc7d65aef425446b999e8dd1bd1f80bcb033 Mon Sep 17 00:00:00 2001 From: Shinrai Date: Sun, 27 Sep 2026 23:51:38 -0700 Subject: [PATCH 1/4] ci: sync v4 workflows with CLDMV/.github v4.29.2 templates --- .github/dependabot.yml | 15 +- .github/workflows/branch-retention.yml | 6 +- .github/workflows/ci.yml | 586 ++++++++++-------- .github/workflows/cla.yml | 8 +- .github/workflows/codeql.yml | 17 +- .github/workflows/dependabot-auto-merge.yml | 8 +- .github/workflows/dependabot-recreate.yml | 63 ++ .github/workflows/dependency-review.yml | 8 + .github/workflows/feature-pr.yml | 15 +- .github/workflows/hotfix-redirector.yml | 12 +- .github/workflows/hotfixes-release.yml | 13 +- .github/workflows/master-commit-audit.yml | 62 +- .github/workflows/member-auto-merge.yml | 71 +++ .github/workflows/next-release.yml | 13 +- .github/workflows/next-reset.yml | 7 +- .github/workflows/pr-notify.yml | 40 ++ .github/workflows/pr-title-normalizer.yml | 7 +- .github/workflows/provenance.yml | 47 ++ .github/workflows/publish.yml | 227 +++---- .github/workflows/release-merge.yml | 96 +++ .github/workflows/scorecard.yml | 21 +- .github/workflows/tag-health.yml | 4 +- .../workflows/update-major-version-tags.yml | 147 ++--- .github/workflows/v4-bootstrap.yml | 7 +- 24 files changed, 971 insertions(+), 529 deletions(-) create mode 100644 .github/workflows/dependabot-recreate.yml create mode 100644 .github/workflows/member-auto-merge.yml create mode 100644 .github/workflows/pr-notify.yml create mode 100644 .github/workflows/provenance.yml create mode 100644 .github/workflows/release-merge.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 388da65..4a1aedf 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/automation/dependabot.yml +# @Project: gitmulti +# @Filename: /.github/dependabot.yml # @Date: 2026-05-26 00:00:00 -07:00 (1782460800) # @Author: Nate Corcoran # @Email: @@ -69,10 +69,13 @@ updates: prefix: "deps" groups: # vitest and @vitest/coverage-v8 (and other @vitest/* packages) peer - # each other exactly, so bumping one without the other breaks - # `npm ci` with an ERESOLVE. Bump the whole family together in one - # PR. Must come before security/patch/minor below โ€” Dependabot - # assigns each update to the FIRST matching group. + # each other EXACTLY, so a partial bump (e.g. vitest to 5.0.0 while + # @vitest/coverage-v8 stays 4.1.11) breaks `npm ci` with an ERESOLVE. + # Bump the whole family together in one PR so the exact-peer + # versions never diverge. Must come before security/patch/minor + # below โ€” Dependabot assigns each update to the FIRST matching + # group, and this one has no applies-to restriction so it always + # wins for vitest-family packages regardless of update type. vitest: patterns: - "vitest" diff --git a/.github/workflows/branch-retention.yml b/.github/workflows/branch-retention.yml index 266d102..4a73bcf 100644 --- a/.github/workflows/branch-retention.yml +++ b/.github/workflows/branch-retention.yml @@ -26,11 +26,13 @@ on: branches: [master, main, next, hotfixes] permissions: - contents: write - pull-requests: read + contents: read jobs: retain: + permissions: + contents: write + pull-requests: read if: github.event.pull_request.merged == true uses: CLDMV/.github/.github/workflows/reusable-branch-retention.yml@v4 secrets: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c11218..2c4850c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,125 +11,146 @@ name: ๐Ÿงช CI Tests & Build on: - # Note: do NOT add `paths:` / `paths-ignore:` at the trigger level. Doing - # that makes GitHub skip the workflow entirely for docs-only changes, which - # means `Required PR Check` never posts and the ruleset blocks the merge. - # The reusable workflow's `paths-gate` job does the same job from inside, - # and exposes a `docs_only` output so this workflow can still green-light - # the required check for docs-only PRs (see `required-check` below). The - # ignore globs themselves are passed via the `paths_ignore:` input below - # โ€” override there if your repo needs different rules. - # - # `push` fires for branches in this repo only (forks push to their own remote, - # not ours). Branch protection on the PR reads the status check from the - # commit SHA, so this single trigger covers both pre-PR pushes and PR head - # updates without duplicating runs. - push: - # Bot-managed branches (badges, gh-pages) carry no source to test. - branches-ignore: [badges, gh-pages] - # `pull_request` covers two cases: - # - Fork PRs (push doesn't fire upstream for fork commits). - # - Release PRs from `next` / `hotfixes` โ†’ `master`. Their head SHA is - # a bot `chore: bump version` commit that workflow-ci.yml's - # `commit-gate` job filters out on the push path, so without the - # pull_request fallback the release PR's `Required PR Check` - # status never gets posted and the ruleset blocks the merge. - # `branches:` includes the v4 integration branches so PRs targeting - # `next` / `hotfixes` get CI too โ€” feature PRs from forks would - # otherwise get nothing. Non-fork feature PRs still skip the - # pull_request `ci` job (push covers them); see the `if:` on the job. - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - branches: [master, main, next, hotfixes] - workflow_dispatch: - inputs: - debug: - description: "Enable debug logging for troubleshooting" - type: boolean - required: false - default: false - node_version: - description: "Node.js version to use (default: lts/*)" - type: string - required: false - default: "lts/*" - min_node_version: - description: "Minimum Node.js version for matrix testing (default: 22.12.0 โ€” the floor vitest 5 actually runs on)" - type: string - required: false - default: "22.12.0" - max_node_major: - description: "Override max Node.js major version (default: 26)" - type: string - required: false - default: "26" - lts_only_matrix: - description: "Only include even-numbered (LTS) Node.js major versions in the test matrix" - type: boolean - required: false - default: true - package_manager: - description: "Package manager (npm or yarn)" - type: string - required: false - default: "npm" - test_environment: - description: "Environment for tests (affects NODE_ENV and NODE_OPTIONS --conditions flag)" - type: string - required: false - default: "development" - # โ”€โ”€ Coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - enable_coverage_badge: - description: "Run the coverage + badge-push job after CI passes" - type: boolean - required: false - default: true - coverage_command: - description: "Command to run tests and generate coverage data" - type: string - required: false - default: "npm run ci:coverage" - coverage_summary_path: - description: "Path to the coverage-summary.json produced by Jest / c8" - type: string - required: false - default: "coverage/coverage-summary.json" - badges_branch: - description: "Branch where the badge JSON is published" - type: string - required: false - default: "badges" - badge_filename: - description: "Filename for the badge JSON committed to the badges branch" - type: string - required: false - default: "coverage.json" - upload_coverage_artifact: - description: "Upload the full coverage/ directory as a workflow artifact" - type: boolean - required: false - default: true - # โ”€โ”€ Type check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - type_check_command: - description: "Command to run type checking" - type: string - required: false - default: "npm run test:types" - skip_type_check: - description: "Skip the type-check step in the coverage-badge job" - type: boolean - required: false - default: false - default_branch: - description: "Default branch name โ€” badge is only pushed on pushes to this branch" - type: string - required: false - default: "master" - enable_coverage_pr_comment: - description: "Inject a coverage badge into the PR description on pull request events" - type: boolean - required: false - default: true + # Note: do NOT add `paths:` / `paths-ignore:` at the trigger level. Doing + # that makes GitHub skip the workflow entirely for docs-only changes, which + # means `Required PR Check` never posts and the ruleset blocks the merge. + # The reusable workflow's `paths-gate` job does the same job from inside, + # and exposes a `docs_only` output so this workflow can still green-light + # the required check for docs-only PRs (see `required-check` below). The + # ignore globs themselves are passed via the `paths_ignore:` input below + # โ€” override there if your repo needs different rules. + # + # `push` fires for branches in this repo only (forks push to their own remote, + # not ours). Branch protection on the PR reads the status check from the + # commit SHA, so this single trigger covers both pre-PR pushes and PR head + # updates without duplicating runs. + push: + # Bot-managed branches (badges, gh-pages) carry no source to test. + branches-ignore: [badges, gh-pages] + # `pull_request` covers two cases: + # - Fork PRs (push doesn't fire upstream for fork commits). + # - Release PRs from `next` / `hotfixes` โ†’ `master`. Their head SHA is + # a bot `chore: bump version` commit that workflow-ci.yml's + # `commit-gate` job filters out on the push path, so without the + # pull_request fallback the release PR's `Required PR Check` + # status never gets posted and the ruleset blocks the merge. + # `branches:` includes the v4 integration branches so PRs targeting + # `next` / `hotfixes` get CI too โ€” feature PRs from forks would + # otherwise get nothing. Non-fork feature PRs still skip the + # pull_request `ci` job (push covers them); see the `if:` on the job. + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: [master, main, next, hotfixes] + workflow_dispatch: + inputs: + debug: + description: "Enable debug logging for troubleshooting" + type: boolean + required: false + default: false + node_version: + description: "Node.js version to use (default: lts/*)" + type: string + required: false + default: "lts/*" + min_node_version: + description: "Minimum Node.js version for matrix testing (default: 22.12.0 โ€” the floor vitest 5 actually runs on)" + type: string + required: false + default: "22.12.0" + max_node_major: + description: "Max Node.js major version for the test matrix. Leave blank (the default) to inherit the CLDMV/.github reusable workflow's default; set a value only to pin/override for a specific run." + type: string + required: false + default: "" + lts_only_matrix: + description: "Only include even-numbered (LTS) Node.js major versions in the test matrix" + type: boolean + required: false + default: true + package_manager: + description: "Package manager (npm or yarn)" + type: string + required: false + default: "npm" + test_environment: + description: "Environment for tests (affects NODE_ENV and NODE_OPTIONS --conditions flag)" + type: string + required: false + default: "development" + # โ”€โ”€ Lint & format (autofix) โ€” all default to `--if-present` (no-op when absent) + format_command: + description: "Formatter that writes fixes (prettier --write)" + type: string + required: false + default: "npm run format --if-present" + lint_fix_command: + description: "Linter that writes safe fixes (eslint --fix)" + type: string + required: false + default: "npm run lint:fix --if-present" + lint_command: + description: "Lint check (no writes) โ€” the authoritative lint gate" + type: string + required: false + default: "npm run lint --if-present" + format_check_command: + description: "Format check (no writes) โ€” used on fork / integration branches" + type: string + required: false + default: "npm run format:check --if-present" + # โ”€โ”€ Coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + enable_coverage_badge: + description: "Run the coverage + badge-push job after CI passes" + type: boolean + required: false + default: true + coverage_command: + description: "Command to run tests and generate coverage data" + type: string + required: false + default: "npm run ci:coverage" + coverage_summary_path: + description: "Path to the coverage-summary.json produced by Jest / c8" + type: string + required: false + default: "coverage/coverage-summary.json" + badges_branch: + description: "Branch where the badge JSON is published" + type: string + required: false + default: "badges" + badge_filename: + description: "Filename for the badge JSON committed to the badges branch" + type: string + required: false + default: "coverage.json" + upload_coverage_artifact: + description: "Upload the full coverage/ directory as a workflow artifact" + type: boolean + required: false + default: true + # โ”€โ”€ Type check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + type_check_command: + description: "Command to run type checking" + type: string + required: false + default: "npm run test:types" + skip_type_check: + description: "Skip the type-check step in the coverage-badge job" + type: boolean + required: false + default: false + default_branch: + description: "Default branch name โ€” badge is only pushed on pushes to this branch" + type: string + required: false + default: "master" + enable_coverage_pr_comment: + description: "Inject a coverage badge into the PR description on pull request events" + type: boolean + required: false + default: true # Concurrency policy, by context: # - FEATURE branches / feature PRs โ†’ cancel superseded runs (per-ref group + @@ -150,8 +171,8 @@ on: # is set only on pull_request (the release PR's head โ†’ next/hotfixes); # github.ref carries the branch on push. concurrency: - group: ci-${{ github.workflow }}-${{ github.ref }}${{ (github.ref == format('refs/heads/{0}', vars.CLDMV_RELEASE_BASE != '' && vars.CLDMV_RELEASE_BASE || github.event.repository.default_branch) || github.ref == 'refs/heads/next' || github.ref == 'refs/heads/hotfixes' || github.head_ref == 'next' || github.head_ref == 'hotfixes') && format('-{0}', github.run_id) || '' }} - cancel-in-progress: true + group: ci-${{ github.workflow }}-${{ github.ref }}${{ (github.ref == format('refs/heads/{0}', vars.CLDMV_RELEASE_BASE != '' && vars.CLDMV_RELEASE_BASE || github.event.repository.default_branch) || github.ref == 'refs/heads/next' || github.ref == 'refs/heads/hotfixes' || github.head_ref == 'next' || github.head_ref == 'hotfixes') && format('-{0}', github.run_id) || '' }} + cancel-in-progress: true # Workflow-level: matches the broadest write surface the called # `workflow-ci.yml` reaches across its branches: @@ -161,162 +182,181 @@ concurrency: # inherit but never exercise the surface. The mirror job overrides to # `permissions: {}` since it's pure shell. permissions: - contents: write - pull-requests: write + contents: read jobs: - ci: - name: ๐Ÿ—๏ธ Continuous Integration - # Run on pull_request when: - # - The PR is from a fork (push doesn't fire upstream for fork commits). - # - The PR is a v4 release PR โ€” head ref is `next` or `hotfixes` - # targeting `master`/`main`. Push-event CI on the head SHA is - # unreliable for these because workflow-ci.yml's `commit-gate` - # filters out the bot's `chore: bump version` commit, so without - # this fallback the release PR's `Required PR Check` never posts. - # Other (in-repo, non-release) PRs skip โ€” the push event on the head - # branch already ran CI and posted status to the SHA. - if: | - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.fork == true || - github.event.pull_request.head.ref == 'next' || - github.event.pull_request.head.ref == 'hotfixes' - uses: CLDMV/.github/.github/workflows/workflow-ci.yml@v4 - with: - package_name: "gitmulti" # Required: replace with your NPM package name - # Globs that should NOT trigger the heavy CI matrix. When every changed - # file matches one of these, `docs_only=true` flows out of the reusable - # and `required-check` below posts a green Required PR Check without - # running CI. The default in the reusable matches these โ€” override only - # if your repo needs different rules. - paths_ignore: | - **.md - docs/** - *.md - LICENSE - .gitignore - debug: ${{ github.event.inputs.debug == 'true' }} - node_version: ${{ github.event.inputs.node_version || 'lts/*' }} - min_node_version: ${{ github.event.inputs.min_node_version || '22.12.0' }} - max_node_major: ${{ github.event.inputs.max_node_major || '26' }} - # LTS-only matrix (even majors: 20, 22, 24, โ€ฆ) on every event. Odd majors - # (21, 23, โ€ฆ) are non-LTS interim releases, and the native-binding test - # toolchain (vitest 4 / rolldown / vite 8) excludes them via `engines` - # (`^20.19.0 || >=22.12.0`), so a "full matrix" on them only re-discovers a - # known toolchain gap ("Cannot find native binding") rather than a real - # per-version regression. workflow_dispatch can still opt out (set false). - lts_only_matrix: ${{ github.event.inputs.lts_only_matrix != 'false' }} - package_manager: ${{ github.event.inputs.package_manager || 'npm' }} - test_command: "npm test" # Use defaults: NODE_ENV=development, NODE_OPTIONS=--conditions=development - # test_command: "NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override NODE_OPTIONS only - # test_command: "NODE_ENV=test npm test" # Override NODE_ENV only - # test_command: "NODE_ENV=test NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override both - test_environment: ${{ github.event.inputs.test_environment || 'development' }} # Alternative to setting in test_command - build_command: "echo 'โœ“ no build step'" - skip_performance_tests: false - skip_matrix_tests: false + ci: + permissions: + contents: write + pull-requests: write + name: ๐Ÿ—๏ธ Continuous Integration + # Run on pull_request when: + # - The PR is from a fork (push doesn't fire upstream for fork commits). + # - The PR is a v4 release PR โ€” head ref is `next` or `hotfixes` + # targeting `master`/`main`. Push-event CI on the head SHA is + # unreliable for these because workflow-ci.yml's `commit-gate` + # filters out the bot's `chore: bump version` commit, so without + # this fallback the release PR's `Required PR Check` never posts. + # Other (in-repo, non-release) PRs skip โ€” the push event on the head + # branch already ran CI and posted status to the SHA. + if: | + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.fork == true || + github.event.pull_request.head.ref == 'next' || + github.event.pull_request.head.ref == 'hotfixes' + uses: CLDMV/.github/.github/workflows/workflow-ci.yml@v4 + with: + package_name: "gitmulti" # Required: replace with your NPM package name + # Globs that should NOT trigger the heavy CI matrix. When every changed + # file matches one of these, `docs_only=true` flows out of the reusable + # and `required-check` below posts a green Required PR Check without + # running CI. The default in the reusable matches these โ€” override only + # if your repo needs different rules. + paths_ignore: | + **.md + docs/** + *.md + LICENSE + .gitignore + debug: ${{ github.event.inputs.debug == 'true' }} + node_version: ${{ github.event.inputs.node_version || 'lts/*' }} + min_node_version: ${{ github.event.inputs.min_node_version || '22.12.0' }} + max_node_major: ${{ github.event.inputs.max_node_major || '' }} # blank โ‡’ inherit the CLDMV/.github reusable default + # LTS-only matrix (even majors: 20, 22, 24, โ€ฆ) on every event. Odd majors + # (21, 23, โ€ฆ) are non-LTS interim releases, and the native-binding test + # toolchain (vitest 4 / rolldown / vite 8) excludes them via `engines` + # (`^20.19.0 || >=22.12.0`), so a "full matrix" on them only re-discovers a + # known toolchain gap ("Cannot find native binding") rather than a real + # per-version regression. workflow_dispatch can still opt out (set false). + lts_only_matrix: ${{ github.event.inputs.lts_only_matrix != 'false' }} + package_manager: ${{ github.event.inputs.package_manager || 'npm' }} + test_command: "npm test" # Use defaults: NODE_ENV=development, NODE_OPTIONS=--conditions=development + # test_command: "NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override NODE_OPTIONS only + # test_command: "NODE_ENV=test npm test" # Override NODE_ENV only + # test_command: "NODE_ENV=test NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override both + test_environment: ${{ github.event.inputs.test_environment || 'development' }} # Alternative to setting in test_command + # โ”€โ”€ Lint & format (autofix gate) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # The lint-format job applies safe fixes (prettier --write, eslint --fix) + # and commits them back on internal branches; on fork PRs / integration + # branches it runs the check variants and fails with a fix hint. Every + # command uses `--if-present`, so a repo with no such script is a graceful + # no-op. Add the scripts to package.json to opt in; override a command for + # a monorepo-aware invocation; or set empty ("") to disable that phase. + format_command: ${{ github.event.inputs.format_command || 'npm run format --if-present' }} + lint_fix_command: ${{ github.event.inputs.lint_fix_command || 'npm run lint:fix --if-present' }} + lint_command: ${{ github.event.inputs.lint_command || 'npm run lint --if-present' }} + format_check_command: ${{ github.event.inputs.format_check_command || 'npm run format:check --if-present' }} + build_command: "echo 'โœ“ no build step'" + skip_performance_tests: false + skip_matrix_tests: false - # โ”€โ”€ Coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - # Runs after a successful CI build; pushes a Shields.io-compatible badge - # JSON to the `badges` branch (signed commit via bot GPG). - # Only runs on direct pushes to default_branch โ€” PRs and feature branches - # are automatically skipped so coverage always reflects merged master code. - # Requires: the coverage_command produces coverage/coverage-summary.json - enable_coverage_badge: ${{ github.event.inputs.enable_coverage_badge != 'false' }} - default_branch: ${{ github.event.inputs.default_branch || 'master' }} # Badge only pushed when a push lands on this branch - coverage_command: ${{ github.event.inputs.coverage_command || 'npm run ci:coverage' }} - coverage_summary_path: ${{ github.event.inputs.coverage_summary_path || 'coverage/coverage-summary.json' }} - badges_branch: ${{ github.event.inputs.badges_branch || 'badges' }} - badge_filename: ${{ github.event.inputs.badge_filename || 'coverage.json' }} - upload_coverage_artifact: ${{ github.event.inputs.upload_coverage_artifact != 'false' }} + # โ”€โ”€ Coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Runs after a successful CI build; pushes a Shields.io-compatible badge + # JSON to the `badges` branch (signed commit via bot GPG). + # Only runs on direct pushes to default_branch โ€” PRs and feature branches + # are automatically skipped so coverage always reflects merged master code. + # Requires: the coverage_command produces coverage/coverage-summary.json + enable_coverage_badge: ${{ github.event.inputs.enable_coverage_badge != 'false' }} + default_branch: ${{ github.event.inputs.default_branch || 'master' }} # Badge only pushed when a push lands on this branch + coverage_command: ${{ github.event.inputs.coverage_command || 'npm run ci:coverage' }} + coverage_summary_path: ${{ github.event.inputs.coverage_summary_path || 'coverage/coverage-summary.json' }} + badges_branch: ${{ github.event.inputs.badges_branch || 'badges' }} + badge_filename: ${{ github.event.inputs.badge_filename || 'coverage.json' }} + upload_coverage_artifact: ${{ github.event.inputs.upload_coverage_artifact != 'false' }} - # โ”€โ”€ Type check (runs inside the coverage-badge job) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - # Skipped deliberately: plain JavaScript package with no TypeScript sources - # or shipped type declarations, so there is no meaningful JS type-check to - # run. ESLint is the static-analysis net. - type_check_command: ${{ github.event.inputs.type_check_command || 'npm run test:types' }} - skip_type_check: true + # โ”€โ”€ Type check (runs inside the coverage-badge job) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Skipped deliberately: plain JavaScript package with no TypeScript sources + # or shipped type declarations, so there is no meaningful JS type-check to + # run. ESLint is the static-analysis net. + type_check_command: ${{ github.event.inputs.type_check_command || 'npm run test:types' }} + skip_type_check: true - # โ”€โ”€ PR coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - # Injects a Shields.io badge + breakdown table directly into the PR body - # on every push to the PR branch. Only fires on pull_request events; - # skipped automatically on push and workflow_dispatch. No files committed. - enable_coverage_pr_comment: ${{ github.event.inputs.enable_coverage_pr_comment != 'false' }} + # โ”€โ”€ PR coverage badge โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + # Injects a Shields.io badge + breakdown table directly into the PR body + # on every push to the PR branch. Only fires on pull_request events; + # skipped automatically on push and workflow_dispatch. No files committed. + enable_coverage_pr_comment: ${{ github.event.inputs.enable_coverage_pr_comment != 'false' }} - # Authentication & Bot Configuration - # The workflow supports automatic App token detection for enhanced permissions and proper attribution: - # - WITH App secrets: Operations attributed to CLDMV bot, enhanced permissions for workflow repositories - # - WITHOUT App secrets: Falls back to GitHub Actions bot with standard permissions - # Note: CI workflow currently only runs build/test jobs, but App secrets are included for consistency - # To set up App authentication, add these secrets to your repository settings: - secrets: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - # Optional: CLDMV Bot credentials for enhanced permissions and proper attribution - # If not provided, will use default GITHUB_TOKEN with GitHub Actions bot attribution - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - # Required when enable_coverage_badge: true - BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} - BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} - BOT_GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} - BOT_GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} + # Authentication & Bot Configuration + # The workflow supports automatic App token detection for enhanced permissions and proper attribution: + # - WITH App secrets: Operations attributed to CLDMV bot, enhanced permissions for workflow repositories + # - WITHOUT App secrets: Falls back to GitHub Actions bot with standard permissions + # Note: CI workflow currently only runs build/test jobs, but App secrets are included for consistency + # To set up App authentication, add these secrets to your repository settings: + secrets: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # Optional: CLDMV Bot credentials for enhanced permissions and proper attribution + # If not provided, will use default GITHUB_TOKEN with GitHub Actions bot attribution + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Required when enable_coverage_badge: true + BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} + BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} + BOT_GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} + BOT_GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} - # โœ… Stable check that mirrors the `ci` result so branch protection has a - # single, predictable status name to require. The push event runs on the - # same SHA that becomes the PR head, so the status attaches to the PR - # automatically โ€” no `pull_request` round-trip needed for non-fork - # non-release PRs. - required-check: - name: โœ… Required PR Check - needs: ci - # Mirror the `ci` job's gating exactly. The four cases that run: - # 1. push events (job needs CI run) - # 2. fork PRs (push doesn't cover forks) - # 3. release PRs from `next` โ†’ master/main (push covers SHA but commit-gate skips chore-bump) - # 4. release PRs from `hotfixes` โ†’ master/main (same reason) - # In-repo feature PRs targeting `next` / `hotfixes` skip on - # pull_request โ€” push on the head branch already posted the status - # on the SHA, and mirroring here would overwrite it. - if: | - always() && ( - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.fork == true || - github.event.pull_request.head.ref == 'next' || - github.event.pull_request.head.ref == 'hotfixes' - ) - runs-on: ubuntu-latest - # Pure shell mirror โ€” no GitHub API access. Strip the workflow's - # write defaults to zero for this job. - permissions: {} - steps: - - name: Mirror reusable result - env: - IS_MASTER_SYNC: ${{ needs.ci.outputs.is_master_sync }} - DOCS_ONLY: ${{ needs.ci.outputs.docs_only }} - CI_RESULT: ${{ needs.ci.result }} - run: | - echo "ci.result=$CI_RESULT docs_only=$DOCS_ONLY is_master_sync=$IS_MASTER_SYNC" - # next/hotfixes was force-synced to master โ€” head SHA matches the - # default branch, nothing new to test, green-light without running CI. - if [ "$IS_MASTER_SYNC" = "true" ]; then - echo "Branch tip matches master โ€” Required PR Check passes without running CI." - exit 0 - fi - # Docs-only PR โ€” the reusable skipped the heavy chain and exported - # docs_only=true. Green-light Required PR Check so the ruleset - # doesn't block a docs change. - if [ "$DOCS_ONLY" = "true" ]; then - echo "Docs-only change โ€” Required PR Check passes without running CI." - exit 0 - fi - if [ "$CI_RESULT" = "success" ]; then - echo "Reusable CI passed." - exit 0 - elif [ "$CI_RESULT" = "failure" ] || [ "$CI_RESULT" = "cancelled" ]; then - echo "Reusable CI did not pass." - exit 1 - else - # covers 'skipped' or undefined; force red to avoid silent green - echo "Reusable CI produced no pass/fail; treating as failure." - exit 1 - fi + # โœ… Stable check that mirrors the `ci` result so branch protection has a + # single, predictable status name to require. The push event runs on the + # same SHA that becomes the PR head, so the status attaches to the PR + # automatically โ€” no `pull_request` round-trip needed for non-fork + # non-release PRs. + required-check: + name: โœ… Required PR Check + needs: ci + # Mirror the `ci` job's gating exactly. The four cases that run: + # 1. push events (job needs CI run) + # 2. fork PRs (push doesn't cover forks) + # 3. release PRs from `next` โ†’ master/main (push covers SHA but commit-gate skips chore-bump) + # 4. release PRs from `hotfixes` โ†’ master/main (same reason) + # In-repo feature PRs targeting `next` / `hotfixes` skip on + # pull_request โ€” push on the head branch already posted the status + # on the SHA, and mirroring here would overwrite it. + if: | + always() && ( + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.fork == true || + github.event.pull_request.head.ref == 'next' || + github.event.pull_request.head.ref == 'hotfixes' + ) + # Match the reusable's runner routing (workflow-ci.yml): private CLDMV + # repos run on self-hosted cldmv-runners (GitHub-hosted Actions budget is + # private-metered and exhausted), public repos use free GitHub-hosted, and + # RUNS_ON_DEFAULT overrides. Hardcoding ubuntu-latest here made this + # required check fail to provision a runner on private repos once the + # reusable moved its own jobs to cldmv-runners in v4.19.1 (see #208). + runs-on: ${{ vars.RUNS_ON_DEFAULT != '' && vars.RUNS_ON_DEFAULT || ((github.repository_owner == 'CLDMV' && github.event.repository.private) && 'cldmv-runners' || 'ubuntu-latest') }} + # Pure shell mirror โ€” no GitHub API access. Strip the workflow's + # write defaults to zero for this job. + permissions: {} + steps: + - name: Mirror reusable result + env: + IS_MASTER_SYNC: ${{ needs.ci.outputs.is_master_sync }} + DOCS_ONLY: ${{ needs.ci.outputs.docs_only }} + CI_RESULT: ${{ needs.ci.result }} + run: | + echo "ci.result=$CI_RESULT docs_only=$DOCS_ONLY is_master_sync=$IS_MASTER_SYNC" + # next/hotfixes was force-synced to master โ€” head SHA matches the + # default branch, nothing new to test, green-light without running CI. + if [ "$IS_MASTER_SYNC" = "true" ]; then + echo "Branch tip matches master โ€” Required PR Check passes without running CI." + exit 0 + fi + # Docs-only PR โ€” the reusable skipped the heavy chain and exported + # docs_only=true. Green-light Required PR Check so the ruleset + # doesn't block a docs change. + if [ "$DOCS_ONLY" = "true" ]; then + echo "Docs-only change โ€” Required PR Check passes without running CI." + exit 0 + fi + if [ "$CI_RESULT" = "success" ]; then + echo "Reusable CI passed." + exit 0 + elif [ "$CI_RESULT" = "failure" ] || [ "$CI_RESULT" = "cancelled" ]; then + echo "Reusable CI did not pass." + exit 1 + else + # covers 'skipped' or undefined; force red to avoid silent green + echo "Reusable CI produced no pass/fail; treating as failure." + exit 1 + fi diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index fc7b6af..20ba5f0 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -42,12 +42,14 @@ on: permissions: contents: read - pull-requests: write - statuses: write - issues: write jobs: cla: + permissions: + contents: read + pull-requests: write + statuses: write + issues: write uses: CLDMV/.github/.github/workflows/reusable-cla.yml@v4 with: cla_version: "1.0" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1415501..f2d1cbb 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -9,6 +9,17 @@ # Individual repo: .github/workflows/codeql.yml # +# PRIVATE REPOS are skipped by DEFAULT: the bootstrap's `variables` phase +# sets CLDMV_SKIP_CODE_SCANNING (this workflow then uploads an empty 0-alert +# SARIF instead of analyzing) on every private repo not opted in, since Code +# Security bills per active committer there. To actually scan a private +# repo: pay for GitHub Code Security and add the repo to the `scan` list in +# data/code-scanning-skips.json in CLDMV/.github. Public repos scan by +# default (free); a public repo with nothing to analyze goes in that file's +# `skip` section. Consumers outside CLDMV can pass `skip_code_scanning: +# true` below instead. Do NOT just delete this file on a repo whose ruleset +# requires code_scanning โ€” the gate then waits forever. +# # REQUIRED REPO SETTING โ€” CodeQL must be in "Advanced" mode for this workflow # to upload SARIF. If the repo has CodeQL "Default setup" enabled (the # GitHub-managed alternative), upload runs fail with: @@ -50,9 +61,7 @@ on: - cron: "37 14 * * 1" # weekly Monday 14:37 UTC; GitHub updates queries over time permissions: - security-events: write contents: read - actions: read concurrency: group: codeql-${{ github.workflow }}-${{ github.ref }} @@ -60,6 +69,10 @@ concurrency: jobs: analyze: + permissions: + security-events: write + contents: read + actions: read uses: CLDMV/.github/.github/workflows/reusable-codeql.yml@v4 with: languages: "javascript-typescript" diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 12e104e..cb24ae3 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -37,16 +37,20 @@ on: types: [opened, reopened, synchronize, ready_for_review] permissions: - contents: write - pull-requests: write + contents: read jobs: automerge: + permissions: + contents: write + pull-requests: write # Pre-filter at workflow level so this doesn't spin up for every PR. if: github.event.pull_request.user.login == 'dependabot[bot]' uses: CLDMV/.github/.github/workflows/reusable-dependabot-auto-merge.yml@v4 with: bump_types: "patch,minor" + # merge_method defaults to "merge" โ€” Dependabot PRs target next / hotfixes, + # whose rulesets are merge-only. Override only if your branches differ. merge_method: "squash" # also_for_actors: "renovate[bot]" # extend if you adopt Renovate secrets: diff --git a/.github/workflows/dependabot-recreate.yml b/.github/workflows/dependabot-recreate.yml new file mode 100644 index 0000000..b64e3d9 --- /dev/null +++ b/.github/workflows/dependabot-recreate.yml @@ -0,0 +1,63 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/dependabot-recreate.yml +# @Date: 2026-07-31 00:00:00 -07:00 (1785481200) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# Individual repo: .github/workflows/dependabot-recreate.yml +# +# Auto-fires `@dependabot recreate` when a Dependabot PR gets stuck in the +# "edited by someone other than Dependabot" state. That state breaks +# `@dependabot rebase` and โ€” under a required-signed-commits ruleset โ€” blocks +# the PR with an unsigned commit. `recreate` rebuilds it as a fresh, signed +# Dependabot commit that dependabot-auto-merge.yml then merges. See +# reusable-dependabot-recreate.yml for the mechanics + the command-actor caveat. +# +# Default in v4: ON. Delete this file to opt out entirely; add a `no-recreate` +# label to a specific PR to exempt just that one (e.g. one you've hand-edited +# on purpose and don't want overwritten). +# +# Triggers: +# - issue_comment: catches Dependabot's own "can't rebase, use recreate" reply +# (Dependabot only comments back when a rebase FAILS โ€” success is a silent +# ๐Ÿ‘ + force-push). +# - pull_request_target: proactive net for a Dependabot PR whose head commit +# is unverified. pull_request_target (not pull_request) is required so the +# job can read the bot-App secrets โ€” Dependabot-triggered `pull_request` +# runs get a read-only token and no secrets. It is SAFE here: Dependabot PRs +# are same-repo branches (not forks), and this workflow never checks out or +# runs PR code โ€” it only reads the PR and posts a comment via the API. +name: ๐Ÿ” Dependabot Auto-Recreate + +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + recreate: + # A) Dependabot replied that it can't rebase (the PR was edited), or + # B) a Dependabot PR opened/updated โ€” the reusable then checks whether + # its head commit is actually unverified before doing anything. + if: >- + (github.event_name == 'issue_comment' + && github.event.issue.pull_request + && github.event.comment.user.login == 'dependabot[bot]' + && contains(github.event.comment.body, 'edited by someone other than Dependabot')) + || (github.event_name == 'pull_request_target' + && github.event.pull_request.user.login == 'dependabot[bot]') + uses: CLDMV/.github/.github/workflows/reusable-dependabot-recreate.yml@v4 + with: + skip_label: "no-recreate" + secrets: + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 0bfb7e3..671a80e 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -8,6 +8,14 @@ # # Individual repo: .github/workflows/dependency-review.yml +# +# PRIVATE REPOS are skipped by DEFAULT (the dependency-review API needs +# GitHub Advanced Security there): the bootstrap's `variables` phase sets +# CLDMV_SKIP_DEPENDENCY_REVIEW on every private repo not opted into the +# `scan` list in data/code-scanning-skips.json in CLDMV/.github. To run the +# review on a private repo, pay for Code Security and add it to that list. +# Consumers outside CLDMV can pass `skip_dependency_review: true` below +# instead. name: ๐Ÿ”’ Dependency Review on: diff --git a/.github/workflows/feature-pr.yml b/.github/workflows/feature-pr.yml index 150a294..6008b0f 100644 --- a/.github/workflows/feature-pr.yml +++ b/.github/workflows/feature-pr.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/feature-pr.yml +# @Project: gitmulti +# @Filename: /.github/workflows/feature-pr.yml # @Author: Nate Corcoran # @Email: # @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. @@ -12,7 +12,7 @@ # right integration branch on every push. # # Mapping (matches CLDMV/.github docs/conventions/branch-naming.md): -# feat/*, feature/*, fix/*, release/*, chore/*, refactor/*, +# feat/*, feature/*, fix/*, release/*, chore/*, deps/*, refactor/*, # docs/*, ci/*, perf/*, test/*, style/* โ†’ next # hotfix/* โ†’ hotfixes # @@ -35,6 +35,7 @@ on: - 'fix/**' - 'release/**' - 'chore/**' + - 'deps/**' - 'refactor/**' - 'docs/**' - 'ci/**' @@ -47,6 +48,9 @@ concurrency: group: feature-pr-${{ github.repository }}-${{ github.ref }} cancel-in-progress: false +permissions: + contents: read + jobs: open-pr: permissions: @@ -57,5 +61,10 @@ jobs: # Map your repo/org secrets to the expected names. BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Optional: only needed if you also use reusable-lint-format.yml / + # reusable-coverage-badge.yml (or otherwise sign a commit locally as + # this identity). Passed through so this PR's changelog body + # recognizes that identity as a bot instead of listing it as a + # contributor. BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} diff --git a/.github/workflows/hotfix-redirector.yml b/.github/workflows/hotfix-redirector.yml index 9ff0443..900ed1c 100644 --- a/.github/workflows/hotfix-redirector.yml +++ b/.github/workflows/hotfix-redirector.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/hotfix-redirector.yml +# @Project: gitmulti +# @Filename: /.github/workflows/hotfix-redirector.yml # @Date: 2026-05-22 00:00:00 -07:00 (1779778800) # @Author: Nate Corcoran # @Email: @@ -39,6 +39,9 @@ concurrency: group: hotfix-redirector-${{ github.event.pull_request.number }} cancel-in-progress: true +permissions: + contents: read + jobs: redirect: permissions: @@ -49,6 +52,11 @@ jobs: # Map your repo/org secrets to the expected names. BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # GPG signing identity โ€” REQUIRED if this repo redirects Dependabot + # SECURITY PRs: that path cherry-picks a commit onto `hotfixes`, and + # an unsigned commit is silently blocked by required-signatures (no + # failing check names the cause). The commit is signed and authored as + # this real-user bot account (the GPG key's owner), not the App bot. BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} BOT_GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} diff --git a/.github/workflows/hotfixes-release.yml b/.github/workflows/hotfixes-release.yml index b3b36d8..f6dc03b 100644 --- a/.github/workflows/hotfixes-release.yml +++ b/.github/workflows/hotfixes-release.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/hotfixes-release.yml +# @Project: gitmulti +# @Filename: /.github/workflows/hotfixes-release.yml # @Date: 2026-05-22 00:00:00 -07:00 (1779778800) # @Author: Nate Corcoran # @Email: @@ -31,6 +31,9 @@ concurrency: group: hotfixes-release-${{ github.repository }} cancel-in-progress: false +permissions: + contents: read + jobs: release: permissions: @@ -44,6 +47,12 @@ jobs: # Map your repo/org secrets to the expected names. BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Optional: only needed if you also use reusable-lint-format.yml / + # reusable-coverage-badge.yml (or otherwise sign a commit locally as + # this identity). Passed through so the release-PR changelog + # recognizes that identity as a bot instead of listing it as a + # contributor โ€” see CLDMV_BOT_NAME/CLDMV_BOT_EMAIL in your other + # workflows for the same values. BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} # Optional release-PR notifier webhooks โ€” each is independently diff --git a/.github/workflows/master-commit-audit.yml b/.github/workflows/master-commit-audit.yml index 07b8d08..8c23c8d 100644 --- a/.github/workflows/master-commit-audit.yml +++ b/.github/workflows/master-commit-audit.yml @@ -10,14 +10,16 @@ # Individual repo: .github/workflows/master-commit-audit.yml # # Post-merge safety net: when any commit lands on the default branch, verify -# its subject matches the expected release-flow patterns. On miss, auto-file -# a GitHub Issue (deduped by SHA) so the alert is persistent and assignable -# โ€” not just a red โŒ that dies in inbox. +# its subject matches the expected release-flow patterns. On miss, auto-file a +# GitHub Issue (deduped by SHA) so the alert is persistent and assignable โ€” +# not just a red โŒ that dies in inbox. # # Catches: release-workflow title-generation regressions, branch-protection # bypasses, unexpected bot commits, direct emergency pushes. # -# Batch 5.1 from tmp/plan-future-workflows.md. +# Thin caller: steps, the action ref, and the canonical commit-subject pattern +# set all live in reusable-master-commit-audit.yml@v4 (the patterns come from +# the audit-commit-subject action's default). Nothing here can drift. name: ๐Ÿงพ Master Commit Audit on: @@ -30,37 +32,21 @@ permissions: jobs: audit: - runs-on: ubuntu-latest - steps: - # Optional. Without these, the audit issue is filed by - # github-actions[bot]. With them, the issue is filed by your bot App. - - name: Create App token (falls back to GITHUB_TOKEN) - id: app-token - uses: CLDMV/.github/.github/actions/github/steps/create-app-token@v4 - with: - client_id: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - private_key: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - env: - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - - - name: Audit commit subject - uses: CLDMV/.github/.github/actions/git/jobs/audit-commit-subject@v4 - with: - commit_sha: ${{ github.sha }} - # allowed_patterns omitted -> inherit the canonical default from - # audit-commit-subject (release/chore/merge patterns, including - # the "release: vX.Y.Z - " form). Customize only if - # this repo's conventions genuinely differ โ€” a hardcoded copy - # here goes stale the next time the canonical default changes. - # allowed_patterns: | - # ^release: v\d+\.\d+\.\d+( - .+?)?( \(#\d+\))?$ - # ^chore(\([^)]+\))?: .+ - # ^Merge pull request #\d+ from .+ - # ^feat(\([^)]+\))?: .+ - # Canonical label names from CLDMV/.github's data/github-labels.json - # (note the space after each colon). Replace with names that exist - # in your repo's label catalog. - issue_labels: "type: ci,priority: high" - # issue_assignee: "shinrai" # uncomment to auto-assign - github_token: ${{ steps.app-token.outputs.token }} + uses: CLDMV/.github/.github/workflows/reusable-master-commit-audit.yml@v4 + with: + # allowed_patterns omitted โ†’ inherit the canonical default + # (release + chore + merge). Uncomment ONLY if this repo lands other + # commit shapes directly on the default branch: + # allowed_patterns: | + # ^release: v\d+\.\d+\.\d+( - .+?)?( \(#\d+\))?$ + # ^chore(\([^)]+\))?: .+ + # ^Merge pull request #\d+ from .+ + # ^feat(\([^)]+\))?: .+ + issue_labels: "type: ci,priority: high" + # issue_assignee: "shinrai" # uncomment to auto-assign + # Optional bot App credentials โ€” when set, the audit issue is filed by + # the consumer's bot App instead of github-actions[bot]. Remove both + # lines to fall back to GITHUB_TOKEN. + secrets: + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/member-auto-merge.yml b/.github/workflows/member-auto-merge.yml new file mode 100644 index 0000000..82cfc60 --- /dev/null +++ b/.github/workflows/member-auto-merge.yml @@ -0,0 +1,71 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/member-auto-merge.yml +# @Date: 2026-05-28 00:00:00 -07:00 (1780210800) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# Individual repo: .github/workflows/member-auto-merge.yml +# +# Auto-enables GitHub's "auto-merge" flag on PRs opened by org members +# against `next` or `hotfixes`, scoped to the standard branch-prefix +# conventions (feat/, fix/, hotfix/, chore/, โ€ฆ). Removes the per-PR +# friction of clicking "Enable auto-merge" โ€” the merge still waits for +# the ruleset's prerequisites (required approvals + CI green). +# +# This does NOT approve the PR. The human-review gate stays intact โ€” +# unlike `dependabot-auto-merge.yml` which bot-approves Dependabot bumps. +# +# Default in v4: ON. To opt out, delete this file โ€” member PRs still +# require a manual "Enable auto-merge" click but otherwise work normally. +# +# Required setup (one-time per repo, both done by `v4-bootstrap.yml`): +# 1. Settings โ†’ Pull Requests โ†’ "Allow auto-merge" โ†’ ON +# 2. A ruleset on next/hotfixes with required status checks AND a +# required-approving-review count โ‰ฅ 1 (the default v4 rulesets do +# both). The action refuses to enable auto-merge on a branch +# without required checks; the ruleset's approval requirement is +# what keeps a human in the loop after auto-merge is enabled. +name: ๐Ÿš€ Member Auto-Enable Auto-Merge + +on: + pull_request_target: + types: [opened, reopened, synchronize, ready_for_review] + +permissions: + contents: read + pull-requests: write + +# Collapse a burst of pushes to one run per PR; the latest state always wins. +concurrency: + group: member-auto-merge-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + enable: + # Pre-filter at workflow level so this doesn't spin up for every PR. + # The action repeats these checks for defense in depth (and clearer + # skip-reason logging), so trimming this `if` is fine; widening it + # is fine too โ€” the action will skip anything that doesn't match. + if: | + github.event.pull_request.draft == false && + ( + github.event.pull_request.author_association == 'MEMBER' || + github.event.pull_request.author_association == 'OWNER' || + github.event.pull_request.author_association == 'COLLABORATOR' + ) && + ( + github.event.pull_request.base.ref == 'next' || + github.event.pull_request.base.ref == 'hotfixes' + ) + uses: CLDMV/.github/.github/workflows/reusable-member-auto-merge.yml@v4 + with: + merge_method: "MERGE" + # CUSTOMIZE: tighten or widen as your repo requires. + # allowed_associations: "MEMBER,OWNER,COLLABORATOR" + # branch_prefixes: "feat,feature,fix,hotfix,chore,refactor,docs,ci,perf,test,style" + secrets: + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/next-release.yml b/.github/workflows/next-release.yml index ba7aa3d..67b54b4 100644 --- a/.github/workflows/next-release.yml +++ b/.github/workflows/next-release.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/next-release.yml +# @Project: gitmulti +# @Filename: /.github/workflows/next-release.yml # @Date: 2026-05-22 00:00:00 -07:00 (1779778800) # @Author: Nate Corcoran # @Email: @@ -37,6 +37,9 @@ concurrency: group: next-release-${{ github.repository }} cancel-in-progress: false +permissions: + contents: read + jobs: release: permissions: @@ -50,6 +53,12 @@ jobs: # Map your repo/org secrets to the expected names. BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + # Optional: only needed if you also use reusable-lint-format.yml / + # reusable-coverage-badge.yml (or otherwise sign a commit locally as + # this identity). Passed through so the release-PR changelog + # recognizes that identity as a bot instead of listing it as a + # contributor โ€” see CLDMV_BOT_NAME/CLDMV_BOT_EMAIL in your other + # workflows for the same values. BOT_NAME: ${{ secrets.CLDMV_BOT_NAME }} BOT_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} # Optional release-PR notifier webhooks โ€” each is independently diff --git a/.github/workflows/next-reset.yml b/.github/workflows/next-reset.yml index 87ba088..f98a57d 100644 --- a/.github/workflows/next-reset.yml +++ b/.github/workflows/next-reset.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/next-reset.yml +# @Project: gitmulti +# @Filename: /.github/workflows/next-reset.yml # @Date: 2026-05-22 00:00:00 -07:00 (1779778800) # @Author: Nate Corcoran # @Email: @@ -32,6 +32,9 @@ concurrency: group: next-reset-${{ github.repository }} cancel-in-progress: false +permissions: + contents: read + jobs: sync: permissions: diff --git a/.github/workflows/pr-notify.yml b/.github/workflows/pr-notify.yml new file mode 100644 index 0000000..11d31e3 --- /dev/null +++ b/.github/workflows/pr-notify.yml @@ -0,0 +1,40 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/pr-notify.yml +# @Date: 2026-05-26 00:00:00 -07:00 (1780124400) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# Individual repo: .github/workflows/pr-notify.yml +# +# Fires once per PR open. Targets ALL PRs in the repo (including the release +# PRs opened by the release-flow workflows) โ€” exactly one notification per +# PR-open event. +# +# Channels are addressed by secret name; no config file. Set the secret to +# enable the channel, leave it unset to skip: +# +# DISCORD_PR_PUBLIC_WEBHOOK / DISCORD_PR_PRIVATE_WEBHOOK +# SLACK_PR_PUBLIC_WEBHOOK / SLACK_PR_PRIVATE_WEBHOOK +# GENERIC_PR_PUBLIC_WEBHOOK / GENERIC_PR_PRIVATE_WEBHOOK +# +# Visibility is determined automatically from the repo: GitHub `public` โ†’ +# PUBLIC, `private` or `internal` โ†’ PRIVATE. Set the org-level secret in +# CLDMV for the default URL; set a repo-level secret with the same name to +# override (or to an empty string to mute that channel for this repo). +name: ๐Ÿ“ฅ PR Notify + +on: + pull_request: + types: [opened] + +permissions: + contents: read + pull-requests: read + +jobs: + notify: + uses: CLDMV/.github/.github/workflows/reusable-pr-notifier.yml@v4 + secrets: inherit diff --git a/.github/workflows/pr-title-normalizer.yml b/.github/workflows/pr-title-normalizer.yml index adba973..319221e 100644 --- a/.github/workflows/pr-title-normalizer.yml +++ b/.github/workflows/pr-title-normalizer.yml @@ -1,6 +1,6 @@ # -# @Project: @cldmv/.github -# @Filename: /examples/individual-repo-workflows/release-flow-v4/pr-title-normalizer.yml +# @Project: gitmulti +# @Filename: /.github/workflows/pr-title-normalizer.yml # @Date: 2026-05-22 00:00:00 -07:00 (1779778800) # @Author: Nate Corcoran # @Email: @@ -33,6 +33,9 @@ concurrency: group: pr-title-normalizer-${{ github.event.pull_request.number }} cancel-in-progress: true +permissions: + contents: read + jobs: normalize: permissions: diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml new file mode 100644 index 0000000..8a90222 --- /dev/null +++ b/.github/workflows/provenance.yml @@ -0,0 +1,47 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/provenance.yml +# @Date: 2026-09-05 00:00:00 -07:00 (1788591600) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# SLSA build provenance (.intoto.jsonl) for this repo's published releases. +# Decoupled from the publish workflow on purpose (see reusable-provenance.yml): +# the SLSA generator is a reusable-workflow call and cannot carry +# `continue-on-error`, so running it here โ€” on its own `release: published` +# trigger โ€” keeps a provenance failure from ever turning a release run red +# (issue #268). It re-packs the SAME build artifact the publish run uploaded, so +# the signed subjects are byte-identical to what was published. +# +# Prereq: the org's allowed actions/reusable-workflows policy must permit +# slsa-framework/*. +name: ๐Ÿ” SLSA Provenance + +on: + release: + types: [published] + +jobs: + provenance: + # Public, real releases only โ€” SLSA provenance is recorded in the public + # Rekor transparency log. Skip drafts, prereleases, and private repos. + if: | + !github.event.repository.private && + !github.event.release.draft && + !github.event.release.prerelease + permissions: + actions: read # look up the publish run's build artifact + id-token: write # provenance signing (OIDC) + contents: write # upload the .intoto.jsonl release asset + uses: CLDMV/.github/.github/workflows/reusable-provenance.yml@v4 + with: + tag: ${{ github.event.release.tag_name }} + # CUSTOMIZE: these MUST match your publish.yml so the re-packed + # tarballs are byte-identical to what was published. + package_name: "gitmulti" + node_version: "lts/*" + # Satellite packages (same value as publish.yml's extra_packages); + # empty disables. See docs/conventions/satellite-packages.md. + extra_packages: "" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9acb04c..44e1bde 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,115 +11,132 @@ name: ๐Ÿ“ฆ Release and Publish on: - push: - branches: [master, main] - paths-ignore: - - "**.md" - - ".github/ISSUE_TEMPLATE/**" - - ".github/PULL_REQUEST_TEMPLATE/**" - workflow_dispatch: - inputs: - debug: - description: "Enable debug logging for troubleshooting" - type: boolean - required: false - default: false - dry_run: - description: "Dry run mode - validate everything but don't publish or create releases" - type: boolean - required: false - default: false - node_version: - description: "Node.js version to use (default: lts/*)" - type: string - required: false - default: "lts/*" - package_manager: - description: "Package manager (npm or yarn)" - type: string - required: false - default: "npm" - test_environment: - description: "Environment for tests (affects NODE_ENV and NODE_OPTIONS --conditions flag)" - type: string - required: false - default: "development" - version: - description: "Version to publish (auto-detected from package.json if not provided)" - type: string - required: false - default: "" - publish_to_npm: - description: "Publish to NPM registry" - type: boolean - required: false - default: true - publish_to_github_packages: - description: "Publish to GitHub Packages registry" - type: boolean - required: false - default: true - min_node_version: - description: "Minimum Node.js version for matrix testing (default: 22.12.0 โ€” the floor vitest 5 actually runs on)" - type: string - required: false - default: "22.12.0" - max_node_major: - description: "Override max Node.js major version (default: 26)" - type: string - required: false - default: "26" - use_gpg: - description: "Enable GPG signing (if GPG secrets provided)" - type: boolean - required: false - default: false + push: + branches: [master, main] + paths-ignore: + - "**.md" + - ".github/ISSUE_TEMPLATE/**" + - ".github/PULL_REQUEST_TEMPLATE/**" + workflow_dispatch: + inputs: + debug: + description: "Enable debug logging for troubleshooting" + type: boolean + required: false + default: false + dry_run: + description: "Dry run mode - validate everything but don't publish or create releases" + type: boolean + required: false + default: false + node_version: + description: "Node.js version to use (default: lts/*)" + type: string + required: false + default: "lts/*" + package_manager: + description: "Package manager (npm or yarn)" + type: string + required: false + default: "npm" + test_environment: + description: "Environment for tests (affects NODE_ENV and NODE_OPTIONS --conditions flag)" + type: string + required: false + default: "development" + version: + description: "Version to publish (auto-detected from package.json if not provided)" + type: string + required: false + default: "" + publish_to_npm: + description: "Publish to NPM registry" + type: boolean + required: false + default: true + publish_to_github_packages: + description: "Publish to GitHub Packages registry" + type: boolean + required: false + default: true + min_node_version: + description: "Minimum Node.js version for matrix testing (enables matrix when set; default: 22.12.0 โ€” the floor vitest 5 actually runs on)" + type: string + required: false + default: "22.12.0" + max_node_major: + description: "Max Node.js major version for the test matrix. Leave blank (the default) to inherit the CLDMV/.github reusable workflow's default; set a value only to pin/override for a specific run." + type: string + required: false + default: "" + use_gpg: + description: "Enable GPG signing (if GPG secrets provided)" + type: boolean + required: false + default: false # NEVER cancel an in-flight publish โ€” half-published versions are nasty to # clean up. Concurrent publishes for the same ref queue instead so they # serialize naturally. concurrency: - group: publish-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false + group: publish-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: read jobs: - publish-package: - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - permissions: - contents: write - packages: write - id-token: write - uses: CLDMV/.github/.github/workflows/workflow-publish.yml@v4 - with: - package_name: "gitmulti" # Required: replace with your NPM package name - debug: ${{ github.event.inputs.debug == 'true' }} - dry_run: ${{ github.event.inputs.dry_run == 'true' }} - node_version: ${{ github.event.inputs.node_version || 'lts/*' }} - package_manager: ${{ github.event.inputs.package_manager || 'npm' }} - version: ${{ github.event.inputs.version || '' }} - publish_to_npm: false - publish_to_github_packages: false - publish_command: "" - github_packages_publish_command: "" - min_node_version: ${{ github.event.inputs.min_node_version || '22.12.0' }} - max_node_major: ${{ github.event.inputs.max_node_major || '26' }} - test_command: "npm test" # Use defaults: NODE_ENV=development, NODE_OPTIONS=--conditions=development - # test_command: "NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override NODE_OPTIONS only - # test_command: "NODE_ENV=test npm test" # Override NODE_ENV only - # test_command: "NODE_ENV=test NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override both - test_environment: ${{ github.event.inputs.test_environment || 'development' }} # Alternative to setting in test_command - build_command: "npm run build:ci" - is_prerelease: false - release_source_only: true - create_documentation: true - skip_performance_tests: false - skip_matrix_tests: false - use_gpg: ${{ github.event.inputs.use_gpg == 'true' }} - secrets: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} - TAGGER_NAME: ${{ secrets.CLDMV_BOT_NAME }} - TAGGER_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} - GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} - GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} + publish-package: + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + permissions: + contents: write + packages: write + id-token: write + uses: CLDMV/.github/.github/workflows/workflow-publish.yml@v4 + with: + package_name: "gitmulti" # Required: replace with your NPM package name + debug: ${{ github.event.inputs.debug == 'true' }} + dry_run: ${{ github.event.inputs.dry_run == 'true' }} + node_version: ${{ github.event.inputs.node_version || 'lts/*' }} + package_manager: ${{ github.event.inputs.package_manager || 'npm' }} + version: ${{ github.event.inputs.version || '' }} + publish_to_npm: false + publish_to_github_packages: false + publish_command: "" + github_packages_publish_command: "" + min_node_version: ${{ github.event.inputs.min_node_version || '22.12.0' }} + max_node_major: ${{ github.event.inputs.max_node_major || '' }} # blank โ‡’ inherit the CLDMV/.github reusable default + test_command: "npm test" # Use defaults: NODE_ENV=development, NODE_OPTIONS=--conditions=development + # test_command: "NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override NODE_OPTIONS only + # test_command: "NODE_ENV=test npm test" # Override NODE_ENV only + # test_command: "NODE_ENV=test NODE_OPTIONS='--conditions=slothlet-dev' npm test" # Override both + test_environment: ${{ github.event.inputs.test_environment || 'development' }} # Alternative to setting in test_command + build_command: "npm run build:ci" + # --- Satellite packages (optional) ---------------------------------------- + # Publish extra packages carved from this build's output (e.g. locale JSON, + # generated types) at the SAME version/commit as the core, each with its own + # @scope/name@version tag + GitHub Release. Uncomment to opt in. + # extra_packages: a JSON [{ name, dir }] array, OR a glob (single '*' in the + # final path segment, e.g. "dist-packages/*"). Empty = disabled. + # build_subpackages_command: runs after build_command to produce + # dist-packages// โ€” omit if build_command already does the carve. + # First publish of each new @scope/name needs a one-time token publish + + # trusted-publisher setup. Full details + the contract: + # docs/conventions/satellite-packages.md + # extra_packages: "dist-packages/*" + # build_subpackages_command: "npm run build:subpackages" + # -------------------------------------------------------------------------- + is_prerelease: false + release_source_only: true + create_documentation: true + skip_performance_tests: false + skip_matrix_tests: false + use_gpg: ${{ github.event.inputs.use_gpg == 'true' }} + secrets: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + TAGGER_NAME: ${{ secrets.CLDMV_BOT_NAME }} + TAGGER_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} + GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml new file mode 100644 index 0000000..086a454 --- /dev/null +++ b/.github/workflows/release-merge.yml @@ -0,0 +1,96 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/release-merge.yml +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# Individual repo: .github/workflows/release-merge.yml +# +# v4 core (optional): squash-merge the persistent `next โ†’ master` release PR on +# YOUR APPROVAL, via the REST merge API with the PR body as the commit message. +# +# Why not just click "Squash and merge"? The mobile Default path can land a +# title-only commit (dropping the curated changelog + coverage), and the web/ +# mobile squash UI auto-appends its own `Co-authored-by:` list (not deduped, not +# bot-stripped). An explicit-message API merge avoids both โ€” the release commit +# is exactly the curated PR body. It also merges only once EVERY check (required +# AND non-required, e.g. the coverage badge and the release-PR body refresh) has +# finished and passed, so the body it captures is never stale. +# +# How you use it: approve the release PR as you normally do. The merge fires when +# CI is green โ€” if you approve before CI finishes, it re-evaluates once CI +# actually finishes and merges once the last check passes. Nothing auto-merges +# without your approval. +# +# Re-evaluation uses `workflow_run`, not `check_suite` โ€” GitHub does not send +# `check_suite: completed` for a suite created by GitHub Actions itself, which +# is every check your own ci.yml produces; it only fires for a suite created +# by a third-party App. See CLDMV/.github#318: an approval given before CI +# finished left a release PR stuck fully green with nothing re-firing the +# merge check, because check_suite silently never fired for that case at all. +# `workflow_run` is GitHub's documented replacement for exactly this pattern. +# +# IMPORTANT: the merge gate waits on EVERY check-run on the release PR's head +# commit, from any workflow โ€” so `workflows:` below must name every workflow in +# your repo that puts a check on that commit, not just ci.yml. Only the one that +# finishes LAST can see a fully green head; if it isn't listed, nothing re-fires +# and the PR sits approved + green until you dispatch this workflow by hand. +# CodeQL in particular routinely outlasts ci.yml (CLDMV/.github PR #322 stuck +# exactly this way). The list below covers the standard v4 template set by their +# template `name:`s โ€” names are matched literally (not by filename), so fix any +# you renamed, and add any extra PR-triggered workflow your repo has. Listing a +# workflow your repo doesn't have is harmless. `branches:` limits re-fires to +# runs on the integration branches, so feature-branch CI doesn't wake this up. +# +# Thin caller: all logic lives in the reusable, pinned at @v4. +# NOTE: pull_request_review / workflow_run events run the copy of this file on +# the DEFAULT branch, so it takes effect once it ships to master with a release. +name: ๐Ÿšฆ Release Merge (v4) + +on: + pull_request_review: + types: [submitted] # your approval arms it + workflow_run: # re-evaluate as each check-producing workflow finishes โ€” see #318 + workflows: # โ† must match your workflows' `name:`s โ€” see IMPORTANT above + - "๐Ÿงช CI Tests & Build" + - "๐Ÿ” CodeQL" + - "๐Ÿ”’ Dependency Review" + - "๐Ÿš€ Next Release (v4)" + - "๐Ÿš‘ Hotfixes Release (v4)" + - "๐ŸŒฟ Branch Retention" + - "๐Ÿท๏ธ PR Labeler" + - "๐Ÿท๏ธ PR Title Normalizer" + - "๐Ÿ‘‹ Welcome Contributor" + - "๐Ÿ”€ Hotfix PR Redirector (v4)" + - "๐Ÿš€ Member Auto-Enable Auto-Merge" + - "๐Ÿค– Dependabot Auto-Merge" + - "๐Ÿ” Dependabot Auto-Recreate" + - "๐Ÿ“œ CLA" + - "๐Ÿ“ฅ PR Notify" + types: [completed] + branches: [next, hotfixes] + workflow_dispatch: # manual re-evaluation + +# Serialize per repo: each run re-resolves the release PR + re-gates the head, +# so queue (don't cancel) to avoid racing a merge that's already in flight. +# GitHub keeps one pending run per group and a newer arrival replaces it โ€” that +# is harmless, since every run re-reads approval + check state from the API. +concurrency: + group: release-merge-${{ github.repository }} + cancel-in-progress: false + +permissions: + contents: read + +jobs: + merge: + permissions: + contents: write + pull-requests: write + checks: read + statuses: read + uses: CLDMV/.github/.github/workflows/workflow-release-merge.yml@v4 + secrets: + # Map your repo/org secrets to the expected names. + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f3b6df5..6637c04 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -14,11 +14,6 @@ # scorecard-action version live in reusable-scorecard.yml@v4, so the action # version can't drift in this copy (it just calls the org reusable). Triggers # stay here, per OpenSSF's recommended setup. -# -# NOTE: this MUST stay a thin caller. OSSF Scorecard's publish step verifies -# the analysis job and allows only a fixed set of steps; the inline form used -# our checkout-code composite, which trips "job has unallowed step" -> publish -# HTTP 400. The reusable uses actions/checkout directly, which passes. name: ๐Ÿ”ฌ OpenSSF Scorecard on: @@ -32,8 +27,8 @@ on: # Caller must grant what the reusable needs โ€” notably id-token: write for the # OpenSSF transparency-log publish. # -# No workflow-level `permissions:` here โ€” grant on the `analyze` job below -# instead. scorecard-action's publish step verifies that write permissions +# Keep the workflow-level grant READ-ONLY (contents: read) and grant every +# WRITE on the `analyze` job instead. scorecard-action's publish step verifies that write permissions # were granted JOB-scoped, not workflow-wide (matching OSSF's own example: # https://github.com/ossf/scorecard-action#example-workflow). A workflow-level # grant satisfies GitHub's own reusable-workflow permission rules fine, but @@ -47,9 +42,13 @@ on: # tampered with results before they hit the public transparency log). That # trade-off means the reusable's own SARIF-to-Security-tab upload step has no # permission to run in this configuration; the public OpenSSF badge is the -# thing actually enabled here, so this repo takes that trade-off. Only add -# security-events: write back (job-scoped) if publish_results is set to false -# instead. +# thing this default enables, so consumers take that trade-off by default. +# Only add security-events: write back (job-scoped) if publish_results is set +# to false instead (SARIF-to-Security-tab upload, no public badge). + +permissions: + contents: read + jobs: analyze: permissions: @@ -58,4 +57,4 @@ jobs: actions: read uses: CLDMV/.github/.github/workflows/reusable-scorecard.yml@v4 with: - publish_results: true # set false for private repos / to skip the public badge + publish_results: true # set false to skip the public badge in favor of SARIF-to-Security-tab. Private repos need not bother: every scorecard job auto-skips there (OpenSSF cannot publish private repos, so the run would only burn paid minutes). diff --git a/.github/workflows/tag-health.yml b/.github/workflows/tag-health.yml index 2a9838a..4ec0df7 100644 --- a/.github/workflows/tag-health.yml +++ b/.github/workflows/tag-health.yml @@ -42,10 +42,12 @@ on: default: true permissions: - contents: write + contents: read jobs: health: + permissions: + contents: write uses: CLDMV/.github/.github/workflows/reusable-tag-health.yml@v4 with: debug: ${{ github.event.inputs.debug == 'true' }} diff --git a/.github/workflows/update-major-version-tags.yml b/.github/workflows/update-major-version-tags.yml index ad07deb..f20b129 100644 --- a/.github/workflows/update-major-version-tags.yml +++ b/.github/workflows/update-major-version-tags.yml @@ -11,77 +11,80 @@ name: ๐Ÿท๏ธ Update Major Version Tags on: - release: - types: [published] - workflow_dispatch: - inputs: - debug: - description: "Enable debug logging for troubleshooting" - type: boolean - required: false - default: false - create_documentation: - description: "Whether to create/update VERSION_TAGS.md documentation" - type: boolean - required: false - default: false - use_gpg: - description: "Enable GPG signing (if GPG secrets provided)" - type: boolean - required: false - default: true - # Tag health configuration - max_tags: - description: "Maximum number of tags to process (safety limit)" - required: false - default: "100" - max_major_versions: - description: "Maximum number of major versions to process" - required: false - default: "10" - max_minor_versions: - description: "Maximum number of minor versions per major to process" - required: false - default: "10" - bot_patterns: - description: "JSON array of bot name patterns to identify bot signatures" - required: false - default: '["CLDMV Bot", "cldmv-bot", "github-actions[bot]"]' - include_patterns: - description: "JSON array of tag patterns to include (e.g. ['v*', 'release-*'])" - required: false - default: '["v*"]' - exclude_patterns: - description: "JSON array of tag patterns to exclude" - required: false - default: "[]" + release: + types: [published] + workflow_dispatch: + inputs: + debug: + description: "Enable debug logging for troubleshooting" + type: boolean + required: false + default: false + create_documentation: + description: "Whether to create/update VERSION_TAGS.md documentation" + type: boolean + required: false + default: false + use_gpg: + description: "Enable GPG signing (if GPG secrets provided)" + type: boolean + required: false + default: true + # Tag health configuration + max_tags: + description: "Maximum number of tags to process (safety limit)" + required: false + default: "100" + max_major_versions: + description: "Maximum number of major versions to process" + required: false + default: "10" + max_minor_versions: + description: "Maximum number of minor versions per major to process" + required: false + default: "10" + bot_patterns: + description: "JSON array of bot name patterns to identify bot signatures" + required: false + default: '["CLDMV Bot", "cldmv-bot", "github-actions[bot]"]' + include_patterns: + description: "JSON array of tag patterns to include (e.g. ['v*', 'release-*'])" + required: false + default: '["v*"]' + exclude_patterns: + description: "JSON array of tag patterns to exclude" + required: false + default: "[]" + +permissions: + contents: read jobs: - update-tags: - # Skip release events fired without a tag_name (e.g. "untagged-" runs - # the bot or a prior code path can produce). The reusable workflow has its - # own tag-readiness polling for forward-facing prevention; this guard - # protects against legacy / external sources of untagged release events. - # Batch 1.2 from tmp/plan-future-workflows.md. - if: github.event_name != 'release' || github.event.release.tag_name != '' - uses: CLDMV/.github/.github/workflows/workflow-update-major-version-tags.yml@v4 - permissions: - contents: write - with: - debug: ${{ github.event.inputs.debug == 'true' }} - create_documentation: ${{ github.event.inputs.create_documentation == 'true' }} - use_gpg: ${{ github.event.inputs.use_gpg != 'false' }} - max_tags: ${{ github.event.inputs.max_tags || '100' }} - max_major_versions: ${{ github.event.inputs.max_major_versions || '10' }} - max_minor_versions: ${{ github.event.inputs.max_minor_versions || '10' }} - bot_patterns: ${{ github.event.inputs.bot_patterns || '["CLDMV Bot", "cldmv-bot", "github-actions[bot]"]' }} - include_patterns: ${{ github.event.inputs.include_patterns || '["v*"]' }} - exclude_patterns: ${{ github.event.inputs.exclude_patterns || '[]' }} - secrets: - # Map your repo/org secrets to the expected names - TAGGER_NAME: ${{ secrets.CLDMV_BOT_NAME }} - TAGGER_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} - GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} - GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} - BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} - BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} + update-tags: + # Skip release events fired without a tag_name (e.g. "untagged-" runs + # the bot or a prior code path can produce). The reusable workflow has its + # own tag-readiness polling for forward-facing prevention; this guard + # protects against legacy / external sources of untagged release events. + # Batch 1.2 from tmp/plan-future-workflows.md. + if: github.event_name != 'release' || github.event.release.tag_name != '' + uses: CLDMV/.github/.github/workflows/workflow-update-major-version-tags.yml@v4 + permissions: + contents: write + with: + debug: ${{ github.event.inputs.debug == 'true' }} + create_documentation: ${{ github.event.inputs.create_documentation == 'true' }} + use_gpg: ${{ github.event.inputs.use_gpg != 'false' }} + max_tags: ${{ github.event.inputs.max_tags || '100' }} + max_major_versions: ${{ github.event.inputs.max_major_versions || '10' }} + max_minor_versions: ${{ github.event.inputs.max_minor_versions || '10' }} + bot_patterns: ${{ github.event.inputs.bot_patterns || '["CLDMV Bot", "cldmv-bot", "github-actions[bot]"]' }} + include_patterns: ${{ github.event.inputs.include_patterns || '["v*"]' }} + exclude_patterns: ${{ github.event.inputs.exclude_patterns || '[]' }} + secrets: + # Map your repo/org secrets to the expected names + TAGGER_NAME: ${{ secrets.CLDMV_BOT_NAME }} + TAGGER_EMAIL: ${{ secrets.CLDMV_BOT_EMAIL }} + GPG_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.CLDMV_BOT_GPG_PASSPHRASE }} + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/v4-bootstrap.yml b/.github/workflows/v4-bootstrap.yml index 5322a9f..7666737 100644 --- a/.github/workflows/v4-bootstrap.yml +++ b/.github/workflows/v4-bootstrap.yml @@ -72,7 +72,11 @@ on: steps: description: "Subset of phases to run, comma-separated." required: false - default: "branches,settings,security,rulesets" + default: "branches,settings,security,rulesets,variables" + code_scanning_config: + description: "Override for the variables-phase GHAS config (scan/skip lists): inline JSON or a workspace path. Empty = the data/code-scanning-skips.json bundled in CLDMV/.github โ€” third-party orgs supply their own here." + required: false + default: "" permissions: contents: read @@ -104,3 +108,4 @@ jobs: steps: ${{ github.event.inputs.steps }} code_security: ${{ github.event.inputs.code_security }} secret_protection: ${{ github.event.inputs.secret_protection }} + code_scanning_config: ${{ github.event.inputs.code_scanning_config }} From a653863e381a1775f5fb9ba55795e8b4bb54db6d Mon Sep 17 00:00:00 2001 From: "cldmv-bot[bot]" <230771808+cldmv-bot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 06:58:46 +0000 Subject: [PATCH 2/4] chore: bump version to 0.0.9 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62ee7cb..9185e45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitmulti", - "version": "0.0.8", + "version": "0.0.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitmulti", - "version": "0.0.8", + "version": "0.0.9", "license": "GPL-3.0", "dependencies": { "commander": "^2.19.0" diff --git a/package.json b/package.json index a745747..f31fc44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gitmulti", - "version": "0.0.8", + "version": "0.0.9", "description": "Simple Node system to manage multiple Repositories into the same repo", "main": "gitmulti.js", "scripts": { From 91f6f858349d9a83933dcc5b0e2108ce6554605c Mon Sep 17 00:00:00 2001 From: Shinrai Date: Mon, 28 Sep 2026 00:12:57 -0700 Subject: [PATCH 3/4] ci: add the bundle-size workflow and restore the release-merge workflow list Also drop the squash merge_method pin from dependabot-auto-merge (the next/hotfixes rulesets are merge-only) and correct the skip_type_check comment, which claimed an ESLint setup the repo does not have. --- .github/workflows/bundle-size.yml | 49 +++++++++++++++++++++ .github/workflows/ci.yml | 2 +- .github/workflows/dependabot-auto-merge.yml | 2 +- .github/workflows/release-merge.yml | 3 ++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/bundle-size.yml diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml new file mode 100644 index 0000000..3e93b2c --- /dev/null +++ b/.github/workflows/bundle-size.yml @@ -0,0 +1,49 @@ +# +# @Project: gitmulti +# @Filename: /.github/workflows/bundle-size.yml +# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) +# @Author: Nate Corcoran +# @Email: +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# + +# Individual repo: .github/workflows/bundle-size.yml +# +# Only relevant for runtime libraries where bundle size matters (e.g. +# @cldmv/slothlet). Skip this template for tool repos / meta repos. +# +# Fork-PR caveat: builds PR-supplied code, so we use `pull_request` +# (NOT pull_request_target). Fork builds run safely without secrets; +# comment posting fails for fork PRs because the token is read-only. +# Maintainer can run via workflow_dispatch after reviewing the code. +# +# Batch 5.4 from tmp/plan-future-workflows.md. +name: ๐Ÿ“Š Bundle Size + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: [master, main] + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + diff: + uses: CLDMV/.github/.github/workflows/reusable-bundle-size.yml@v4 + with: + build_command: "npm run build:ci" + # Leading `*` is required: the measure step only walks directories, so a bare top-level filename matches nothing. + dist_paths: "*gitmulti.js" + # warning_pct: 5 + # warning_bytes: 500 + # comment_mode: "update" + # Optional. Without these, the size-diff comment is posted by + # github-actions[bot]. With these, it's posted by your CLDMV bot App. + # Note: fork PRs can't access org secrets, so the bot attribution only + # applies to same-repo PRs; fork PRs fall back to GITHUB_TOKEN. + secrets: + BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} + BOT_APP_PRIVATE_KEY: ${{ secrets.CLDMV_BOT_APP_PRIVATE_KEY }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c4850c..a832932 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -267,7 +267,7 @@ jobs: # โ”€โ”€ Type check (runs inside the coverage-badge job) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # Skipped deliberately: plain JavaScript package with no TypeScript sources # or shipped type declarations, so there is no meaningful JS type-check to - # run. ESLint is the static-analysis net. + # run. There is no type check or lint check in this repo yet. type_check_command: ${{ github.event.inputs.type_check_command || 'npm run test:types' }} skip_type_check: true diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index cb24ae3..2f801b0 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -51,7 +51,7 @@ jobs: bump_types: "patch,minor" # merge_method defaults to "merge" โ€” Dependabot PRs target next / hotfixes, # whose rulesets are merge-only. Override only if your branches differ. - merge_method: "squash" + # merge_method: "merge" # also_for_actors: "renovate[bot]" # extend if you adopt Renovate secrets: BOT_APP_CLIENT_ID: ${{ secrets.CLDMV_BOT_APP_CLIENT_ID }} diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml index 086a454..fed525d 100644 --- a/.github/workflows/release-merge.yml +++ b/.github/workflows/release-merge.yml @@ -1,6 +1,8 @@ # # @Project: gitmulti # @Filename: /.github/workflows/release-merge.yml +# @Author: Nate Corcoran +# @Email: # @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # @@ -55,6 +57,7 @@ on: - "๐Ÿงช CI Tests & Build" - "๐Ÿ” CodeQL" - "๐Ÿ”’ Dependency Review" + - "๐Ÿ“Š Bundle Size" - "๐Ÿš€ Next Release (v4)" - "๐Ÿš‘ Hotfixes Release (v4)" - "๐ŸŒฟ Branch Retention" From 2b7107ee19f2667500a164265ff754c174d7c2b4 Mon Sep 17 00:00:00 2001 From: Shinrai Date: Fri, 2 Oct 2026 11:31:38 -0700 Subject: [PATCH 4/4] chore: adopt the shared CLDMV fix-headers config and stamp uniform file headers --- .configs/fix-headers.json | 3 ++ .configs/vitest.config.mjs | 15 +++++++ .github/dependabot.yml | 16 ++++--- .github/workflows/branch-retention.yml | 16 ++++--- .github/workflows/bundle-size.yml | 16 ++++--- .github/workflows/ci.yml | 16 ++++--- .github/workflows/cla.yml | 16 ++++--- .github/workflows/codeql.yml | 16 ++++--- .github/workflows/dependabot-auto-merge.yml | 16 ++++--- .github/workflows/dependabot-recreate.yml | 16 ++++--- .github/workflows/dependency-review.yml | 16 ++++--- .github/workflows/feature-pr.yml | 15 ++++--- .github/workflows/hotfix-redirector.yml | 16 ++++--- .github/workflows/hotfixes-release.yml | 16 ++++--- .github/workflows/labeler.yml | 16 ++++--- .github/workflows/master-commit-audit.yml | 16 ++++--- .github/workflows/member-auto-merge.yml | 16 ++++--- .github/workflows/next-release.yml | 16 ++++--- .github/workflows/next-reset.yml | 16 ++++--- .github/workflows/pr-notify.yml | 16 ++++--- .github/workflows/pr-title-normalizer.yml | 16 ++++--- .github/workflows/provenance.yml | 16 ++++--- .github/workflows/publish.yml | 16 ++++--- .github/workflows/release-merge.yml | 15 ++++--- .github/workflows/release-notify.yml | 16 ++++--- .github/workflows/scorecard.yml | 16 ++++--- .github/workflows/stale.yml | 16 ++++--- .github/workflows/tag-health.yml | 16 ++++--- .../workflows/update-major-version-tags.yml | 16 ++++--- .github/workflows/v4-bootstrap.yml | 16 ++++--- .github/workflows/welcome.yml | 16 ++++--- gitmulti.js | 15 +++++++ package-lock.json | 43 +++++++++++++++++++ package.json | 5 ++- tests/gitmulti.cli.test.vitest.mjs | 15 +++++++ tests/gitmulti.test.vitest.mjs | 15 +++++++ tests/run-vitest.mjs | 15 +++++++ 37 files changed, 415 insertions(+), 173 deletions(-) create mode 100644 .configs/fix-headers.json diff --git a/.configs/fix-headers.json b/.configs/fix-headers.json new file mode 100644 index 0000000..f5dd35f --- /dev/null +++ b/.configs/fix-headers.json @@ -0,0 +1,3 @@ +{ + "extends": "@cldmv/configs/fix-headers.json" +} diff --git a/.configs/vitest.config.mjs b/.configs/vitest.config.mjs index 483c5d7..e4203b5 100644 --- a/.configs/vitest.config.mjs +++ b/.configs/vitest.config.mjs @@ -1,3 +1,18 @@ +/** + * + * @Project: gitmulti + * @Filename: /.configs/vitest.config.mjs + * @Date: 2026-08-02T16:42:01-07:00 (1785714121) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-10-02T11:30:27-07:00 (1790965827) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + * + */ + import { defineConfig } from "vitest/config"; import { fileURLToPath } from "node:url"; import path from "node:path"; diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4a1aedf..fc681ac 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/dependabot.yml -# @Date: 2026-05-26 00:00:00 -07:00 (1782460800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/dependabot.yml +# @Date: 2026-05-26T00:00:00-07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:28-07:00 (1790965828) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/dependabot.yml diff --git a/.github/workflows/branch-retention.yml b/.github/workflows/branch-retention.yml index 4a73bcf..c1c05cf 100644 --- a/.github/workflows/branch-retention.yml +++ b/.github/workflows/branch-retention.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/branch-retention.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/branch-retention.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:28-07:00 (1790965828) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/branch-retention.yml diff --git a/.github/workflows/bundle-size.yml b/.github/workflows/bundle-size.yml index 3e93b2c..1411aa1 100644 --- a/.github/workflows/bundle-size.yml +++ b/.github/workflows/bundle-size.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/bundle-size.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/bundle-size.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:28-07:00 (1790965828) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/bundle-size.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a832932..2c1f8c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/ci.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/ci.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:28-07:00 (1790965828) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/ci.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 20ba5f0..9e26bfc 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/cla.yml -# @Date: 2026-07-19 00:00:00 -07:00 (1784523600) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/cla.yml +# @Date: 2026-07-19T00:00:00-07:00 (1784444400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:28-07:00 (1790965828) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/cla.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f2d1cbb..5852096 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/codeql.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/codeql.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:29-07:00 (1790965829) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/codeql.yml diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 2f801b0..d84530c 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/dependabot-auto-merge.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/dependabot-auto-merge.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:29-07:00 (1790965829) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/dependabot-auto-merge.yml diff --git a/.github/workflows/dependabot-recreate.yml b/.github/workflows/dependabot-recreate.yml index b64e3d9..931b9c9 100644 --- a/.github/workflows/dependabot-recreate.yml +++ b/.github/workflows/dependabot-recreate.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/dependabot-recreate.yml -# @Date: 2026-07-31 00:00:00 -07:00 (1785481200) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/dependabot-recreate.yml +# @Date: 2026-07-31T00:00:00-07:00 (1785481200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:29-07:00 (1790965829) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/dependabot-recreate.yml diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 671a80e..7fe6bd0 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/dependency-review.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/dependency-review.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:29-07:00 (1790965829) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/dependency-review.yml diff --git a/.github/workflows/feature-pr.yml b/.github/workflows/feature-pr.yml index 6008b0f..eda19da 100644 --- a/.github/workflows/feature-pr.yml +++ b/.github/workflows/feature-pr.yml @@ -1,9 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/feature-pr.yml -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/feature-pr.yml +# @Date: 2026-08-02T16:42:01-07:00 (1785714121) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:29-07:00 (1790965829) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/feature-pr.yml diff --git a/.github/workflows/hotfix-redirector.yml b/.github/workflows/hotfix-redirector.yml index 900ed1c..b7eb18e 100644 --- a/.github/workflows/hotfix-redirector.yml +++ b/.github/workflows/hotfix-redirector.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/hotfix-redirector.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/hotfix-redirector.yml +# @Date: 2026-05-22T00:00:00-07:00 (1779433200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/hotfix-redirector.yml diff --git a/.github/workflows/hotfixes-release.yml b/.github/workflows/hotfixes-release.yml index f6dc03b..35f9c84 100644 --- a/.github/workflows/hotfixes-release.yml +++ b/.github/workflows/hotfixes-release.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/hotfixes-release.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/hotfixes-release.yml +# @Date: 2026-05-22T00:00:00-07:00 (1779433200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/hotfixes-release.yml diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index dd6ebe8..66162c6 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/labeler.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/labeler.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/labeler.yml diff --git a/.github/workflows/master-commit-audit.yml b/.github/workflows/master-commit-audit.yml index 8c23c8d..c1b18b7 100644 --- a/.github/workflows/master-commit-audit.yml +++ b/.github/workflows/master-commit-audit.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/master-commit-audit.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/master-commit-audit.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/master-commit-audit.yml diff --git a/.github/workflows/member-auto-merge.yml b/.github/workflows/member-auto-merge.yml index 82cfc60..532f955 100644 --- a/.github/workflows/member-auto-merge.yml +++ b/.github/workflows/member-auto-merge.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/member-auto-merge.yml -# @Date: 2026-05-28 00:00:00 -07:00 (1780210800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/member-auto-merge.yml +# @Date: 2026-05-28T00:00:00-07:00 (1779951600) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/member-auto-merge.yml diff --git a/.github/workflows/next-release.yml b/.github/workflows/next-release.yml index 67b54b4..f7539b9 100644 --- a/.github/workflows/next-release.yml +++ b/.github/workflows/next-release.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/next-release.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/next-release.yml +# @Date: 2026-05-22T00:00:00-07:00 (1779433200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/next-release.yml diff --git a/.github/workflows/next-reset.yml b/.github/workflows/next-reset.yml index f98a57d..3d13f66 100644 --- a/.github/workflows/next-reset.yml +++ b/.github/workflows/next-reset.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/next-reset.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/next-reset.yml +# @Date: 2026-05-22T00:00:00-07:00 (1779433200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/next-reset.yml diff --git a/.github/workflows/pr-notify.yml b/.github/workflows/pr-notify.yml index 11d31e3..734acf2 100644 --- a/.github/workflows/pr-notify.yml +++ b/.github/workflows/pr-notify.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/pr-notify.yml -# @Date: 2026-05-26 00:00:00 -07:00 (1780124400) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/pr-notify.yml +# @Date: 2026-05-26T00:00:00-07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:30-07:00 (1790965830) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/pr-notify.yml diff --git a/.github/workflows/pr-title-normalizer.yml b/.github/workflows/pr-title-normalizer.yml index 319221e..c9fde71 100644 --- a/.github/workflows/pr-title-normalizer.yml +++ b/.github/workflows/pr-title-normalizer.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/pr-title-normalizer.yml -# @Date: 2026-05-22 00:00:00 -07:00 (1779778800) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/pr-title-normalizer.yml +# @Date: 2026-05-22T00:00:00-07:00 (1779433200) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:31-07:00 (1790965831) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/pr-title-normalizer.yml diff --git a/.github/workflows/provenance.yml b/.github/workflows/provenance.yml index 8a90222..699bffc 100644 --- a/.github/workflows/provenance.yml +++ b/.github/workflows/provenance.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/provenance.yml -# @Date: 2026-09-05 00:00:00 -07:00 (1788591600) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/provenance.yml +# @Date: 2026-09-05T00:00:00-07:00 (1788591600) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:31-07:00 (1790965831) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # SLSA build provenance (.intoto.jsonl) for this repo's published releases. diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 44e1bde..73a42bf 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/publish.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/publish.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:31-07:00 (1790965831) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/publish.yml diff --git a/.github/workflows/release-merge.yml b/.github/workflows/release-merge.yml index fed525d..a7b9468 100644 --- a/.github/workflows/release-merge.yml +++ b/.github/workflows/release-merge.yml @@ -1,9 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/release-merge.yml -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/release-merge.yml +# @Date: 2026-09-27T23:51:38-07:00 (1790578298) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:31-07:00 (1790965831) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/release-merge.yml diff --git a/.github/workflows/release-notify.yml b/.github/workflows/release-notify.yml index f18d7e3..984c9ca 100644 --- a/.github/workflows/release-notify.yml +++ b/.github/workflows/release-notify.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/release-notify.yml -# @Date: 2026-07-19 00:00:00 -07:00 (1784523600) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/release-notify.yml +# @Date: 2026-07-19T00:00:00-07:00 (1784444400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/release-notify.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6637c04..e100961 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/scorecard.yml -# @Date: 2026-07-19 00:00:00 -07:00 (1784523600) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/scorecard.yml +# @Date: 2026-07-19T00:00:00-07:00 (1784444400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/scorecard.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f75f0d6..d29a71c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/stale.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/stale.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/stale.yml diff --git a/.github/workflows/tag-health.yml b/.github/workflows/tag-health.yml index 4ec0df7..64544f5 100644 --- a/.github/workflows/tag-health.yml +++ b/.github/workflows/tag-health.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/tag-health.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/tag-health.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/tag-health.yml diff --git a/.github/workflows/update-major-version-tags.yml b/.github/workflows/update-major-version-tags.yml index f20b129..f6cc7b3 100644 --- a/.github/workflows/update-major-version-tags.yml +++ b/.github/workflows/update-major-version-tags.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/update-major-version-tags.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/update-major-version-tags.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/update-major-version-tags.yml diff --git a/.github/workflows/v4-bootstrap.yml b/.github/workflows/v4-bootstrap.yml index 7666737..e310638 100644 --- a/.github/workflows/v4-bootstrap.yml +++ b/.github/workflows/v4-bootstrap.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/v4-bootstrap.yml -# @Date: 2026-05-26 00:00:00 -07:00 (1780124400) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/v4-bootstrap.yml +# @Date: 2026-05-26T00:00:00-07:00 (1779778800) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/v4-bootstrap.yml diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml index 5df0fe3..862a549 100644 --- a/.github/workflows/welcome.yml +++ b/.github/workflows/welcome.yml @@ -1,10 +1,14 @@ # -# @Project: gitmulti -# @Filename: /.github/workflows/welcome.yml -# @Date: 2026-05-20 00:00:00 -07:00 (1779606000) -# @Author: Nate Corcoran -# @Email: -# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. +# @Project: gitmulti +# @Filename: /.github/workflows/welcome.yml +# @Date: 2026-05-20T00:00:00-07:00 (1779260400) +# @Author: Nate Corcoran +# @Email: +# ----- +# @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) +# @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) +# ----- +# @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. # # Individual repo: .github/workflows/welcome.yml diff --git a/gitmulti.js b/gitmulti.js index e98e562..b74f333 100644 --- a/gitmulti.js +++ b/gitmulti.js @@ -1,3 +1,18 @@ +/** + * + * @Project: gitmulti + * @Filename: /gitmulti.js + * @Date: 2019-01-09T05:21:21-08:00 (1547040081) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + * + */ + "use strict" const program = require('commander'); diff --git a/package-lock.json b/package-lock.json index 9185e45..8561463 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "commander": "^2.19.0" }, "devDependencies": { + "@cldmv/configs": "^1.2.0", + "@cldmv/fix-headers": "^2.1.1", "@cldmv/vitest-runner": "^1.2.0", "@vitest/coverage-v8": "^5.0.0", "vitest": "^5.0.1" @@ -77,6 +79,37 @@ "node": ">=18" } }, + "node_modules/@cldmv/configs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@cldmv/configs/-/configs-1.2.0.tgz", + "integrity": "sha512-FDmlxOx6ceKuD5zTamUy9XOfAC4opeOaLxWqZz9okKxj8TsTZP6dN7W0VccRYRdw4606NvXjhdZqOPibcNpXmQ==", + "dev": true, + "license": "Apache-2.0", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/shinrai" + } + }, + "node_modules/@cldmv/fix-headers": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cldmv/fix-headers/-/fix-headers-2.1.1.tgz", + "integrity": "sha512-08xW44RvtrKUCTOjUFKHyrDvx6rT70zGqgRR+tdW0R9ElZrHwSg25xCRrZD+U7Dmj5fK9KmtuOWPjZtJYSfzYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ignore": "^7.0.5" + }, + "bin": { + "fix-headers": "bin/fix-headers.mjs" + }, + "engines": { + "node": ">=22.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/shinrai" + } + }, "node_modules/@cldmv/vitest-runner": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@cldmv/vitest-runner/-/vitest-runner-1.2.0.tgz", @@ -668,6 +701,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/ignore": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", + "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/js-tokens": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", diff --git a/package.json b/package.json index f31fc44..83101be 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "build:ci": "echo 'โœ“ no build step'", "test:watch": "vitest --config .configs/vitest.config.mjs", "coverage": "node tests/run-vitest.mjs --coverage-quiet", - "ci:coverage": "npm run coverage" + "ci:coverage": "npm run coverage", + "fix:headers": "fix-headers --config .configs/fix-headers.json" }, "repository": { "type": "git", @@ -32,6 +33,8 @@ "commander": "^2.19.0" }, "devDependencies": { + "@cldmv/configs": "^1.2.0", + "@cldmv/fix-headers": "^2.1.1", "@cldmv/vitest-runner": "^1.2.0", "@vitest/coverage-v8": "^5.0.0", "vitest": "^5.0.1" diff --git a/tests/gitmulti.cli.test.vitest.mjs b/tests/gitmulti.cli.test.vitest.mjs index 61e65b4..733333d 100644 --- a/tests/gitmulti.cli.test.vitest.mjs +++ b/tests/gitmulti.cli.test.vitest.mjs @@ -1,3 +1,18 @@ +/** + * + * @Project: gitmulti + * @Filename: /tests/gitmulti.cli.test.vitest.mjs + * @Date: 2026-08-02T23:52:42-07:00 (1785739962) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + * + */ + /** * End-to-end characterization of the gitmulti CLI entry point via a real, * fully isolated subprocess (spawnSync of `node gitmulti.js `). diff --git a/tests/gitmulti.test.vitest.mjs b/tests/gitmulti.test.vitest.mjs index ca09a8d..ffae39c 100644 --- a/tests/gitmulti.test.vitest.mjs +++ b/tests/gitmulti.test.vitest.mjs @@ -1,3 +1,18 @@ +/** + * + * @Project: gitmulti + * @Filename: /tests/gitmulti.test.vitest.mjs + * @Date: 2026-08-02T23:52:42-07:00 (1785739962) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-10-02T11:30:32-07:00 (1790965832) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + * + */ + /** * Characterization tests for gitmulti.js. * diff --git a/tests/run-vitest.mjs b/tests/run-vitest.mjs index 8dbdb5e..0a5277d 100644 --- a/tests/run-vitest.mjs +++ b/tests/run-vitest.mjs @@ -1,3 +1,18 @@ +/** + * + * @Project: gitmulti + * @Filename: /tests/run-vitest.mjs + * @Date: 2026-08-02T16:42:01-07:00 (1785714121) + * @Author: Nate Corcoran + * @Email: + * ----- + * @Last modified by: Nate Corcoran (Shinrai@users.noreply.github.com) + * @Last modified time: 2026-10-02T11:30:33-07:00 (1790965833) + * ----- + * @Copyright: Copyright (c) 2013-2026 Catalyzed Motivation Inc. All rights reserved. + * + */ + /** * @fileoverview OOM-safe Vitest runner โ€” delegates to @cldmv/vitest-runner, which * spawns each test file in its own child process and (under coverage) uses a