@theholocron/cli 2.0.0-alpha.7 → 2.0.0-alpha.9
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 +1225 -236
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -446,6 +446,1201 @@ 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
|
+
"sync-github": `\
|
|
1135
|
+
name: Sync GitHub Templates
|
|
1136
|
+
|
|
1137
|
+
# Builds the holocron CLI from source and pushes updated workflow templates
|
|
1138
|
+
# and composite actions to downstream .github repos. Runs whenever the
|
|
1139
|
+
# template source files change on main or alpha.
|
|
1140
|
+
#
|
|
1141
|
+
# Secrets required:
|
|
1142
|
+
# SYNC_TOKEN — fine-grained PAT or GitHub App token with Contents write
|
|
1143
|
+
# access to the primary and secondary repos.
|
|
1144
|
+
|
|
1145
|
+
on: # yamllint disable-line rule:truthy
|
|
1146
|
+
workflow_call:
|
|
1147
|
+
inputs:
|
|
1148
|
+
primary-repo:
|
|
1149
|
+
description: >
|
|
1150
|
+
Primary .github repo — receives composite actions, reusable workflows,
|
|
1151
|
+
and thin-caller templates. Requires a PR (branch protection assumed).
|
|
1152
|
+
type: string
|
|
1153
|
+
required: false
|
|
1154
|
+
default: theholocron/.github
|
|
1155
|
+
secondary-repos:
|
|
1156
|
+
description: >
|
|
1157
|
+
Space-separated list of secondary repos (reusable workflows + thin
|
|
1158
|
+
callers only, no composite actions). Pushed directly to main.
|
|
1159
|
+
type: string
|
|
1160
|
+
required: false
|
|
1161
|
+
default: ""
|
|
1162
|
+
sync-branch:
|
|
1163
|
+
description: Branch name used for the primary-repo PR
|
|
1164
|
+
type: string
|
|
1165
|
+
required: false
|
|
1166
|
+
default: chore/sync-templates
|
|
1167
|
+
secrets:
|
|
1168
|
+
SYNC_TOKEN:
|
|
1169
|
+
required: true
|
|
1170
|
+
|
|
1171
|
+
jobs:
|
|
1172
|
+
sync:
|
|
1173
|
+
name: Sync templates
|
|
1174
|
+
runs-on: ubuntu-latest
|
|
1175
|
+
timeout-minutes: 15
|
|
1176
|
+
permissions:
|
|
1177
|
+
contents: read
|
|
1178
|
+
steps:
|
|
1179
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
1180
|
+
name: Checkout repository
|
|
1181
|
+
|
|
1182
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
1183
|
+
name: Setup
|
|
1184
|
+
|
|
1185
|
+
- run: pnpm build
|
|
1186
|
+
name: Build CLI
|
|
1187
|
+
|
|
1188
|
+
- name: Sync primary repo (PR)
|
|
1189
|
+
run: >
|
|
1190
|
+
node packages/cli/dist/cli.mjs sync-github
|
|
1191
|
+
--repo \${{ inputs.primary-repo }}
|
|
1192
|
+
--branch \${{ inputs.sync-branch }}
|
|
1193
|
+
--pr
|
|
1194
|
+
env:
|
|
1195
|
+
GITHUB_TOKEN: \${{ secrets.SYNC_TOKEN }}
|
|
1196
|
+
|
|
1197
|
+
- name: Sync secondary repos (direct push)
|
|
1198
|
+
if: \${{ inputs.secondary-repos != '' }}
|
|
1199
|
+
run: |
|
|
1200
|
+
for repo in \${{ inputs.secondary-repos }}; do
|
|
1201
|
+
node packages/cli/dist/cli.mjs sync-github --repo "$repo"
|
|
1202
|
+
done
|
|
1203
|
+
env:
|
|
1204
|
+
GITHUB_TOKEN: \${{ secrets.SYNC_TOKEN }}
|
|
1205
|
+
`,
|
|
1206
|
+
typecheck: `\
|
|
1207
|
+
name: Typecheck
|
|
1208
|
+
|
|
1209
|
+
on: # yamllint disable-line rule:truthy
|
|
1210
|
+
workflow_call:
|
|
1211
|
+
|
|
1212
|
+
jobs:
|
|
1213
|
+
typecheck:
|
|
1214
|
+
name: tsc --noEmit
|
|
1215
|
+
permissions:
|
|
1216
|
+
contents: read
|
|
1217
|
+
runs-on: ubuntu-latest
|
|
1218
|
+
timeout-minutes: 10
|
|
1219
|
+
steps:
|
|
1220
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
1221
|
+
name: Checkout repository
|
|
1222
|
+
|
|
1223
|
+
- uses: theholocron/.github/.github/actions/setup@main
|
|
1224
|
+
name: Setup
|
|
1225
|
+
|
|
1226
|
+
- run: pnpm typecheck
|
|
1227
|
+
name: Type check
|
|
1228
|
+
`
|
|
1229
|
+
};
|
|
1230
|
+
//#endregion
|
|
1231
|
+
//#region src/commands/setup-workflows.ts
|
|
1232
|
+
/**
|
|
1233
|
+
* Thin workflow wrapper templates for `holocron setup`.
|
|
1234
|
+
*
|
|
1235
|
+
* Each entry is a complete `.github/workflows/<name>.yml` that delegates
|
|
1236
|
+
* to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.
|
|
1237
|
+
* Files are overwritten on each setup run — they are generated artifacts.
|
|
1238
|
+
*/
|
|
1239
|
+
const WORKFLOW_REPO = "theholocron/.github";
|
|
1240
|
+
const WORKFLOW_REF = "main";
|
|
1241
|
+
function ref(name) {
|
|
1242
|
+
return `${WORKFLOW_REPO}/.github/workflows/${name}.yml@${WORKFLOW_REF}`;
|
|
1243
|
+
}
|
|
1244
|
+
/** Header prepended when holocron setup writes a thin caller to a repo. */
|
|
1245
|
+
const WORKFLOW_HEADER = `\
|
|
1246
|
+
# AUTO-GENERATED by holocron — do not edit directly.
|
|
1247
|
+
# Source: theholocron/holocron · packages/cli/src/commands/setup-workflows.ts
|
|
1248
|
+
# Run \`holocron setup\` to regenerate.
|
|
1249
|
+
|
|
1250
|
+
`;
|
|
1251
|
+
const WORKFLOW_TEMPLATES = {
|
|
1252
|
+
lint: `\
|
|
1253
|
+
name: Lint
|
|
1254
|
+
|
|
1255
|
+
on: # yamllint disable-line rule:truthy
|
|
1256
|
+
push:
|
|
1257
|
+
branches: [main, alpha]
|
|
1258
|
+
pull_request:
|
|
1259
|
+
|
|
1260
|
+
concurrency:
|
|
1261
|
+
group: lint-\${{ github.ref }}
|
|
1262
|
+
cancel-in-progress: true
|
|
1263
|
+
|
|
1264
|
+
permissions:
|
|
1265
|
+
contents: write
|
|
1266
|
+
statuses: write
|
|
1267
|
+
|
|
1268
|
+
jobs:
|
|
1269
|
+
lint:
|
|
1270
|
+
name: Lint
|
|
1271
|
+
uses: ${ref("lint")}
|
|
1272
|
+
secrets: inherit
|
|
1273
|
+
with:
|
|
1274
|
+
enable-auto-commit: true
|
|
1275
|
+
`,
|
|
1276
|
+
test: `\
|
|
1277
|
+
name: Test
|
|
1278
|
+
|
|
1279
|
+
on: # yamllint disable-line rule:truthy
|
|
1280
|
+
push:
|
|
1281
|
+
branches: [main, alpha]
|
|
1282
|
+
pull_request:
|
|
1283
|
+
|
|
1284
|
+
concurrency:
|
|
1285
|
+
group: test-\${{ github.ref }}
|
|
1286
|
+
cancel-in-progress: true
|
|
1287
|
+
|
|
1288
|
+
permissions:
|
|
1289
|
+
contents: read
|
|
1290
|
+
|
|
1291
|
+
jobs:
|
|
1292
|
+
test:
|
|
1293
|
+
name: Test
|
|
1294
|
+
uses: ${ref("test")}
|
|
1295
|
+
secrets: inherit
|
|
1296
|
+
`,
|
|
1297
|
+
typecheck: `\
|
|
1298
|
+
name: Typecheck
|
|
1299
|
+
|
|
1300
|
+
on: # yamllint disable-line rule:truthy
|
|
1301
|
+
push:
|
|
1302
|
+
branches: [main, alpha]
|
|
1303
|
+
pull_request:
|
|
1304
|
+
|
|
1305
|
+
concurrency:
|
|
1306
|
+
group: typecheck-\${{ github.ref }}
|
|
1307
|
+
cancel-in-progress: true
|
|
1308
|
+
|
|
1309
|
+
permissions:
|
|
1310
|
+
contents: read
|
|
1311
|
+
|
|
1312
|
+
jobs:
|
|
1313
|
+
typecheck:
|
|
1314
|
+
name: Typecheck
|
|
1315
|
+
uses: ${ref("typecheck")}
|
|
1316
|
+
secrets: inherit
|
|
1317
|
+
`,
|
|
1318
|
+
codeql: `\
|
|
1319
|
+
name: CodeQL
|
|
1320
|
+
|
|
1321
|
+
on: # yamllint disable-line rule:truthy
|
|
1322
|
+
push:
|
|
1323
|
+
branches:
|
|
1324
|
+
- main
|
|
1325
|
+
pull_request:
|
|
1326
|
+
branches:
|
|
1327
|
+
- main
|
|
1328
|
+
schedule:
|
|
1329
|
+
- cron: "0 0 * * 1"
|
|
1330
|
+
|
|
1331
|
+
permissions:
|
|
1332
|
+
actions: read
|
|
1333
|
+
contents: read
|
|
1334
|
+
security-events: write
|
|
1335
|
+
|
|
1336
|
+
jobs:
|
|
1337
|
+
codeql:
|
|
1338
|
+
uses: ${ref("codeql")}
|
|
1339
|
+
secrets: inherit
|
|
1340
|
+
`,
|
|
1341
|
+
review: `\
|
|
1342
|
+
name: Review
|
|
1343
|
+
|
|
1344
|
+
on: # yamllint disable-line rule:truthy
|
|
1345
|
+
pull_request:
|
|
1346
|
+
|
|
1347
|
+
concurrency:
|
|
1348
|
+
group: review-\${{ github.ref }}
|
|
1349
|
+
cancel-in-progress: true
|
|
1350
|
+
|
|
1351
|
+
permissions:
|
|
1352
|
+
contents: read
|
|
1353
|
+
checks: write
|
|
1354
|
+
pull-requests: write
|
|
1355
|
+
|
|
1356
|
+
jobs:
|
|
1357
|
+
review:
|
|
1358
|
+
name: Review
|
|
1359
|
+
uses: ${ref("review")}
|
|
1360
|
+
secrets: inherit
|
|
1361
|
+
`,
|
|
1362
|
+
release: `\
|
|
1363
|
+
name: Release
|
|
1364
|
+
|
|
1365
|
+
on: # yamllint disable-line rule:truthy
|
|
1366
|
+
push:
|
|
1367
|
+
branches:
|
|
1368
|
+
- main
|
|
1369
|
+
- alpha
|
|
1370
|
+
workflow_dispatch:
|
|
1371
|
+
|
|
1372
|
+
permissions:
|
|
1373
|
+
contents: write
|
|
1374
|
+
id-token: write
|
|
1375
|
+
issues: write
|
|
1376
|
+
pull-requests: write
|
|
1377
|
+
|
|
1378
|
+
concurrency:
|
|
1379
|
+
group: \${{ github.workflow }}-\${{ github.ref }}
|
|
1380
|
+
cancel-in-progress: false
|
|
1381
|
+
|
|
1382
|
+
jobs:
|
|
1383
|
+
release:
|
|
1384
|
+
uses: ${ref("release")}
|
|
1385
|
+
secrets: inherit
|
|
1386
|
+
`,
|
|
1387
|
+
stale: `\
|
|
1388
|
+
name: Stale
|
|
1389
|
+
|
|
1390
|
+
on: # yamllint disable-line rule:truthy
|
|
1391
|
+
schedule:
|
|
1392
|
+
- cron: "30 1 * * *"
|
|
1393
|
+
|
|
1394
|
+
permissions:
|
|
1395
|
+
contents: write
|
|
1396
|
+
issues: write
|
|
1397
|
+
pull-requests: write
|
|
1398
|
+
|
|
1399
|
+
jobs:
|
|
1400
|
+
stale:
|
|
1401
|
+
uses: ${ref("stale")}
|
|
1402
|
+
secrets: inherit
|
|
1403
|
+
`,
|
|
1404
|
+
greetings: `\
|
|
1405
|
+
name: Greetings
|
|
1406
|
+
|
|
1407
|
+
on: # yamllint disable-line rule:truthy
|
|
1408
|
+
pull_request:
|
|
1409
|
+
issues:
|
|
1410
|
+
|
|
1411
|
+
permissions:
|
|
1412
|
+
issues: write
|
|
1413
|
+
pull-requests: write
|
|
1414
|
+
|
|
1415
|
+
jobs:
|
|
1416
|
+
greetings:
|
|
1417
|
+
uses: ${ref("greetings")}
|
|
1418
|
+
secrets: inherit
|
|
1419
|
+
`,
|
|
1420
|
+
dependencies: `\
|
|
1421
|
+
name: Dependencies
|
|
1422
|
+
|
|
1423
|
+
on: # yamllint disable-line rule:truthy
|
|
1424
|
+
pull_request:
|
|
1425
|
+
|
|
1426
|
+
permissions:
|
|
1427
|
+
contents: write
|
|
1428
|
+
pull-requests: write
|
|
1429
|
+
|
|
1430
|
+
jobs:
|
|
1431
|
+
dependencies:
|
|
1432
|
+
uses: ${ref("dependencies")}
|
|
1433
|
+
secrets: inherit
|
|
1434
|
+
`,
|
|
1435
|
+
"bookkeeping-pr": `\
|
|
1436
|
+
name: PR Bookkeeping
|
|
1437
|
+
|
|
1438
|
+
on: # yamllint disable-line rule:truthy
|
|
1439
|
+
pull_request:
|
|
1440
|
+
types:
|
|
1441
|
+
- opened
|
|
1442
|
+
- edited
|
|
1443
|
+
|
|
1444
|
+
permissions:
|
|
1445
|
+
contents: read
|
|
1446
|
+
pull-requests: write
|
|
1447
|
+
|
|
1448
|
+
jobs:
|
|
1449
|
+
bookkeeping:
|
|
1450
|
+
uses: ${ref("bookkeeping-pr")}
|
|
1451
|
+
secrets: inherit
|
|
1452
|
+
`,
|
|
1453
|
+
audit: `\
|
|
1454
|
+
name: Audit
|
|
1455
|
+
|
|
1456
|
+
on: # yamllint disable-line rule:truthy
|
|
1457
|
+
push:
|
|
1458
|
+
branches: [main, alpha]
|
|
1459
|
+
pull_request:
|
|
1460
|
+
|
|
1461
|
+
permissions:
|
|
1462
|
+
contents: read
|
|
1463
|
+
|
|
1464
|
+
jobs:
|
|
1465
|
+
audit:
|
|
1466
|
+
uses: ${ref("audit")}
|
|
1467
|
+
secrets: inherit
|
|
1468
|
+
`,
|
|
1469
|
+
"sync-github": `\
|
|
1470
|
+
name: Sync GitHub Templates
|
|
1471
|
+
|
|
1472
|
+
on: # yamllint disable-line rule:truthy
|
|
1473
|
+
push:
|
|
1474
|
+
branches: [main, alpha]
|
|
1475
|
+
paths:
|
|
1476
|
+
- packages/cli/src/templates/index.ts
|
|
1477
|
+
- packages/cli/src/commands/setup-workflows.ts
|
|
1478
|
+
|
|
1479
|
+
concurrency:
|
|
1480
|
+
group: sync-github-\${{ github.ref }}
|
|
1481
|
+
cancel-in-progress: true
|
|
1482
|
+
|
|
1483
|
+
permissions:
|
|
1484
|
+
contents: read
|
|
1485
|
+
|
|
1486
|
+
jobs:
|
|
1487
|
+
sync:
|
|
1488
|
+
name: Sync
|
|
1489
|
+
uses: ${ref("sync-github")}
|
|
1490
|
+
with:
|
|
1491
|
+
secondary-repos: theholocron/.github-private
|
|
1492
|
+
secrets:
|
|
1493
|
+
SYNC_TOKEN: \${{ secrets.SYNC_TOKEN }}
|
|
1494
|
+
`
|
|
1495
|
+
};
|
|
1496
|
+
const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));
|
|
1497
|
+
//#endregion
|
|
1498
|
+
//#region src/commands/sync-github.ts
|
|
1499
|
+
const DEFAULT_REPO = "theholocron/.github";
|
|
1500
|
+
const API_BASE = "https://api.github.com";
|
|
1501
|
+
function reusableHeader(source) {
|
|
1502
|
+
return [
|
|
1503
|
+
`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,
|
|
1504
|
+
`# Source: theholocron/holocron · ${source}`,
|
|
1505
|
+
`# Synced: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
1506
|
+
`# Tool: holocron sync-github`,
|
|
1507
|
+
`# Changes: edit source in theholocron/holocron and push to alpha or main.`,
|
|
1508
|
+
``
|
|
1509
|
+
].join("\n");
|
|
1510
|
+
}
|
|
1511
|
+
function thinCallerHeader() {
|
|
1512
|
+
return [
|
|
1513
|
+
`# AUTO-GENERATED — do not edit in theholocron/.github directly.`,
|
|
1514
|
+
`# Source: theholocron/holocron · packages/cli/src/commands/setup-workflows.ts`,
|
|
1515
|
+
`# Synced: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
1516
|
+
`# Tool: holocron sync-github`,
|
|
1517
|
+
`# Changes: edit setup-workflows.ts in theholocron/holocron and push.`,
|
|
1518
|
+
``
|
|
1519
|
+
].join("\n");
|
|
1520
|
+
}
|
|
1521
|
+
function buildBatch(repo) {
|
|
1522
|
+
const files = [];
|
|
1523
|
+
if (repo === DEFAULT_REPO) for (const [name, content] of Object.entries(ACTIONS)) files.push({
|
|
1524
|
+
path: `.github/actions/${name}.yml`,
|
|
1525
|
+
content: reusableHeader(`packages/cli/src/templates/index.ts`) + content
|
|
1526
|
+
});
|
|
1527
|
+
for (const [name, content] of Object.entries(REUSABLE_WORKFLOWS)) files.push({
|
|
1528
|
+
path: `.github/workflows/${name}.yml`,
|
|
1529
|
+
content: reusableHeader(`packages/cli/src/templates/index.ts`) + content
|
|
1530
|
+
});
|
|
1531
|
+
for (const [name, content] of Object.entries(WORKFLOW_TEMPLATES)) files.push({
|
|
1532
|
+
path: `workflow-templates/${name}.yml`,
|
|
1533
|
+
content: thinCallerHeader() + content
|
|
1534
|
+
});
|
|
1535
|
+
return files;
|
|
1536
|
+
}
|
|
1537
|
+
async function runSyncGithub(input) {
|
|
1538
|
+
const print = input.print ?? ((line) => console.log(line));
|
|
1539
|
+
const repo = input.repo ?? DEFAULT_REPO;
|
|
1540
|
+
const [owner, repoName] = repo.split("/");
|
|
1541
|
+
const { token, dryRun = false, branch, createPr = false } = input;
|
|
1542
|
+
const message = input.message ?? `chore: sync from theholocron/holocron`;
|
|
1543
|
+
const fetchFn = input.fetch ?? globalThis.fetch;
|
|
1544
|
+
const headers = {
|
|
1545
|
+
Authorization: `Bearer ${token}`,
|
|
1546
|
+
Accept: "application/vnd.github+json",
|
|
1547
|
+
"Content-Type": "application/json",
|
|
1548
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1549
|
+
};
|
|
1550
|
+
print(`holocron sync-github${dryRun ? " (dry-run)" : ""}`);
|
|
1551
|
+
print(` repo: ${repo}`);
|
|
1552
|
+
if (branch) print(` branch: ${branch}`);
|
|
1553
|
+
print("");
|
|
1554
|
+
const batch = buildBatch(repo);
|
|
1555
|
+
let created = 0;
|
|
1556
|
+
let updated = 0;
|
|
1557
|
+
let unchanged = 0;
|
|
1558
|
+
for (const file of batch) {
|
|
1559
|
+
const ref = branch ? `?ref=${encodeURIComponent(branch)}` : "";
|
|
1560
|
+
const url = `${API_BASE}/repos/${owner}/${repoName}/contents/${file.path}`;
|
|
1561
|
+
const newContent = Buffer.from(file.content, "utf8").toString("base64");
|
|
1562
|
+
let existingSha;
|
|
1563
|
+
let existingContent;
|
|
1564
|
+
try {
|
|
1565
|
+
const getRes = await fetchFn(`${url}${ref}`, { headers });
|
|
1566
|
+
if (getRes.ok) {
|
|
1567
|
+
const data = await getRes.json();
|
|
1568
|
+
existingSha = data.sha;
|
|
1569
|
+
existingContent = data.content.replace(/\n/g, "");
|
|
1570
|
+
}
|
|
1571
|
+
} catch {}
|
|
1572
|
+
if (existingContent === newContent) {
|
|
1573
|
+
print(` · unchanged ${file.path}`);
|
|
1574
|
+
unchanged++;
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const verb = existingSha ? "updated " : "created ";
|
|
1578
|
+
if (dryRun) {
|
|
1579
|
+
print(` ~ ${verb} ${file.path}`);
|
|
1580
|
+
if (existingSha) updated++;
|
|
1581
|
+
else created++;
|
|
1582
|
+
continue;
|
|
1583
|
+
}
|
|
1584
|
+
const body = {
|
|
1585
|
+
message,
|
|
1586
|
+
content: newContent
|
|
1587
|
+
};
|
|
1588
|
+
if (existingSha) body.sha = existingSha;
|
|
1589
|
+
if (branch) body.branch = branch;
|
|
1590
|
+
const putRes = await fetchFn(url, {
|
|
1591
|
+
method: "PUT",
|
|
1592
|
+
headers,
|
|
1593
|
+
body: JSON.stringify(body)
|
|
1594
|
+
});
|
|
1595
|
+
if (!putRes.ok) {
|
|
1596
|
+
const err = await putRes.json();
|
|
1597
|
+
const msg = `failed to push ${file.path}: ${err.message ?? putRes.status}`;
|
|
1598
|
+
print(` ✗ ${msg}`);
|
|
1599
|
+
return {
|
|
1600
|
+
status: "fail",
|
|
1601
|
+
created,
|
|
1602
|
+
updated,
|
|
1603
|
+
unchanged,
|
|
1604
|
+
message: msg
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
print(` ✓ ${verb} ${file.path}`);
|
|
1608
|
+
if (existingSha) updated++;
|
|
1609
|
+
else created++;
|
|
1610
|
+
}
|
|
1611
|
+
const changed = created + updated;
|
|
1612
|
+
print("");
|
|
1613
|
+
print(` ${created} created, ${updated} updated, ${unchanged} unchanged`);
|
|
1614
|
+
let prUrl;
|
|
1615
|
+
if (branch && createPr && changed > 0 && !dryRun) {
|
|
1616
|
+
const prRes = await fetchFn(`${API_BASE}/repos/${owner}/${repoName}/pulls`, {
|
|
1617
|
+
method: "POST",
|
|
1618
|
+
headers,
|
|
1619
|
+
body: JSON.stringify({
|
|
1620
|
+
title: message,
|
|
1621
|
+
head: branch,
|
|
1622
|
+
base: "main",
|
|
1623
|
+
body: "Auto-generated by `holocron sync-github`. Review and merge to apply template updates."
|
|
1624
|
+
})
|
|
1625
|
+
});
|
|
1626
|
+
if (prRes.ok) {
|
|
1627
|
+
prUrl = (await prRes.json()).html_url;
|
|
1628
|
+
print(` → PR opened: ${prUrl}`);
|
|
1629
|
+
} else {
|
|
1630
|
+
const err = await prRes.json();
|
|
1631
|
+
if (err.errors?.some((e) => e.message.includes("already exists"))) print(` → PR already open for ${branch} — branch updated, ready to merge`);
|
|
1632
|
+
else print(` ⚠ PR creation failed: ${err.message ?? prRes.status}`);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return {
|
|
1636
|
+
status: dryRun ? "dry-run" : "ok",
|
|
1637
|
+
created,
|
|
1638
|
+
updated,
|
|
1639
|
+
unchanged,
|
|
1640
|
+
prUrl
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
//#endregion
|
|
449
1644
|
//#region src/commands/npm-publish-initial.ts
|
|
450
1645
|
/**
|
|
451
1646
|
* `holocron npm publish-initial` — bottles up the chicken-and-egg
|
|
@@ -1865,241 +3060,6 @@ function vaultProviderName(loader) {
|
|
|
1865
3060
|
return loader.get("vault").providerName;
|
|
1866
3061
|
}
|
|
1867
3062
|
//#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
3063
|
//#region src/commands/setup.ts
|
|
2104
3064
|
const DEPENDABOT_CONFIG = `\
|
|
2105
3065
|
# AUTO-GENERATED by holocron — run \`holocron setup\` to regenerate.
|
|
@@ -2653,7 +3613,36 @@ await yargs(hideBin(process.argv)).scriptName("holocron").usage("$0 <command> [o
|
|
|
2653
3613
|
dryRun: argv.dryRun,
|
|
2654
3614
|
...argv.otp ? { otp: argv.otp } : {}
|
|
2655
3615
|
})).status === "fail") process.exitCode = 1;
|
|
2656
|
-
}).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("
|
|
3616
|
+
}).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", {
|
|
3617
|
+
type: "string",
|
|
3618
|
+
default: "theholocron/.github",
|
|
3619
|
+
describe: "Target org/repo (default: theholocron/.github)"
|
|
3620
|
+
}).option("branch", {
|
|
3621
|
+
type: "string",
|
|
3622
|
+
describe: "Push to this branch instead of the default branch (enables PR-based workflow for protected repos)"
|
|
3623
|
+
}).option("pr", {
|
|
3624
|
+
type: "boolean",
|
|
3625
|
+
default: false,
|
|
3626
|
+
describe: "Open a PR after pushing to --branch (no-op without --branch)"
|
|
3627
|
+
}).option("message", {
|
|
3628
|
+
type: "string",
|
|
3629
|
+
describe: "Commit message (default: chore: sync from theholocron/holocron)"
|
|
3630
|
+
}), async (argv) => {
|
|
3631
|
+
const token = argv.token ?? process.env.GITHUB_TOKEN ?? process.env.HOLOCRON_GITHUB_TOKEN;
|
|
3632
|
+
if (!token) {
|
|
3633
|
+
console.error("sync-github: GitHub token required — pass --token or set GITHUB_TOKEN");
|
|
3634
|
+
process.exitCode = 1;
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
if ((await runSyncGithub({
|
|
3638
|
+
token,
|
|
3639
|
+
repo: argv.repo,
|
|
3640
|
+
dryRun: argv.dryRun,
|
|
3641
|
+
...argv.branch ? { branch: argv.branch } : {},
|
|
3642
|
+
...argv.pr ? { createPr: true } : {},
|
|
3643
|
+
...argv.message ? { message: argv.message } : {}
|
|
3644
|
+
})).status === "fail") process.exitCode = 1;
|
|
3645
|
+
}).command("config show", "Print the resolved holocron config", () => {}, async (argv) => {
|
|
2657
3646
|
const loaded = await loadConfig(argv.cwd);
|
|
2658
3647
|
console.log(JSON.stringify(loaded.resolved, null, 2));
|
|
2659
3648
|
}).command("plugin create <slug> <vendor>", "Scaffold a new @theholocron/holocron-plugin-<slug> package", (y) => y.positional("slug", {
|