@theholocron/cli 2.0.0-alpha.6 → 2.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1092 -236
- package/package.json +4 -4
package/dist/cli.mjs
CHANGED
|
@@ -446,6 +446,1077 @@ async function runNpmBumpVersions(input) {
|
|
|
446
446
|
};
|
|
447
447
|
}
|
|
448
448
|
//#endregion
|
|
449
|
+
//#region src/templates/index.ts
|
|
450
|
+
/**
|
|
451
|
+
* All reusable workflow and composite action content bundled as string
|
|
452
|
+
* constants so the CLI can push them to theholocron/.github without
|
|
453
|
+
* needing filesystem access at runtime.
|
|
454
|
+
*
|
|
455
|
+
* These are the sources of truth — the YAML files in this directory
|
|
456
|
+
* have been removed in favour of these constants.
|
|
457
|
+
*/
|
|
458
|
+
const ACTIONS = {
|
|
459
|
+
"setup/action": `\
|
|
460
|
+
name: Setup
|
|
461
|
+
description: Prepare the environment and install project dependencies.
|
|
462
|
+
|
|
463
|
+
inputs:
|
|
464
|
+
node-version:
|
|
465
|
+
description: Node.js version
|
|
466
|
+
required: false
|
|
467
|
+
default: "22.x"
|
|
468
|
+
|
|
469
|
+
pnpm-version:
|
|
470
|
+
description: pnpm version
|
|
471
|
+
required: false
|
|
472
|
+
default: "10"
|
|
473
|
+
|
|
474
|
+
runs:
|
|
475
|
+
using: composite
|
|
476
|
+
|
|
477
|
+
steps:
|
|
478
|
+
- uses: ./.github/actions/setup-node
|
|
479
|
+
with:
|
|
480
|
+
node-version: \${{ inputs.node-version }}
|
|
481
|
+
pnpm-version: \${{ inputs.pnpm-version }}
|
|
482
|
+
|
|
483
|
+
- uses: ./.github/actions/install
|
|
484
|
+
`,
|
|
485
|
+
"install/action": `\
|
|
486
|
+
name: Install dependencies
|
|
487
|
+
description: Install project dependencies with pnpm frozen lockfile.
|
|
488
|
+
|
|
489
|
+
runs:
|
|
490
|
+
using: composite
|
|
491
|
+
|
|
492
|
+
steps:
|
|
493
|
+
- name: Install dependencies
|
|
494
|
+
shell: bash
|
|
495
|
+
run: pnpm install --frozen-lockfile
|
|
496
|
+
`,
|
|
497
|
+
"setup-node/action": `\
|
|
498
|
+
name: Setup Node
|
|
499
|
+
description: Install pnpm and Node.js with pnpm dependency caching.
|
|
500
|
+
|
|
501
|
+
inputs:
|
|
502
|
+
node-version:
|
|
503
|
+
description: Node.js version
|
|
504
|
+
required: false
|
|
505
|
+
default: "22.x"
|
|
506
|
+
|
|
507
|
+
pnpm-version:
|
|
508
|
+
description: pnpm version
|
|
509
|
+
required: false
|
|
510
|
+
default: "10"
|
|
511
|
+
|
|
512
|
+
runs:
|
|
513
|
+
using: composite
|
|
514
|
+
|
|
515
|
+
steps:
|
|
516
|
+
- name: Setup pnpm
|
|
517
|
+
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
|
|
518
|
+
with:
|
|
519
|
+
version: \${{ inputs.pnpm-version }}
|
|
520
|
+
|
|
521
|
+
- name: Setup Node.js
|
|
522
|
+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
|
523
|
+
with:
|
|
524
|
+
node-version: \${{ inputs.node-version }}
|
|
525
|
+
cache: pnpm
|
|
526
|
+
`
|
|
527
|
+
};
|
|
528
|
+
const REUSABLE_WORKFLOWS = {
|
|
529
|
+
audit: `\
|
|
530
|
+
name: Audit
|
|
531
|
+
|
|
532
|
+
on: # yamllint disable-line rule:truthy
|
|
533
|
+
workflow_call:
|
|
534
|
+
inputs:
|
|
535
|
+
build-script:
|
|
536
|
+
description: Script to build before analyzing bundle size
|
|
537
|
+
type: string
|
|
538
|
+
required: false
|
|
539
|
+
default: pnpm build
|
|
540
|
+
secrets:
|
|
541
|
+
BUNDLEWATCH_GITHUB_TOKEN:
|
|
542
|
+
required: true
|
|
543
|
+
|
|
544
|
+
jobs:
|
|
545
|
+
bundle-size:
|
|
546
|
+
name: Audit the bundle size
|
|
547
|
+
permissions:
|
|
548
|
+
contents: read
|
|
549
|
+
runs-on: ubuntu-latest
|
|
550
|
+
timeout-minutes: 15
|
|
551
|
+
concurrency:
|
|
552
|
+
group: audit-\${{ github.ref }}
|
|
553
|
+
cancel-in-progress: true
|
|
554
|
+
steps:
|
|
555
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
556
|
+
name: Checkout repository
|
|
557
|
+
with:
|
|
558
|
+
fetch-depth: 0
|
|
559
|
+
|
|
560
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
561
|
+
name: Setup
|
|
562
|
+
|
|
563
|
+
- uses: jackyef/bundlewatch-gh-action@01f51133d3580a6daa046ca83eb233d79735e1c1 # 0.3.0
|
|
564
|
+
name: Analyze using BundleWatch
|
|
565
|
+
with:
|
|
566
|
+
build-script: \${{ inputs.build-script }}
|
|
567
|
+
bundlewatch-github-token: \${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
|
568
|
+
`,
|
|
569
|
+
"bookkeeping-pr": `\
|
|
570
|
+
name: PR Bookkeeping
|
|
571
|
+
|
|
572
|
+
on: # yamllint disable-line rule:truthy
|
|
573
|
+
workflow_call:
|
|
574
|
+
inputs:
|
|
575
|
+
configuration-path:
|
|
576
|
+
description: Path to the labeler configuration file in the calling repo
|
|
577
|
+
type: string
|
|
578
|
+
required: false
|
|
579
|
+
default: .github/labeler.yml
|
|
580
|
+
|
|
581
|
+
jobs:
|
|
582
|
+
label:
|
|
583
|
+
name: Add Labels to PRs
|
|
584
|
+
permissions:
|
|
585
|
+
contents: read
|
|
586
|
+
pull-requests: write
|
|
587
|
+
runs-on: ubuntu-latest
|
|
588
|
+
timeout-minutes: 5
|
|
589
|
+
concurrency:
|
|
590
|
+
group: bookkeeping-pr-\${{ github.event.pull_request.number }}
|
|
591
|
+
cancel-in-progress: true
|
|
592
|
+
steps:
|
|
593
|
+
- uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4
|
|
594
|
+
with:
|
|
595
|
+
# Fall back to default path when triggered directly (not via workflow_call)
|
|
596
|
+
# because inputs.* defaults only apply on workflow_call events.
|
|
597
|
+
configuration-path: \${{ inputs.configuration-path || '.github/labeler.yml' }}
|
|
598
|
+
include-title: 1
|
|
599
|
+
include-body: 0
|
|
600
|
+
sync-labels: 1
|
|
601
|
+
enable-versioned-regex: 0
|
|
602
|
+
repo-token: \${{ github.token }}
|
|
603
|
+
`,
|
|
604
|
+
codeql: `\
|
|
605
|
+
name: CodeQL
|
|
606
|
+
|
|
607
|
+
on: # yamllint disable-line rule:truthy
|
|
608
|
+
workflow_call:
|
|
609
|
+
inputs:
|
|
610
|
+
language:
|
|
611
|
+
description: CodeQL language to analyze
|
|
612
|
+
type: string
|
|
613
|
+
required: false
|
|
614
|
+
default: javascript-typescript
|
|
615
|
+
|
|
616
|
+
jobs:
|
|
617
|
+
analyze:
|
|
618
|
+
name: Analyze (\${{ inputs.language }})
|
|
619
|
+
permissions:
|
|
620
|
+
actions: read
|
|
621
|
+
contents: read
|
|
622
|
+
security-events: write
|
|
623
|
+
runs-on: ubuntu-latest
|
|
624
|
+
timeout-minutes: 45
|
|
625
|
+
# Do not cancel in-progress security scans.
|
|
626
|
+
concurrency:
|
|
627
|
+
group: codeql-\${{ github.ref }}
|
|
628
|
+
cancel-in-progress: false
|
|
629
|
+
steps:
|
|
630
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
631
|
+
name: Checkout repository
|
|
632
|
+
|
|
633
|
+
- uses: github/codeql-action/init@411c4c9a36b3fca4d674f06b6396b2c6d23522c6 # v3
|
|
634
|
+
name: Initialize CodeQL
|
|
635
|
+
with:
|
|
636
|
+
languages: \${{ inputs.language }}
|
|
637
|
+
|
|
638
|
+
- uses: github/codeql-action/autobuild@411c4c9a36b3fca4d674f06b6396b2c6d23522c6 # v3
|
|
639
|
+
name: Autobuild
|
|
640
|
+
|
|
641
|
+
- uses: github/codeql-action/analyze@411c4c9a36b3fca4d674f06b6396b2c6d23522c6 # v3
|
|
642
|
+
name: Analyze
|
|
643
|
+
with:
|
|
644
|
+
category: /language:\${{ inputs.language }}
|
|
645
|
+
`,
|
|
646
|
+
dependencies: `\
|
|
647
|
+
name: Dependencies
|
|
648
|
+
|
|
649
|
+
on: # yamllint disable-line rule:truthy
|
|
650
|
+
workflow_call:
|
|
651
|
+
secrets:
|
|
652
|
+
merge-token:
|
|
653
|
+
description: >
|
|
654
|
+
Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.
|
|
655
|
+
Required when branch protection enforces required reviews — GITHUB_TOKEN
|
|
656
|
+
cannot approve its own PRs.
|
|
657
|
+
required: false
|
|
658
|
+
|
|
659
|
+
jobs:
|
|
660
|
+
dependabot:
|
|
661
|
+
name: Update the dependencies
|
|
662
|
+
permissions:
|
|
663
|
+
contents: write
|
|
664
|
+
pull-requests: write
|
|
665
|
+
runs-on: ubuntu-latest
|
|
666
|
+
timeout-minutes: 5
|
|
667
|
+
concurrency:
|
|
668
|
+
group: dependencies-\${{ github.event.pull_request.number }}
|
|
669
|
+
cancel-in-progress: true
|
|
670
|
+
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
|
671
|
+
steps:
|
|
672
|
+
- uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2
|
|
673
|
+
name: Fetch Dependabot metadata
|
|
674
|
+
id: metadata
|
|
675
|
+
|
|
676
|
+
- run: gh pr merge --auto --squash "$PR_URL"
|
|
677
|
+
# --squash is intentional: repoPolicy sets allow_merge_commit: false,
|
|
678
|
+
# so --merge would fail on any repo using the standard preset.
|
|
679
|
+
name: Enable auto-merge for Dependabot PRs
|
|
680
|
+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
|
|
681
|
+
env:
|
|
682
|
+
PR_URL: \${{ github.event.pull_request.html_url }}
|
|
683
|
+
GH_TOKEN: \${{ secrets.merge-token || github.token }}
|
|
684
|
+
`,
|
|
685
|
+
greetings: `\
|
|
686
|
+
name: Greetings
|
|
687
|
+
|
|
688
|
+
on: # yamllint disable-line rule:truthy
|
|
689
|
+
workflow_call:
|
|
690
|
+
|
|
691
|
+
jobs:
|
|
692
|
+
greeting:
|
|
693
|
+
name: Greet first-time contributors
|
|
694
|
+
permissions:
|
|
695
|
+
issues: write
|
|
696
|
+
pull-requests: write
|
|
697
|
+
runs-on: ubuntu-latest
|
|
698
|
+
timeout-minutes: 5
|
|
699
|
+
# Group by the issue/PR number so duplicate events don't race each other.
|
|
700
|
+
concurrency:
|
|
701
|
+
group: greetings-\${{ github.event.issue.number || github.event.pull_request.number }}
|
|
702
|
+
cancel-in-progress: false
|
|
703
|
+
steps:
|
|
704
|
+
- uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
|
|
705
|
+
name: Greet on first contribution
|
|
706
|
+
with:
|
|
707
|
+
script: |
|
|
708
|
+
// Only greet on the initial open — ignore synchronize, reopened, etc.
|
|
709
|
+
if (context.payload.action !== 'opened') return;
|
|
710
|
+
|
|
711
|
+
const actor = context.actor;
|
|
712
|
+
const { owner, repo } = context.repo;
|
|
713
|
+
|
|
714
|
+
// Payload inspection is more reliable than context.eventName for detecting
|
|
715
|
+
// whether this is an issue vs. PR event — works regardless of how GitHub
|
|
716
|
+
// propagates event names through workflow_call chains.
|
|
717
|
+
const isIssue = !!context.payload.issue && !context.payload.pull_request;
|
|
718
|
+
// listForRepo returns both issues and PRs (GitHub treats PRs as issues),
|
|
719
|
+
// sorted newest-first. Filter by type to track first-issue and first-PR
|
|
720
|
+
// independently, and avoid search-index eventual-consistency lag.
|
|
721
|
+
const { data: recent } = await github.rest.issues.listForRepo({
|
|
722
|
+
owner, repo,
|
|
723
|
+
creator: actor,
|
|
724
|
+
state: 'all',
|
|
725
|
+
per_page: 100
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
const sameType = recent.filter(item =>
|
|
729
|
+
isIssue ? !item.pull_request : !!item.pull_request
|
|
730
|
+
);
|
|
731
|
+
|
|
732
|
+
if (sameType.length !== 1) return;
|
|
733
|
+
const body = isIssue
|
|
734
|
+
? \`Hey @\${actor}!\\n\\nWe really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.\`
|
|
735
|
+
: \`Hey @\${actor}!\\n\\nWe really appreciate you taking the time to help out with this PR. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.\`;
|
|
736
|
+
|
|
737
|
+
await github.rest.issues.createComment({
|
|
738
|
+
owner,
|
|
739
|
+
repo,
|
|
740
|
+
issue_number: context.issue.number,
|
|
741
|
+
body
|
|
742
|
+
});
|
|
743
|
+
`,
|
|
744
|
+
lint: `\
|
|
745
|
+
name: Lint
|
|
746
|
+
|
|
747
|
+
on: # yamllint disable-line rule:truthy
|
|
748
|
+
workflow_call:
|
|
749
|
+
inputs:
|
|
750
|
+
prettier-config:
|
|
751
|
+
type: string
|
|
752
|
+
required: false
|
|
753
|
+
default: prettier.config.js
|
|
754
|
+
yaml-config:
|
|
755
|
+
type: string
|
|
756
|
+
required: false
|
|
757
|
+
default: yamllint.config.yml
|
|
758
|
+
enable-auto-commit:
|
|
759
|
+
description: Auto-commit super-linter fixes via GPG-signed commit
|
|
760
|
+
type: boolean
|
|
761
|
+
required: false
|
|
762
|
+
default: false
|
|
763
|
+
secrets:
|
|
764
|
+
SUPER_LINTER_GPG_PRIVATE_KEY:
|
|
765
|
+
required: false
|
|
766
|
+
SUPER_LINTER_GPG_PASSPHRASE:
|
|
767
|
+
required: false
|
|
768
|
+
|
|
769
|
+
jobs:
|
|
770
|
+
super-lint:
|
|
771
|
+
name: Lint entire codebase
|
|
772
|
+
permissions:
|
|
773
|
+
contents: write
|
|
774
|
+
statuses: write
|
|
775
|
+
runs-on: ubuntu-latest
|
|
776
|
+
timeout-minutes: 30
|
|
777
|
+
steps:
|
|
778
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
779
|
+
name: Checkout repository
|
|
780
|
+
with:
|
|
781
|
+
fetch-depth: 0
|
|
782
|
+
token: \${{ github.token }}
|
|
783
|
+
|
|
784
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
785
|
+
name: Setup
|
|
786
|
+
|
|
787
|
+
- uses: super-linter/super-linter/slim@b92721f792f381cedc002ecdbb9847a15ece5bb8 # v7.1.0
|
|
788
|
+
name: Run Super Linter
|
|
789
|
+
env:
|
|
790
|
+
GITHUB_TOKEN: \${{ github.token }}
|
|
791
|
+
ANNOTATE_ONLY: true
|
|
792
|
+
DISABLE_COMMENTS: false
|
|
793
|
+
IGNORE_GITIGNORED_FILES: true
|
|
794
|
+
LINTER_RULES_PATH: /
|
|
795
|
+
EDITORCONFIG_FILE_NAME: ".editorconfig-checker.json"
|
|
796
|
+
FIX_ENV: true
|
|
797
|
+
FIX_GRAPHQL_PRETTIER: true
|
|
798
|
+
FIX_HTML_PRETTIER: true
|
|
799
|
+
FIX_JAVASCRIPT_PRETTIER: true
|
|
800
|
+
FIX_JSX_PRETTIER: true
|
|
801
|
+
FIX_MARKDOWN_PRETTIER: true
|
|
802
|
+
FIX_TSX: true
|
|
803
|
+
FIX_TYPESCRIPT_PRETTIER: true
|
|
804
|
+
PRETTIER_CONFIG: \${{ inputs.prettier-config }}
|
|
805
|
+
VALIDATE_DOCKERFILE: true
|
|
806
|
+
VALIDATE_EDITORCONFIG: true
|
|
807
|
+
VALIDATE_ENV: true
|
|
808
|
+
VALIDATE_GIT_COMMITLINT: true
|
|
809
|
+
VALIDATE_GIT_MERGE_CONFLICT_MARKERS: true
|
|
810
|
+
VALIDATE_GITHUB_ACTIONS: true
|
|
811
|
+
VALIDATE_GITLEAKS: true
|
|
812
|
+
VALIDATE_GRAPHQL_PRETTIER: true
|
|
813
|
+
VALIDATE_HTML_PRETTIER: true
|
|
814
|
+
VALIDATE_JAVASCRIPT_PRETTIER: true
|
|
815
|
+
VALIDATE_JSX_PRETTIER: true
|
|
816
|
+
VALIDATE_MARKDOWN_PRETTIER: true
|
|
817
|
+
VALIDATE_TSX: true
|
|
818
|
+
VALIDATE_TYPESCRIPT_PRETTIER: true
|
|
819
|
+
VALIDATE_YAML: true
|
|
820
|
+
YAML_CONFIG_FILE: \${{ inputs.yaml-config }}
|
|
821
|
+
|
|
822
|
+
- uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6
|
|
823
|
+
name: Import GPG Key
|
|
824
|
+
# Conditions mirror auto-commit exactly — no point importing GPG if the
|
|
825
|
+
# commit step will be skipped (fork PR, default branch, or secret unset).
|
|
826
|
+
if: >
|
|
827
|
+
inputs.enable-auto-commit == true &&
|
|
828
|
+
github.event.pull_request != null &&
|
|
829
|
+
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
830
|
+
github.ref_name != github.event.repository.default_branch &&
|
|
831
|
+
secrets.SUPER_LINTER_GPG_PRIVATE_KEY != ''
|
|
832
|
+
with:
|
|
833
|
+
git_user_signingkey: true
|
|
834
|
+
git_commit_gpgsign: true
|
|
835
|
+
GPG_PRIVATE_KEY: \${{ secrets.SUPER_LINTER_GPG_PRIVATE_KEY }}
|
|
836
|
+
PASSPHRASE: \${{ secrets.SUPER_LINTER_GPG_PASSPHRASE }}
|
|
837
|
+
|
|
838
|
+
- uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 # v5
|
|
839
|
+
name: Commit and push linting fixes
|
|
840
|
+
if: >
|
|
841
|
+
inputs.enable-auto-commit == true &&
|
|
842
|
+
github.event.pull_request != null &&
|
|
843
|
+
github.event.pull_request.head.repo.full_name == github.repository &&
|
|
844
|
+
github.ref_name != github.event.repository.default_branch &&
|
|
845
|
+
secrets.SUPER_LINTER_GPG_PRIVATE_KEY != ''
|
|
846
|
+
with:
|
|
847
|
+
branch: \${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}
|
|
848
|
+
commit_message: "chore: fix linting issues"
|
|
849
|
+
commit_options: "--no-verify --signoff"
|
|
850
|
+
commit_user_name: super-linter
|
|
851
|
+
commit_user_email: super-linter@super-linter.dev
|
|
852
|
+
`,
|
|
853
|
+
release: `\
|
|
854
|
+
name: Release
|
|
855
|
+
|
|
856
|
+
# Semantic-release with OIDC Trusted Publishing — no NPM_TOKEN required.
|
|
857
|
+
# The calling repo must have a .releaserc.json that configures branches,
|
|
858
|
+
# plugins, and any publish options. npm@11+ is installed to support OIDC.
|
|
859
|
+
|
|
860
|
+
on: # yamllint disable-line rule:truthy
|
|
861
|
+
workflow_call:
|
|
862
|
+
inputs:
|
|
863
|
+
run-build:
|
|
864
|
+
description: Run \`pnpm build\` before releasing
|
|
865
|
+
type: boolean
|
|
866
|
+
required: false
|
|
867
|
+
default: true
|
|
868
|
+
|
|
869
|
+
jobs:
|
|
870
|
+
release:
|
|
871
|
+
name: Semantic release
|
|
872
|
+
permissions:
|
|
873
|
+
contents: write
|
|
874
|
+
id-token: write
|
|
875
|
+
issues: write
|
|
876
|
+
pull-requests: write
|
|
877
|
+
runs-on: ubuntu-latest
|
|
878
|
+
timeout-minutes: 30
|
|
879
|
+
# Do not cancel in-progress releases — a partial release is worse than a slow one.
|
|
880
|
+
concurrency:
|
|
881
|
+
group: release-\${{ github.ref }}
|
|
882
|
+
cancel-in-progress: false
|
|
883
|
+
steps:
|
|
884
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
885
|
+
name: Checkout repository
|
|
886
|
+
with:
|
|
887
|
+
fetch-depth: 0
|
|
888
|
+
token: \${{ github.token }}
|
|
889
|
+
|
|
890
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
891
|
+
name: Setup
|
|
892
|
+
|
|
893
|
+
- run: npm install -g npm@11 sigstore
|
|
894
|
+
name: Upgrade npm for OIDC support
|
|
895
|
+
# sigstore is required by libnpmpublish/provenance.js at module parse
|
|
896
|
+
# time — before any config takes effect. Some npm 11.x builds stopped
|
|
897
|
+
# bundling it; installing it globally into the same prefix ensures it
|
|
898
|
+
# resolves regardless of npm version. (Discovered 2026-07-09.)
|
|
899
|
+
|
|
900
|
+
- run: pnpm build
|
|
901
|
+
name: Build
|
|
902
|
+
if: \${{ inputs.run-build == true }}
|
|
903
|
+
|
|
904
|
+
- run: npx semantic-release
|
|
905
|
+
name: Release
|
|
906
|
+
env:
|
|
907
|
+
GITHUB_TOKEN: \${{ github.token }}
|
|
908
|
+
NPM_CONFIG_PROVENANCE: true
|
|
909
|
+
`,
|
|
910
|
+
review: `\
|
|
911
|
+
name: Review
|
|
912
|
+
|
|
913
|
+
# ReviewDog is the annotation layer — posts inline PR diff annotations.
|
|
914
|
+
# Runs on pull_request only: inline annotations require PR context,
|
|
915
|
+
# and branch protection ensures all changes go through PRs anyway.
|
|
916
|
+
# super-linter (lint.yml) is the CI gate covering push + PR events.
|
|
917
|
+
# Gitleaks and YAML are intentionally duplicated: super-linter gates
|
|
918
|
+
# merges; ReviewDog surfaces exact line annotations in the PR diff.
|
|
919
|
+
|
|
920
|
+
on: # yamllint disable-line rule:truthy
|
|
921
|
+
workflow_call:
|
|
922
|
+
|
|
923
|
+
concurrency:
|
|
924
|
+
group: review-\${{ github.workflow }}-\${{ github.ref }}
|
|
925
|
+
cancel-in-progress: true
|
|
926
|
+
|
|
927
|
+
jobs:
|
|
928
|
+
reviewdog:
|
|
929
|
+
name: Review PRs
|
|
930
|
+
runs-on: ubuntu-latest
|
|
931
|
+
timeout-minutes: 20
|
|
932
|
+
permissions:
|
|
933
|
+
contents: read
|
|
934
|
+
checks: write
|
|
935
|
+
pull-requests: write
|
|
936
|
+
|
|
937
|
+
steps:
|
|
938
|
+
- name: Checkout repository
|
|
939
|
+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
940
|
+
|
|
941
|
+
- name: Setup
|
|
942
|
+
if: \${{ hashFiles('pnpm-lock.yaml') != '' }}
|
|
943
|
+
uses: theholocron/.github/.github/actions/setup@main
|
|
944
|
+
|
|
945
|
+
- name: Install ReviewDog
|
|
946
|
+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1
|
|
947
|
+
with:
|
|
948
|
+
reviewdog_version: latest
|
|
949
|
+
|
|
950
|
+
#
|
|
951
|
+
# Always applicable
|
|
952
|
+
#
|
|
953
|
+
|
|
954
|
+
- name: Gitleaks (secrets)
|
|
955
|
+
uses: reviewdog/action-gitleaks@2b7b5685e3e3eecddab5d30cfa04f18123031421 # v1
|
|
956
|
+
with:
|
|
957
|
+
reporter: github-pr-check
|
|
958
|
+
|
|
959
|
+
- name: YamlLint
|
|
960
|
+
uses: reviewdog/action-yamllint@b5f7217d8c815ae374d1d55840d5e569d82f01f0 # v1
|
|
961
|
+
with:
|
|
962
|
+
reporter: github-pr-check
|
|
963
|
+
yamllint_flags: >-
|
|
964
|
+
\${{ hashFiles('yamllint.config.yml') != ''
|
|
965
|
+
&& format('-c {0}/yamllint.config.yml {0}', github.workspace)
|
|
966
|
+
|| github.workspace }}
|
|
967
|
+
|
|
968
|
+
- name: ActionLint (GitHub Actions)
|
|
969
|
+
if: \${{ hashFiles('.github/workflows/*.yml', '.github/workflows/*.yaml') != '' }}
|
|
970
|
+
uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1
|
|
971
|
+
with:
|
|
972
|
+
reporter: github-pr-check
|
|
973
|
+
|
|
974
|
+
#
|
|
975
|
+
# TypeScript / JavaScript
|
|
976
|
+
#
|
|
977
|
+
|
|
978
|
+
- name: ESLint
|
|
979
|
+
if: >-
|
|
980
|
+
\${{
|
|
981
|
+
hashFiles(
|
|
982
|
+
'**/eslint.config.js',
|
|
983
|
+
'**/eslint.config.mjs',
|
|
984
|
+
'**/eslint.config.cjs',
|
|
985
|
+
'**/eslint.config.ts',
|
|
986
|
+
'**/.eslintrc',
|
|
987
|
+
'**/.eslintrc.js',
|
|
988
|
+
'**/.eslintrc.cjs',
|
|
989
|
+
'**/.eslintrc.json',
|
|
990
|
+
'**/.eslintrc.yaml',
|
|
991
|
+
'**/.eslintrc.yml'
|
|
992
|
+
) != ''
|
|
993
|
+
}}
|
|
994
|
+
uses: reviewdog/action-eslint@556a3fdaf8b4201d4d74d406013386aa4f7dab96 # v1
|
|
995
|
+
with:
|
|
996
|
+
reporter: github-pr-check
|
|
997
|
+
eslint_flags: .
|
|
998
|
+
|
|
999
|
+
- name: TypeScript
|
|
1000
|
+
if: \${{ hashFiles('**/tsconfig.json') != '' }}
|
|
1001
|
+
uses: EPMatt/reviewdog-action-tsc@63d923a3c5b4497671940b8874f58a404e2351b5 # v1
|
|
1002
|
+
with:
|
|
1003
|
+
reporter: github-pr-check
|
|
1004
|
+
|
|
1005
|
+
#
|
|
1006
|
+
# Shell
|
|
1007
|
+
#
|
|
1008
|
+
|
|
1009
|
+
- name: ShellCheck
|
|
1010
|
+
if: \${{ hashFiles('**/*.sh') != '' }}
|
|
1011
|
+
uses: reviewdog/action-shellcheck@4c07458293ac342d477251099501a718ae5ef86e # v1
|
|
1012
|
+
with:
|
|
1013
|
+
reporter: github-pr-check
|
|
1014
|
+
fail_level: none
|
|
1015
|
+
|
|
1016
|
+
#
|
|
1017
|
+
# Docker
|
|
1018
|
+
#
|
|
1019
|
+
|
|
1020
|
+
- name: Hadolint
|
|
1021
|
+
if: >-
|
|
1022
|
+
\${{
|
|
1023
|
+
hashFiles(
|
|
1024
|
+
'**/Dockerfile',
|
|
1025
|
+
'**/*.Dockerfile',
|
|
1026
|
+
'**/Containerfile'
|
|
1027
|
+
) != ''
|
|
1028
|
+
}}
|
|
1029
|
+
uses: reviewdog/action-hadolint@1b2cfa6ba72072ad35158d7ff3aa49bbdc03506d # v1
|
|
1030
|
+
with:
|
|
1031
|
+
reporter: github-pr-check
|
|
1032
|
+
fail_level: none
|
|
1033
|
+
|
|
1034
|
+
#
|
|
1035
|
+
# Environment files
|
|
1036
|
+
#
|
|
1037
|
+
|
|
1038
|
+
- name: dotenv-linter
|
|
1039
|
+
if: \${{ hashFiles('**/.env*') != '' }}
|
|
1040
|
+
uses: dotenv-linter/action-dotenv-linter@21287e2624aaf2dc8da5dd8ccfe8e49c63501116 # v2
|
|
1041
|
+
with:
|
|
1042
|
+
reporter: github-code-suggestions
|
|
1043
|
+
|
|
1044
|
+
#
|
|
1045
|
+
# Documentation
|
|
1046
|
+
#
|
|
1047
|
+
|
|
1048
|
+
- name: Alex (inclusive language)
|
|
1049
|
+
if: \${{ hashFiles('**/*.md') != '' }}
|
|
1050
|
+
uses: reviewdog/action-alex@347481655add010a2ae302df34b57c9bcfa0d6e4 # v1
|
|
1051
|
+
with:
|
|
1052
|
+
reporter: github-pr-check
|
|
1053
|
+
`,
|
|
1054
|
+
stale: `\
|
|
1055
|
+
name: Stale
|
|
1056
|
+
|
|
1057
|
+
on: # yamllint disable-line rule:truthy
|
|
1058
|
+
workflow_call:
|
|
1059
|
+
inputs:
|
|
1060
|
+
days-before-stale:
|
|
1061
|
+
description: Days of inactivity before an issue is marked stale
|
|
1062
|
+
type: number
|
|
1063
|
+
required: false
|
|
1064
|
+
default: 30
|
|
1065
|
+
days-before-close:
|
|
1066
|
+
description: Days of inactivity after stale label before closing
|
|
1067
|
+
type: number
|
|
1068
|
+
required: false
|
|
1069
|
+
default: 5
|
|
1070
|
+
|
|
1071
|
+
jobs:
|
|
1072
|
+
stale:
|
|
1073
|
+
name: Mark stale issues and pull requests
|
|
1074
|
+
permissions:
|
|
1075
|
+
contents: write
|
|
1076
|
+
issues: write
|
|
1077
|
+
pull-requests: write
|
|
1078
|
+
runs-on: ubuntu-latest
|
|
1079
|
+
timeout-minutes: 10
|
|
1080
|
+
steps:
|
|
1081
|
+
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
|
|
1082
|
+
name: Run Stale
|
|
1083
|
+
with:
|
|
1084
|
+
close-issue-message: >
|
|
1085
|
+
This issue was closed because it has been stalled for
|
|
1086
|
+
\${{ inputs.days-before-close }} days with no activity.
|
|
1087
|
+
days-before-close: \${{ inputs.days-before-close }}
|
|
1088
|
+
days-before-stale: \${{ inputs.days-before-stale }}
|
|
1089
|
+
exempt-all-pr-milestones: true
|
|
1090
|
+
stale-issue-label: wontfix
|
|
1091
|
+
stale-issue-message: >
|
|
1092
|
+
This issue is stale because it has been open \${{ inputs.days-before-stale }}
|
|
1093
|
+
days with no activity. Remove the stale label or comment, or this will be
|
|
1094
|
+
closed in \${{ inputs.days-before-close }} days.
|
|
1095
|
+
stale-pr-label: wontfix
|
|
1096
|
+
stale-pr-message: >
|
|
1097
|
+
This PR is stale because it has been open \${{ inputs.days-before-stale }}
|
|
1098
|
+
days with no activity. Remove the stale label or comment, or this will be
|
|
1099
|
+
closed in \${{ inputs.days-before-close }} days.
|
|
1100
|
+
`,
|
|
1101
|
+
test: `\
|
|
1102
|
+
name: Test
|
|
1103
|
+
|
|
1104
|
+
on: # yamllint disable-line rule:truthy
|
|
1105
|
+
workflow_call:
|
|
1106
|
+
secrets:
|
|
1107
|
+
CODECOV_TOKEN:
|
|
1108
|
+
required: false
|
|
1109
|
+
|
|
1110
|
+
jobs:
|
|
1111
|
+
unit:
|
|
1112
|
+
name: Run tests and collect coverage
|
|
1113
|
+
permissions:
|
|
1114
|
+
contents: read
|
|
1115
|
+
runs-on: ubuntu-latest
|
|
1116
|
+
timeout-minutes: 15
|
|
1117
|
+
steps:
|
|
1118
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
1119
|
+
name: Checkout repository
|
|
1120
|
+
with:
|
|
1121
|
+
fetch-depth: 0
|
|
1122
|
+
|
|
1123
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
1124
|
+
name: Setup
|
|
1125
|
+
|
|
1126
|
+
- run: pnpm test -- --coverage
|
|
1127
|
+
name: Run tests with coverage
|
|
1128
|
+
|
|
1129
|
+
- uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
|
|
1130
|
+
name: Upload results to Codecov
|
|
1131
|
+
with:
|
|
1132
|
+
token: \${{ secrets.CODECOV_TOKEN }}
|
|
1133
|
+
`,
|
|
1134
|
+
typecheck: `\
|
|
1135
|
+
name: Typecheck
|
|
1136
|
+
|
|
1137
|
+
on: # yamllint disable-line rule:truthy
|
|
1138
|
+
workflow_call:
|
|
1139
|
+
|
|
1140
|
+
jobs:
|
|
1141
|
+
typecheck:
|
|
1142
|
+
name: tsc --noEmit
|
|
1143
|
+
permissions:
|
|
1144
|
+
contents: read
|
|
1145
|
+
runs-on: ubuntu-latest
|
|
1146
|
+
timeout-minutes: 10
|
|
1147
|
+
steps:
|
|
1148
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
1149
|
+
name: Checkout repository
|
|
1150
|
+
|
|
1151
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
1152
|
+
name: Setup
|
|
1153
|
+
|
|
1154
|
+
- run: pnpm typecheck
|
|
1155
|
+
name: Type check
|
|
1156
|
+
`
|
|
1157
|
+
};
|
|
1158
|
+
//#endregion
|
|
1159
|
+
//#region src/commands/setup-workflows.ts
|
|
1160
|
+
/**
|
|
1161
|
+
* Thin workflow wrapper templates for `holocron setup`.
|
|
1162
|
+
*
|
|
1163
|
+
* Each entry is a complete `.github/workflows/<name>.yml` that delegates
|
|
1164
|
+
* to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.
|
|
1165
|
+
* Files are overwritten on each setup run — they are generated artifacts.
|
|
1166
|
+
*/
|
|
1167
|
+
const WORKFLOW_REPO = "theholocron/.github";
|
|
1168
|
+
const WORKFLOW_REF = "main";
|
|
1169
|
+
function ref(name) {
|
|
1170
|
+
return `${WORKFLOW_REPO}/.github/workflows/${name}.yml@${WORKFLOW_REF}`;
|
|
1171
|
+
}
|
|
1172
|
+
/** Header prepended when holocron setup writes a thin caller to a repo. */
|
|
1173
|
+
const WORKFLOW_HEADER = `\
|
|
1174
|
+
# AUTO-GENERATED by holocron — do not edit directly.
|
|
1175
|
+
# Source: theholocron/holocron · packages/cli/src/commands/setup-workflows.ts
|
|
1176
|
+
# Run \`holocron setup\` to regenerate.
|
|
1177
|
+
|
|
1178
|
+
`;
|
|
1179
|
+
const WORKFLOW_TEMPLATES = {
|
|
1180
|
+
lint: `\
|
|
1181
|
+
name: Lint
|
|
1182
|
+
|
|
1183
|
+
on: # yamllint disable-line rule:truthy
|
|
1184
|
+
push:
|
|
1185
|
+
branches: [main, alpha]
|
|
1186
|
+
pull_request:
|
|
1187
|
+
|
|
1188
|
+
concurrency:
|
|
1189
|
+
group: lint-\${{ github.ref }}
|
|
1190
|
+
cancel-in-progress: true
|
|
1191
|
+
|
|
1192
|
+
permissions:
|
|
1193
|
+
contents: write
|
|
1194
|
+
statuses: write
|
|
1195
|
+
|
|
1196
|
+
jobs:
|
|
1197
|
+
lint:
|
|
1198
|
+
name: Lint
|
|
1199
|
+
uses: ${ref("lint")}
|
|
1200
|
+
secrets: inherit
|
|
1201
|
+
with:
|
|
1202
|
+
enable-auto-commit: true
|
|
1203
|
+
`,
|
|
1204
|
+
test: `\
|
|
1205
|
+
name: Test
|
|
1206
|
+
|
|
1207
|
+
on: # yamllint disable-line rule:truthy
|
|
1208
|
+
push:
|
|
1209
|
+
branches: [main, alpha]
|
|
1210
|
+
pull_request:
|
|
1211
|
+
|
|
1212
|
+
concurrency:
|
|
1213
|
+
group: test-\${{ github.ref }}
|
|
1214
|
+
cancel-in-progress: true
|
|
1215
|
+
|
|
1216
|
+
permissions:
|
|
1217
|
+
contents: read
|
|
1218
|
+
|
|
1219
|
+
jobs:
|
|
1220
|
+
test:
|
|
1221
|
+
name: Test
|
|
1222
|
+
uses: ${ref("test")}
|
|
1223
|
+
secrets: inherit
|
|
1224
|
+
`,
|
|
1225
|
+
typecheck: `\
|
|
1226
|
+
name: Typecheck
|
|
1227
|
+
|
|
1228
|
+
on: # yamllint disable-line rule:truthy
|
|
1229
|
+
push:
|
|
1230
|
+
branches: [main, alpha]
|
|
1231
|
+
pull_request:
|
|
1232
|
+
|
|
1233
|
+
concurrency:
|
|
1234
|
+
group: typecheck-\${{ github.ref }}
|
|
1235
|
+
cancel-in-progress: true
|
|
1236
|
+
|
|
1237
|
+
permissions:
|
|
1238
|
+
contents: read
|
|
1239
|
+
|
|
1240
|
+
jobs:
|
|
1241
|
+
typecheck:
|
|
1242
|
+
name: Typecheck
|
|
1243
|
+
uses: ${ref("typecheck")}
|
|
1244
|
+
secrets: inherit
|
|
1245
|
+
`,
|
|
1246
|
+
codeql: `\
|
|
1247
|
+
name: CodeQL
|
|
1248
|
+
|
|
1249
|
+
on: # yamllint disable-line rule:truthy
|
|
1250
|
+
push:
|
|
1251
|
+
branches:
|
|
1252
|
+
- main
|
|
1253
|
+
pull_request:
|
|
1254
|
+
branches:
|
|
1255
|
+
- main
|
|
1256
|
+
schedule:
|
|
1257
|
+
- cron: "0 0 * * 1"
|
|
1258
|
+
|
|
1259
|
+
permissions:
|
|
1260
|
+
actions: read
|
|
1261
|
+
contents: read
|
|
1262
|
+
security-events: write
|
|
1263
|
+
|
|
1264
|
+
jobs:
|
|
1265
|
+
codeql:
|
|
1266
|
+
uses: ${ref("codeql")}
|
|
1267
|
+
secrets: inherit
|
|
1268
|
+
`,
|
|
1269
|
+
review: `\
|
|
1270
|
+
name: Review
|
|
1271
|
+
|
|
1272
|
+
on: # yamllint disable-line rule:truthy
|
|
1273
|
+
pull_request:
|
|
1274
|
+
|
|
1275
|
+
concurrency:
|
|
1276
|
+
group: review-\${{ github.ref }}
|
|
1277
|
+
cancel-in-progress: true
|
|
1278
|
+
|
|
1279
|
+
permissions:
|
|
1280
|
+
contents: read
|
|
1281
|
+
checks: write
|
|
1282
|
+
pull-requests: write
|
|
1283
|
+
|
|
1284
|
+
jobs:
|
|
1285
|
+
review:
|
|
1286
|
+
name: Review
|
|
1287
|
+
uses: ${ref("review")}
|
|
1288
|
+
secrets: inherit
|
|
1289
|
+
`,
|
|
1290
|
+
release: `\
|
|
1291
|
+
name: Release
|
|
1292
|
+
|
|
1293
|
+
on: # yamllint disable-line rule:truthy
|
|
1294
|
+
push:
|
|
1295
|
+
branches:
|
|
1296
|
+
- main
|
|
1297
|
+
- alpha
|
|
1298
|
+
workflow_dispatch:
|
|
1299
|
+
|
|
1300
|
+
permissions:
|
|
1301
|
+
contents: write
|
|
1302
|
+
id-token: write
|
|
1303
|
+
issues: write
|
|
1304
|
+
pull-requests: write
|
|
1305
|
+
|
|
1306
|
+
concurrency:
|
|
1307
|
+
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
1308
|
+
cancel-in-progress: false
|
|
1309
|
+
|
|
1310
|
+
jobs:
|
|
1311
|
+
release:
|
|
1312
|
+
uses: ${ref("release")}
|
|
1313
|
+
secrets: inherit
|
|
1314
|
+
`,
|
|
1315
|
+
stale: `\
|
|
1316
|
+
name: Stale
|
|
1317
|
+
|
|
1318
|
+
on: # yamllint disable-line rule:truthy
|
|
1319
|
+
schedule:
|
|
1320
|
+
- cron: "30 1 * * *"
|
|
1321
|
+
|
|
1322
|
+
permissions:
|
|
1323
|
+
contents: write
|
|
1324
|
+
issues: write
|
|
1325
|
+
pull-requests: write
|
|
1326
|
+
|
|
1327
|
+
jobs:
|
|
1328
|
+
stale:
|
|
1329
|
+
uses: ${ref("stale")}
|
|
1330
|
+
secrets: inherit
|
|
1331
|
+
`,
|
|
1332
|
+
greetings: `\
|
|
1333
|
+
name: Greetings
|
|
1334
|
+
|
|
1335
|
+
on: # yamllint disable-line rule:truthy
|
|
1336
|
+
pull_request:
|
|
1337
|
+
issues:
|
|
1338
|
+
|
|
1339
|
+
permissions:
|
|
1340
|
+
issues: write
|
|
1341
|
+
pull-requests: write
|
|
1342
|
+
|
|
1343
|
+
jobs:
|
|
1344
|
+
greetings:
|
|
1345
|
+
uses: ${ref("greetings")}
|
|
1346
|
+
secrets: inherit
|
|
1347
|
+
`,
|
|
1348
|
+
dependencies: `\
|
|
1349
|
+
name: Dependencies
|
|
1350
|
+
|
|
1351
|
+
on: # yamllint disable-line rule:truthy
|
|
1352
|
+
pull_request:
|
|
1353
|
+
|
|
1354
|
+
permissions:
|
|
1355
|
+
contents: write
|
|
1356
|
+
pull-requests: write
|
|
1357
|
+
|
|
1358
|
+
jobs:
|
|
1359
|
+
dependencies:
|
|
1360
|
+
uses: ${ref("dependencies")}
|
|
1361
|
+
secrets: inherit
|
|
1362
|
+
`,
|
|
1363
|
+
"bookkeeping-pr": `\
|
|
1364
|
+
name: PR Bookkeeping
|
|
1365
|
+
|
|
1366
|
+
on: # yamllint disable-line rule:truthy
|
|
1367
|
+
pull_request:
|
|
1368
|
+
types:
|
|
1369
|
+
- opened
|
|
1370
|
+
- edited
|
|
1371
|
+
|
|
1372
|
+
permissions:
|
|
1373
|
+
contents: read
|
|
1374
|
+
pull-requests: write
|
|
1375
|
+
|
|
1376
|
+
jobs:
|
|
1377
|
+
bookkeeping:
|
|
1378
|
+
uses: ${ref("bookkeeping-pr")}
|
|
1379
|
+
secrets: inherit
|
|
1380
|
+
`,
|
|
1381
|
+
audit: `\
|
|
1382
|
+
name: Audit
|
|
1383
|
+
|
|
1384
|
+
on: # yamllint disable-line rule:truthy
|
|
1385
|
+
push:
|
|
1386
|
+
branches: [main, alpha]
|
|
1387
|
+
pull_request:
|
|
1388
|
+
|
|
1389
|
+
permissions:
|
|
1390
|
+
contents: read
|
|
1391
|
+
|
|
1392
|
+
jobs:
|
|
1393
|
+
audit:
|
|
1394
|
+
uses: ${ref("audit")}
|
|
1395
|
+
secrets: inherit
|
|
1396
|
+
`
|
|
1397
|
+
};
|
|
1398
|
+
const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));
|
|
1399
|
+
//#endregion
|
|
1400
|
+
//#region src/commands/sync-github.ts
|
|
1401
|
+
const DEFAULT_REPO = "theholocron/.github";
|
|
1402
|
+
const API_BASE = "https://api.github.com";
|
|
1403
|
+
function reusableHeader(source) {
|
|
1404
|
+
return [
|
|
1405
|
+
`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,
|
|
1406
|
+
`# Source: theholocron/holocron · ${source}`,
|
|
1407
|
+
`# Synced: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
1408
|
+
`# Tool: holocron sync-github`,
|
|
1409
|
+
`# Changes: edit source in theholocron/holocron and push to alpha or main.`,
|
|
1410
|
+
``
|
|
1411
|
+
].join("\n");
|
|
1412
|
+
}
|
|
1413
|
+
function thinCallerHeader() {
|
|
1414
|
+
return [
|
|
1415
|
+
`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,
|
|
1416
|
+
`# Source: theholocron/holocron · packages/cli/src/commands/setup-workflows.ts`,
|
|
1417
|
+
`# Synced: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
1418
|
+
`# Tool: holocron sync-github`,
|
|
1419
|
+
`# Changes: edit setup-workflows.ts in theholocron/holocron and push.`,
|
|
1420
|
+
``
|
|
1421
|
+
].join("\n");
|
|
1422
|
+
}
|
|
1423
|
+
function buildBatch() {
|
|
1424
|
+
const files = [];
|
|
1425
|
+
for (const [name, content] of Object.entries(ACTIONS)) files.push({
|
|
1426
|
+
path: `.github/actions/${name}.yml`,
|
|
1427
|
+
content: reusableHeader(`packages/cli/src/templates/index.ts`) + content
|
|
1428
|
+
});
|
|
1429
|
+
for (const [name, content] of Object.entries(REUSABLE_WORKFLOWS)) files.push({
|
|
1430
|
+
path: `.github/workflows/${name}.yml`,
|
|
1431
|
+
content: reusableHeader(`packages/cli/src/templates/index.ts`) + content
|
|
1432
|
+
});
|
|
1433
|
+
for (const [name, content] of Object.entries(WORKFLOW_TEMPLATES)) files.push({
|
|
1434
|
+
path: `workflow-templates/${name}.yml`,
|
|
1435
|
+
content: thinCallerHeader() + content
|
|
1436
|
+
});
|
|
1437
|
+
return files;
|
|
1438
|
+
}
|
|
1439
|
+
async function runSyncGithub(input) {
|
|
1440
|
+
const print = input.print ?? ((line) => console.log(line));
|
|
1441
|
+
const repo = input.repo ?? DEFAULT_REPO;
|
|
1442
|
+
const [owner, repoName] = repo.split("/");
|
|
1443
|
+
const { token, dryRun = false } = input;
|
|
1444
|
+
const message = input.message ?? `chore: sync from theholocron/holocron`;
|
|
1445
|
+
const fetchFn = input.fetch ?? globalThis.fetch;
|
|
1446
|
+
const headers = {
|
|
1447
|
+
Authorization: `Bearer ${token}`,
|
|
1448
|
+
Accept: "application/vnd.github+json",
|
|
1449
|
+
"Content-Type": "application/json",
|
|
1450
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1451
|
+
};
|
|
1452
|
+
print(`holocron sync-github${dryRun ? " (dry-run)" : ""}`);
|
|
1453
|
+
print(` repo: ${repo}`);
|
|
1454
|
+
print("");
|
|
1455
|
+
const batch = buildBatch();
|
|
1456
|
+
let created = 0;
|
|
1457
|
+
let updated = 0;
|
|
1458
|
+
let unchanged = 0;
|
|
1459
|
+
for (const file of batch) {
|
|
1460
|
+
const url = `${API_BASE}/repos/${owner}/${repoName}/contents/${file.path}`;
|
|
1461
|
+
const newContent = Buffer.from(file.content, "utf8").toString("base64");
|
|
1462
|
+
let existingSha;
|
|
1463
|
+
let existingContent;
|
|
1464
|
+
try {
|
|
1465
|
+
const getRes = await fetchFn(url, { headers });
|
|
1466
|
+
if (getRes.ok) {
|
|
1467
|
+
const data = await getRes.json();
|
|
1468
|
+
existingSha = data.sha;
|
|
1469
|
+
existingContent = data.content.replace(/\n/g, "");
|
|
1470
|
+
}
|
|
1471
|
+
} catch {}
|
|
1472
|
+
if (existingContent === newContent) {
|
|
1473
|
+
print(` · unchanged ${file.path}`);
|
|
1474
|
+
unchanged++;
|
|
1475
|
+
continue;
|
|
1476
|
+
}
|
|
1477
|
+
const verb = existingSha ? "updated " : "created ";
|
|
1478
|
+
if (dryRun) {
|
|
1479
|
+
print(` ~ ${verb} ${file.path}`);
|
|
1480
|
+
if (existingSha) updated++;
|
|
1481
|
+
else created++;
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
const body = {
|
|
1485
|
+
message,
|
|
1486
|
+
content: newContent
|
|
1487
|
+
};
|
|
1488
|
+
if (existingSha) body.sha = existingSha;
|
|
1489
|
+
const putRes = await fetchFn(url, {
|
|
1490
|
+
method: "PUT",
|
|
1491
|
+
headers,
|
|
1492
|
+
body: JSON.stringify(body)
|
|
1493
|
+
});
|
|
1494
|
+
if (!putRes.ok) {
|
|
1495
|
+
const err = await putRes.json();
|
|
1496
|
+
const msg = `failed to push ${file.path}: ${err.message ?? putRes.status}`;
|
|
1497
|
+
print(` ✗ ${msg}`);
|
|
1498
|
+
return {
|
|
1499
|
+
status: "fail",
|
|
1500
|
+
created,
|
|
1501
|
+
updated,
|
|
1502
|
+
unchanged,
|
|
1503
|
+
message: msg
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
print(` ✓ ${verb} ${file.path}`);
|
|
1507
|
+
if (existingSha) updated++;
|
|
1508
|
+
else created++;
|
|
1509
|
+
}
|
|
1510
|
+
print("");
|
|
1511
|
+
print(` ${created} created, ${updated} updated, ${unchanged} unchanged`);
|
|
1512
|
+
return {
|
|
1513
|
+
status: dryRun ? "dry-run" : "ok",
|
|
1514
|
+
created,
|
|
1515
|
+
updated,
|
|
1516
|
+
unchanged
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
//#endregion
|
|
449
1520
|
//#region src/commands/npm-publish-initial.ts
|
|
450
1521
|
/**
|
|
451
1522
|
* `holocron npm publish-initial` — bottles up the chicken-and-egg
|
|
@@ -1865,241 +2936,6 @@ function vaultProviderName(loader) {
|
|
|
1865
2936
|
return loader.get("vault").providerName;
|
|
1866
2937
|
}
|
|
1867
2938
|
//#endregion
|
|
1868
|
-
//#region src/commands/setup-workflows.ts
|
|
1869
|
-
/**
|
|
1870
|
-
* Thin workflow wrapper templates for `holocron setup`.
|
|
1871
|
-
*
|
|
1872
|
-
* Each entry is a complete `.github/workflows/<name>.yml` that delegates
|
|
1873
|
-
* to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.
|
|
1874
|
-
* Files are overwritten on each setup run — they are generated artifacts.
|
|
1875
|
-
*/
|
|
1876
|
-
const WORKFLOW_REPO = "theholocron/.github";
|
|
1877
|
-
const WORKFLOW_REF = "main";
|
|
1878
|
-
function ref(name) {
|
|
1879
|
-
return `${WORKFLOW_REPO}/.github/workflows/${name}.yml@${WORKFLOW_REF}`;
|
|
1880
|
-
}
|
|
1881
|
-
/** Header prepended when holocron setup writes a thin caller to a repo. */
|
|
1882
|
-
const WORKFLOW_HEADER = `\
|
|
1883
|
-
# AUTO-GENERATED by holocron — do not edit directly.
|
|
1884
|
-
# Source: theholocron/holocron · packages/cli/src/commands/setup-workflows.ts
|
|
1885
|
-
# Run \`holocron setup\` to regenerate.
|
|
1886
|
-
|
|
1887
|
-
`;
|
|
1888
|
-
const WORKFLOW_TEMPLATES = {
|
|
1889
|
-
lint: `\
|
|
1890
|
-
name: Lint
|
|
1891
|
-
|
|
1892
|
-
on: # yamllint disable-line rule:truthy
|
|
1893
|
-
push:
|
|
1894
|
-
branches: [main, alpha]
|
|
1895
|
-
pull_request:
|
|
1896
|
-
|
|
1897
|
-
concurrency:
|
|
1898
|
-
group: lint-\${{ github.ref }}
|
|
1899
|
-
cancel-in-progress: true
|
|
1900
|
-
|
|
1901
|
-
permissions:
|
|
1902
|
-
contents: write
|
|
1903
|
-
statuses: write
|
|
1904
|
-
|
|
1905
|
-
jobs:
|
|
1906
|
-
lint:
|
|
1907
|
-
name: Lint
|
|
1908
|
-
uses: ${ref("lint")}
|
|
1909
|
-
secrets: inherit
|
|
1910
|
-
with:
|
|
1911
|
-
enable-auto-commit: true
|
|
1912
|
-
`,
|
|
1913
|
-
test: `\
|
|
1914
|
-
name: Test
|
|
1915
|
-
|
|
1916
|
-
on: # yamllint disable-line rule:truthy
|
|
1917
|
-
push:
|
|
1918
|
-
branches: [main, alpha]
|
|
1919
|
-
pull_request:
|
|
1920
|
-
|
|
1921
|
-
concurrency:
|
|
1922
|
-
group: test-\${{ github.ref }}
|
|
1923
|
-
cancel-in-progress: true
|
|
1924
|
-
|
|
1925
|
-
permissions:
|
|
1926
|
-
contents: read
|
|
1927
|
-
|
|
1928
|
-
jobs:
|
|
1929
|
-
test:
|
|
1930
|
-
name: Test
|
|
1931
|
-
uses: ${ref("test")}
|
|
1932
|
-
secrets: inherit
|
|
1933
|
-
`,
|
|
1934
|
-
typecheck: `\
|
|
1935
|
-
name: Typecheck
|
|
1936
|
-
|
|
1937
|
-
on: # yamllint disable-line rule:truthy
|
|
1938
|
-
push:
|
|
1939
|
-
branches: [main, alpha]
|
|
1940
|
-
pull_request:
|
|
1941
|
-
|
|
1942
|
-
concurrency:
|
|
1943
|
-
group: typecheck-\${{ github.ref }}
|
|
1944
|
-
cancel-in-progress: true
|
|
1945
|
-
|
|
1946
|
-
permissions:
|
|
1947
|
-
contents: read
|
|
1948
|
-
|
|
1949
|
-
jobs:
|
|
1950
|
-
typecheck:
|
|
1951
|
-
name: Typecheck
|
|
1952
|
-
uses: ${ref("typecheck")}
|
|
1953
|
-
secrets: inherit
|
|
1954
|
-
`,
|
|
1955
|
-
codeql: `\
|
|
1956
|
-
name: CodeQL
|
|
1957
|
-
|
|
1958
|
-
on: # yamllint disable-line rule:truthy
|
|
1959
|
-
push:
|
|
1960
|
-
branches:
|
|
1961
|
-
- main
|
|
1962
|
-
pull_request:
|
|
1963
|
-
branches:
|
|
1964
|
-
- main
|
|
1965
|
-
schedule:
|
|
1966
|
-
- cron: "0 0 * * 1"
|
|
1967
|
-
|
|
1968
|
-
permissions:
|
|
1969
|
-
actions: read
|
|
1970
|
-
contents: read
|
|
1971
|
-
security-events: write
|
|
1972
|
-
|
|
1973
|
-
jobs:
|
|
1974
|
-
codeql:
|
|
1975
|
-
uses: ${ref("codeql")}
|
|
1976
|
-
secrets: inherit
|
|
1977
|
-
`,
|
|
1978
|
-
review: `\
|
|
1979
|
-
name: Review
|
|
1980
|
-
|
|
1981
|
-
on: # yamllint disable-line rule:truthy
|
|
1982
|
-
pull_request:
|
|
1983
|
-
|
|
1984
|
-
concurrency:
|
|
1985
|
-
group: review-\${{ github.ref }}
|
|
1986
|
-
cancel-in-progress: true
|
|
1987
|
-
|
|
1988
|
-
permissions:
|
|
1989
|
-
contents: read
|
|
1990
|
-
checks: write
|
|
1991
|
-
pull-requests: write
|
|
1992
|
-
|
|
1993
|
-
jobs:
|
|
1994
|
-
review:
|
|
1995
|
-
name: Review
|
|
1996
|
-
uses: ${ref("review")}
|
|
1997
|
-
secrets: inherit
|
|
1998
|
-
`,
|
|
1999
|
-
release: `\
|
|
2000
|
-
name: Release
|
|
2001
|
-
|
|
2002
|
-
on: # yamllint disable-line rule:truthy
|
|
2003
|
-
push:
|
|
2004
|
-
branches:
|
|
2005
|
-
- main
|
|
2006
|
-
|
|
2007
|
-
permissions:
|
|
2008
|
-
contents: write
|
|
2009
|
-
id-token: write
|
|
2010
|
-
issues: write
|
|
2011
|
-
pull-requests: write
|
|
2012
|
-
|
|
2013
|
-
jobs:
|
|
2014
|
-
release:
|
|
2015
|
-
uses: ${ref("release")}
|
|
2016
|
-
secrets: inherit
|
|
2017
|
-
`,
|
|
2018
|
-
stale: `\
|
|
2019
|
-
name: Stale
|
|
2020
|
-
|
|
2021
|
-
on: # yamllint disable-line rule:truthy
|
|
2022
|
-
schedule:
|
|
2023
|
-
- cron: "30 1 * * *"
|
|
2024
|
-
|
|
2025
|
-
permissions:
|
|
2026
|
-
contents: write
|
|
2027
|
-
issues: write
|
|
2028
|
-
pull-requests: write
|
|
2029
|
-
|
|
2030
|
-
jobs:
|
|
2031
|
-
stale:
|
|
2032
|
-
uses: ${ref("stale")}
|
|
2033
|
-
secrets: inherit
|
|
2034
|
-
`,
|
|
2035
|
-
greetings: `\
|
|
2036
|
-
name: Greetings
|
|
2037
|
-
|
|
2038
|
-
on: # yamllint disable-line rule:truthy
|
|
2039
|
-
pull_request:
|
|
2040
|
-
issues:
|
|
2041
|
-
|
|
2042
|
-
permissions:
|
|
2043
|
-
issues: write
|
|
2044
|
-
pull-requests: write
|
|
2045
|
-
|
|
2046
|
-
jobs:
|
|
2047
|
-
greetings:
|
|
2048
|
-
uses: ${ref("greetings")}
|
|
2049
|
-
secrets: inherit
|
|
2050
|
-
`,
|
|
2051
|
-
dependencies: `\
|
|
2052
|
-
name: Dependencies
|
|
2053
|
-
|
|
2054
|
-
on: # yamllint disable-line rule:truthy
|
|
2055
|
-
pull_request:
|
|
2056
|
-
|
|
2057
|
-
permissions:
|
|
2058
|
-
contents: write
|
|
2059
|
-
pull-requests: write
|
|
2060
|
-
|
|
2061
|
-
jobs:
|
|
2062
|
-
dependencies:
|
|
2063
|
-
uses: ${ref("dependencies")}
|
|
2064
|
-
secrets: inherit
|
|
2065
|
-
`,
|
|
2066
|
-
"bookkeeping-pr": `\
|
|
2067
|
-
name: PR Bookkeeping
|
|
2068
|
-
|
|
2069
|
-
on: # yamllint disable-line rule:truthy
|
|
2070
|
-
pull_request:
|
|
2071
|
-
types:
|
|
2072
|
-
- opened
|
|
2073
|
-
- edited
|
|
2074
|
-
|
|
2075
|
-
permissions:
|
|
2076
|
-
contents: read
|
|
2077
|
-
pull-requests: write
|
|
2078
|
-
|
|
2079
|
-
jobs:
|
|
2080
|
-
bookkeeping:
|
|
2081
|
-
uses: ${ref("bookkeeping-pr")}
|
|
2082
|
-
secrets: inherit
|
|
2083
|
-
`,
|
|
2084
|
-
audit: `\
|
|
2085
|
-
name: Audit
|
|
2086
|
-
|
|
2087
|
-
on: # yamllint disable-line rule:truthy
|
|
2088
|
-
push:
|
|
2089
|
-
branches: [main, alpha]
|
|
2090
|
-
pull_request:
|
|
2091
|
-
|
|
2092
|
-
permissions:
|
|
2093
|
-
contents: read
|
|
2094
|
-
|
|
2095
|
-
jobs:
|
|
2096
|
-
audit:
|
|
2097
|
-
uses: ${ref("audit")}
|
|
2098
|
-
secrets: inherit
|
|
2099
|
-
`
|
|
2100
|
-
};
|
|
2101
|
-
const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));
|
|
2102
|
-
//#endregion
|
|
2103
2939
|
//#region src/commands/setup.ts
|
|
2104
2940
|
const DEPENDABOT_CONFIG = `\
|
|
2105
2941
|
# AUTO-GENERATED by holocron — run \`holocron setup\` to regenerate.
|
|
@@ -2653,7 +3489,27 @@ await yargs(hideBin(process.argv)).scriptName("holocron").usage("$0 <command> [o
|
|
|
2653
3489
|
dryRun: argv.dryRun,
|
|
2654
3490
|
...argv.otp ? { otp: argv.otp } : {}
|
|
2655
3491
|
})).status === "fail") process.exitCode = 1;
|
|
2656
|
-
}).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("
|
|
3492
|
+
}).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("sync-github", "Sync workflow templates and composite actions to theholocron/.github via the GitHub API", (y) => y.option("repo", {
|
|
3493
|
+
type: "string",
|
|
3494
|
+
default: "theholocron/.github",
|
|
3495
|
+
describe: "Target org/repo (default: theholocron/.github)"
|
|
3496
|
+
}).option("message", {
|
|
3497
|
+
type: "string",
|
|
3498
|
+
describe: "Commit message (default: chore: sync from theholocron/holocron)"
|
|
3499
|
+
}), async (argv) => {
|
|
3500
|
+
const token = argv.token ?? process.env.GITHUB_TOKEN ?? process.env.HOLOCRON_GITHUB_TOKEN;
|
|
3501
|
+
if (!token) {
|
|
3502
|
+
console.error("sync-github: GitHub token required — pass --token or set GITHUB_TOKEN");
|
|
3503
|
+
process.exitCode = 1;
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3506
|
+
if ((await runSyncGithub({
|
|
3507
|
+
token,
|
|
3508
|
+
repo: argv.repo,
|
|
3509
|
+
dryRun: argv.dryRun,
|
|
3510
|
+
...argv.message ? { message: argv.message } : {}
|
|
3511
|
+
})).status === "fail") process.exitCode = 1;
|
|
3512
|
+
}).command("config show", "Print the resolved holocron config", () => {}, async (argv) => {
|
|
2657
3513
|
const loaded = await loadConfig(argv.cwd);
|
|
2658
3514
|
console.log(JSON.stringify(loaded.resolved, null, 2));
|
|
2659
3515
|
}).command("plugin create <slug> <vendor>", "Scaffold a new @theholocron/holocron-plugin-<slug> package", (y) => y.positional("slug", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.8",
|
|
4
4
|
"description": "The Holocron CLI — a pluggable, capability-based orchestrator for spinning up and operating software projects.",
|
|
5
5
|
"homepage": "https://github.com/theholocron/holocron/tree/main/packages/cli#readme",
|
|
6
6
|
"bugs": "https://github.com/theholocron/holocron/issues",
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@napi-rs/keyring": "^1.3.0",
|
|
37
|
-
"yargs": "^18.0.0"
|
|
38
|
-
"@theholocron/cli-utils": "0.0.0"
|
|
37
|
+
"yargs": "^18.0.0"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
40
|
"@theholocron/eslint-config": "^4.1.0",
|
|
@@ -47,7 +46,8 @@
|
|
|
47
46
|
"globals": "^16.5.0",
|
|
48
47
|
"tsdown": "^0.22.3",
|
|
49
48
|
"typescript": "^5.9.3",
|
|
50
|
-
"vitest": "^3.2.6"
|
|
49
|
+
"vitest": "^3.2.6",
|
|
50
|
+
"@theholocron/cli-utils": "0.0.0"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|