@theholocron/cli 3.62.1 → 3.63.0
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/README.md +10 -2
- package/dist/cli.mjs +176 -69
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -192,8 +192,16 @@ Axiom shipping activates when a token (`HOLOCRON_AXIOM_TOKEN` / `AXIOM_TOKEN`
|
|
|
192
192
|
→ OS keyring `axiom.<org>` → `axiom`) **and** a dataset
|
|
193
193
|
(`HOLOCRON_AXIOM_DATASET` / `AXIOM_DATASET` → `log.axiom.dataset` in
|
|
194
194
|
`holocron.config`) both resolve; env vars win. The token is never read from a
|
|
195
|
-
config file.
|
|
196
|
-
|
|
195
|
+
config file. See the [logging guide](https://docs.theholocron.dev/holocron/logging/).
|
|
196
|
+
|
|
197
|
+
### Telemetry
|
|
198
|
+
|
|
199
|
+
The CLI reports on itself through three sinks: **Sentry** (errors), **Axiom**
|
|
200
|
+
(logs), and **PostHog** (anonymous usage analytics — command frequency,
|
|
201
|
+
duration, failure rates, keyed to a one-way `sha256(hostname + username)`
|
|
202
|
+
fingerprint). PostHog activates from `HOLOCRON_POSTHOG_PROJECT_TOKEN` → `POSTHOG_PROJECT_TOKEN`
|
|
203
|
+
→ a shipped ingest-only key (on by default). `HOLOCRON_TELEMETRY=false` disables
|
|
204
|
+
all three. See the [telemetry guide](https://docs.theholocron.dev/holocron/telemetry/).
|
|
197
205
|
|
|
198
206
|
## What's in here
|
|
199
207
|
|
package/dist/cli.mjs
CHANGED
|
@@ -13,14 +13,15 @@ import { createLogger, parseLogLevel, resolveAxiomFromEnv } from "@theholocron/l
|
|
|
13
13
|
import ora from "ora";
|
|
14
14
|
import chalk from "chalk";
|
|
15
15
|
import { execFile, execFileSync, spawnSync } from "node:child_process";
|
|
16
|
-
import { homedir } from "node:os";
|
|
16
|
+
import { homedir, hostname, userInfo } from "node:os";
|
|
17
17
|
import { access, copyFile, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
18
18
|
import { createHash } from "node:crypto";
|
|
19
19
|
import { generateReadme } from "@theholocron/components-doc/markdown";
|
|
20
20
|
import { getClients, getConfigs, getDocs, getPlugins, getSkills, getThemes, getUtils } from "@theholocron/registry-doc";
|
|
21
21
|
import { createGitHubClient } from "@theholocron/github-client";
|
|
22
|
-
import { promisify } from "node:util";
|
|
23
22
|
import * as Sentry from "@sentry/node";
|
|
23
|
+
import { PostHog } from "posthog-node";
|
|
24
|
+
import { promisify } from "node:util";
|
|
24
25
|
//#region src/env.ts
|
|
25
26
|
/** Singleton env for simple global lookups throughout the CLI. */
|
|
26
27
|
const env = createEnvLookup();
|
|
@@ -5960,6 +5961,168 @@ async function writeWorkflowFile(repoRoot, filename, content) {
|
|
|
5960
5961
|
await writeFile(join(dir, filename), content, "utf8");
|
|
5961
5962
|
}
|
|
5962
5963
|
//#endregion
|
|
5964
|
+
//#region src/telemetry.ts
|
|
5965
|
+
const FALLBACK_DSN = "https://95cbb72ad5636c94e119a5405ee8f55f@o4508238154104832.ingest.us.sentry.io/4511810950791168";
|
|
5966
|
+
/**
|
|
5967
|
+
* Resolve the Sentry DSN — the `errors` capability's self-contained
|
|
5968
|
+
* activation, per ADR-0007:
|
|
5969
|
+
*
|
|
5970
|
+
* HOLOCRON_SENTRY_DSN → SENTRY_DSN → built-in fallback
|
|
5971
|
+
*
|
|
5972
|
+
* A consumer repo with `SENTRY_DSN` set gets CLI errors routed to its own
|
|
5973
|
+
* project with no config. Opt out entirely with `HOLOCRON_TELEMETRY=false`.
|
|
5974
|
+
*/
|
|
5975
|
+
function resolveDsn() {
|
|
5976
|
+
return env.get("HOLOCRON_SENTRY_DSN") ?? env.get("SENTRY_DSN") ?? FALLBACK_DSN;
|
|
5977
|
+
}
|
|
5978
|
+
const FALLBACK_POSTHOG_PROJECT_TOKEN = "phc_AC4vFCvYzwnzmG7Vg5nEc3PZKZztoPyfKp4Lb9BbXcLK";
|
|
5979
|
+
const DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
5980
|
+
/**
|
|
5981
|
+
* Resolve the PostHog project key — mirrors {@link resolveDsn} and the
|
|
5982
|
+
* `HOLOCRON_AXIOM_TOKEN` / `AXIOM_TOKEN` pattern, per ADR-0008:
|
|
5983
|
+
*
|
|
5984
|
+
* HOLOCRON_POSTHOG_PROJECT_TOKEN → POSTHOG_PROJECT_TOKEN → built-in fallback
|
|
5985
|
+
*
|
|
5986
|
+
* `POSTHOG_PROJECT_TOKEN` is the vendor-native name a consumer repo sets (as a
|
|
5987
|
+
* plain variable, not a secret — the `phc_…` key is publishable) to route CLI
|
|
5988
|
+
* usage to its own project.
|
|
5989
|
+
*/
|
|
5990
|
+
function resolvePostHogKey() {
|
|
5991
|
+
return env.get("HOLOCRON_POSTHOG_PROJECT_TOKEN") ?? env.get("POSTHOG_PROJECT_TOKEN") ?? FALLBACK_POSTHOG_PROJECT_TOKEN;
|
|
5992
|
+
}
|
|
5993
|
+
function resolvePostHogHost() {
|
|
5994
|
+
return env.get("HOLOCRON_POSTHOG_HOST") ?? env.get("POSTHOG_HOST") ?? DEFAULT_POSTHOG_HOST;
|
|
5995
|
+
}
|
|
5996
|
+
function isEnabled() {
|
|
5997
|
+
return env.get("HOLOCRON_TELEMETRY") !== "false" && !env.get("NO_HOLOCRON_TELEMETRY");
|
|
5998
|
+
}
|
|
5999
|
+
const sentryEnabled = () => isEnabled() && resolveDsn() !== "";
|
|
6000
|
+
const posthogEnabled = () => isEnabled() && resolvePostHogKey() !== "";
|
|
6001
|
+
let posthog;
|
|
6002
|
+
let commandStartedAt = 0;
|
|
6003
|
+
let currentCommand = "unknown";
|
|
6004
|
+
/**
|
|
6005
|
+
* Anonymous, stable per-machine id — `sha256(hostname + username)` truncated
|
|
6006
|
+
* (ADR-0008). A one-way fingerprint: no raw hostname or username is ever
|
|
6007
|
+
* transmitted, and it is not personal data under this project's rule.
|
|
6008
|
+
*/
|
|
6009
|
+
function machineId() {
|
|
6010
|
+
try {
|
|
6011
|
+
return createHash("sha256").update(`${hostname()} ${userInfo().username}`).digest("hex").slice(0, 32);
|
|
6012
|
+
} catch {
|
|
6013
|
+
return "unknown";
|
|
6014
|
+
}
|
|
6015
|
+
}
|
|
6016
|
+
/** Properties every event carries, so any event can be pivoted to its Axiom trace. */
|
|
6017
|
+
function baseProps() {
|
|
6018
|
+
const runId = getRunId();
|
|
6019
|
+
return {
|
|
6020
|
+
command: currentCommand,
|
|
6021
|
+
ci: Boolean(env.get("CI")),
|
|
6022
|
+
...runId ? { runId } : {}
|
|
6023
|
+
};
|
|
6024
|
+
}
|
|
6025
|
+
/**
|
|
6026
|
+
* Capture a PostHog event. Runs every `properties` object through the same
|
|
6027
|
+
* token scrubber Sentry uses (defence-in-depth — values are controlled).
|
|
6028
|
+
*/
|
|
6029
|
+
function event(name, properties = {}) {
|
|
6030
|
+
if (!posthogEnabled() || !posthog) return;
|
|
6031
|
+
const merged = {
|
|
6032
|
+
...baseProps(),
|
|
6033
|
+
...properties
|
|
6034
|
+
};
|
|
6035
|
+
posthog.capture({
|
|
6036
|
+
distinctId: machineId(),
|
|
6037
|
+
event: name,
|
|
6038
|
+
properties: JSON.parse(redact(JSON.stringify(merged)))
|
|
6039
|
+
});
|
|
6040
|
+
}
|
|
6041
|
+
function init(version) {
|
|
6042
|
+
initSentry(version);
|
|
6043
|
+
initPostHog(version);
|
|
6044
|
+
}
|
|
6045
|
+
function initSentry(version) {
|
|
6046
|
+
if (!sentryEnabled()) return;
|
|
6047
|
+
Sentry.init({
|
|
6048
|
+
dsn: resolveDsn(),
|
|
6049
|
+
release: `holocron@${version}`,
|
|
6050
|
+
environment: env.get("CI") ? "ci" : "local",
|
|
6051
|
+
tracesSampleRate: 1,
|
|
6052
|
+
beforeSend: scrubError
|
|
6053
|
+
});
|
|
6054
|
+
Sentry.startSession();
|
|
6055
|
+
Sentry.setTag("os", process.platform);
|
|
6056
|
+
Sentry.setTag("node", process.version);
|
|
6057
|
+
Sentry.setTag("ci", String(Boolean(env.get("CI"))));
|
|
6058
|
+
}
|
|
6059
|
+
function initPostHog(version) {
|
|
6060
|
+
if (!posthogEnabled()) return;
|
|
6061
|
+
posthog = new PostHog(resolvePostHogKey(), { host: resolvePostHogHost() });
|
|
6062
|
+
posthog.identify({
|
|
6063
|
+
distinctId: machineId(),
|
|
6064
|
+
properties: {
|
|
6065
|
+
ci: Boolean(env.get("CI")),
|
|
6066
|
+
os: process.platform,
|
|
6067
|
+
node: process.version,
|
|
6068
|
+
cli: version,
|
|
6069
|
+
...env.get("HOLOCRON_ORG") ? { org: env.get("HOLOCRON_ORG") } : {}
|
|
6070
|
+
}
|
|
6071
|
+
});
|
|
6072
|
+
}
|
|
6073
|
+
let lastErrorType;
|
|
6074
|
+
/** Start a Sentry command span, or `undefined` when Sentry is off. */
|
|
6075
|
+
function startSpan(name) {
|
|
6076
|
+
if (!sentryEnabled()) return void 0;
|
|
6077
|
+
Sentry.setTag("command", name);
|
|
6078
|
+
return Sentry.startInactiveSpan({
|
|
6079
|
+
name,
|
|
6080
|
+
op: "holocron.command",
|
|
6081
|
+
forceTransaction: true
|
|
6082
|
+
});
|
|
6083
|
+
}
|
|
6084
|
+
function startCommand(name) {
|
|
6085
|
+
currentCommand = name;
|
|
6086
|
+
commandStartedAt = Date.now();
|
|
6087
|
+
lastErrorType = void 0;
|
|
6088
|
+
const span = startSpan(name);
|
|
6089
|
+
event("command_started", { dry_run: process.argv.includes("--dry-run") });
|
|
6090
|
+
return (ok) => {
|
|
6091
|
+
if (span) {
|
|
6092
|
+
span.setStatus({ code: ok ? 1 : 2 });
|
|
6093
|
+
span.end();
|
|
6094
|
+
}
|
|
6095
|
+
event(ok ? "command_completed" : "command_failed", {
|
|
6096
|
+
status: ok ? "ok" : "fail",
|
|
6097
|
+
duration_ms: Date.now() - commandStartedAt,
|
|
6098
|
+
...ok || !lastErrorType ? {} : { error_type: lastErrorType }
|
|
6099
|
+
});
|
|
6100
|
+
};
|
|
6101
|
+
}
|
|
6102
|
+
function captureException(err) {
|
|
6103
|
+
lastErrorType = err instanceof Error ? err.constructor.name : "Error";
|
|
6104
|
+
if (!sentryEnabled()) return;
|
|
6105
|
+
Sentry.captureException(err);
|
|
6106
|
+
}
|
|
6107
|
+
function endSession() {
|
|
6108
|
+
if (!sentryEnabled()) return;
|
|
6109
|
+
Sentry.endSession();
|
|
6110
|
+
}
|
|
6111
|
+
async function flush() {
|
|
6112
|
+
if (sentryEnabled()) await Sentry.close(2e3);
|
|
6113
|
+
if (posthog) {
|
|
6114
|
+
await posthog.shutdown();
|
|
6115
|
+
posthog = void 0;
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6118
|
+
const TOKEN_RE = /\b(ghp_|ghs_|glpat-|xoxb-|xoxp-|npm_|sk-|[A-Z][A-Z0-9_]{2,}_TOKEN[=\s])[^\s"]*/g;
|
|
6119
|
+
function redact(raw) {
|
|
6120
|
+
return raw.replace(TOKEN_RE, "[REDACTED]");
|
|
6121
|
+
}
|
|
6122
|
+
function scrubError(event, _hint) {
|
|
6123
|
+
return JSON.parse(redact(JSON.stringify(event)));
|
|
6124
|
+
}
|
|
6125
|
+
//#endregion
|
|
5963
6126
|
//#region src/templates/actions/auto-commit.yml
|
|
5964
6127
|
var auto_commit_default = "name: Auto Commit\ndescription: >\n Commit and push any file changes using stefanzweifel/git-auto-commit-action.\n If a branch name is provided and differs from the current branch, a new branch\n is created automatically.\n\ninputs:\n token:\n description: >\n GitHub token with push access to the target branch. Used to authenticate\n the git remote so the commit can be pushed.\n required: true\n branch:\n description: >\n Branch to commit to. Leave empty to commit to the current branch (useful\n in PR contexts). Provide an explicit name (e.g. chore/auto-sync) to push\n to a separate branch.\n required: false\n default: \"\"\n commit-message:\n description: Commit message.\n required: true\n commit-options:\n description: >\n Additional options passed to git commit (e.g. --no-verify).\n required: false\n default: \"\"\n commit-user-name:\n description: Git user.name for the commit.\n required: false\n default: \"github-actions[bot]\"\n commit-user-email:\n description: Git user.email for the commit.\n required: false\n default: \"41898282+github-actions[bot]@users.noreply.github.com\"\n commit-author:\n description: >\n Git author string in \"Name <email>\" format.\n required: false\n default: \"github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>\"\n\noutputs:\n changes-detected:\n description: \"'true' if any files were committed, 'false' otherwise.\"\n value: ${{ steps.commit.outputs.changes_detected }}\n\nruns:\n using: composite\n steps:\n - name: Configure git remote with token\n shell: bash\n run: |\n REMOTE_URL=$(git remote get-url origin)\n AUTHED_URL=$(echo \"$REMOTE_URL\" | sed \"s|https://|https://x-access-token:${TOKEN}@|\")\n git remote set-url origin \"$AUTHED_URL\"\n env:\n TOKEN: ${{ inputs.token }}\n\n - name: Reset branch to current HEAD\n if: ${{ inputs.branch != '' }}\n shell: bash\n run: git checkout -B \"$BRANCH\"\n env:\n BRANCH: ${{ inputs.branch }}\n\n - name: Build signed commit message\n id: msg\n shell: bash\n run: |\n TRAILER=\"Signed-off-by: ${COMMIT_USER_NAME} <${COMMIT_USER_EMAIL}>\"\n if echo \"$COMMIT_MESSAGE\" | grep -qF \"$TRAILER\"; then\n FINAL=\"$COMMIT_MESSAGE\"\n else\n FINAL=\"${COMMIT_MESSAGE}\"$'\\n\\n'\"${TRAILER}\"\n fi\n {\n echo \"value<<EOF_TRAILER\"\n printf '%s' \"$FINAL\"\n echo \"\"\n echo \"EOF_TRAILER\"\n } >> \"$GITHUB_OUTPUT\"\n env:\n COMMIT_MESSAGE: ${{ inputs.commit-message }}\n COMMIT_USER_NAME: ${{ inputs.commit-user-name }}\n COMMIT_USER_EMAIL: ${{ inputs.commit-user-email }}\n\n - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0\n id: commit\n with:\n branch: ${{ inputs.branch }}\n commit_message: ${{ steps.msg.outputs.value }}\n commit_options: ${{ inputs.commit-options }}\n commit_user_name: ${{ inputs.commit-user-name }}\n commit_user_email: ${{ inputs.commit-user-email }}\n commit_author: ${{ inputs.commit-author }}\n";
|
|
5965
6128
|
//#endregion
|
|
@@ -6006,13 +6169,13 @@ var security_default = "name: Security\n\non: # yamllint disable-line rule:truth
|
|
|
6006
6169
|
var stale_default = "name: Stale\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n days-before-stale:\n description: Days of inactivity before an issue or PR is marked stale (applies to both unless type-specific value is set)\n type: number\n required: false\n default: 30\n days-before-close:\n description: Days after stale label before closing (applies to both unless type-specific value is set)\n type: number\n required: false\n default: 5\n days-before-issue-stale:\n description: Days of inactivity before an issue is marked stale; overrides days-before-stale when set to a non-negative value\n type: number\n required: false\n default: -1\n days-before-issue-close:\n description: Days after stale label before closing an issue; overrides days-before-close when set to a non-negative value\n type: number\n required: false\n default: -1\n days-before-pr-stale:\n description: Days of inactivity before a PR is marked stale; overrides days-before-stale when set to a non-negative value\n type: number\n required: false\n default: -1\n days-before-pr-close:\n description: Days after stale label before closing a PR; overrides days-before-close when set to a non-negative value\n type: number\n required: false\n default: -1\n exempt-issue-labels:\n description: Comma-separated labels that exempt an issue from being marked stale\n type: string\n required: false\n default: \"in-progress,wip\"\n exempt-pr-labels:\n description: Comma-separated labels that exempt a PR from being marked stale\n type: string\n required: false\n default: \"\"\n exempt-all-issue-milestones:\n description: Issues assigned to any milestone are never marked stale\n type: boolean\n required: false\n default: true\n exempt-all-pr-milestones:\n description: PRs assigned to any milestone are never marked stale\n type: boolean\n required: false\n default: true\n exempt-all-issue-projects:\n description: Issues assigned to any project are never marked stale\n type: boolean\n required: false\n default: true\n exempt-all-pr-projects:\n description: PRs assigned to any project are never marked stale\n type: boolean\n required: false\n default: true\n\njobs:\n stale:\n name: Mark stale issues and pull requests\n permissions:\n contents: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0\n name: Run Stale\n with:\n close-issue-message: >\n This issue was closed because it has been stalled for\n ${{ inputs.days-before-close }} days with no activity.\n days-before-close: ${{ inputs.days-before-close }}\n days-before-issue-close: ${{ inputs.days-before-issue-close }}\n days-before-issue-stale: ${{ inputs.days-before-issue-stale }}\n days-before-pr-close: ${{ inputs.days-before-pr-close }}\n days-before-pr-stale: ${{ inputs.days-before-pr-stale }}\n days-before-stale: ${{ inputs.days-before-stale }}\n exempt-all-issue-milestones: ${{ inputs.exempt-all-issue-milestones }}\n exempt-all-issue-projects: ${{ inputs.exempt-all-issue-projects }}\n exempt-all-pr-milestones: ${{ inputs.exempt-all-pr-milestones }}\n exempt-all-pr-projects: ${{ inputs.exempt-all-pr-projects }}\n exempt-issue-labels: ${{ inputs.exempt-issue-labels }}\n exempt-pr-labels: ${{ inputs.exempt-pr-labels }}\n stale-issue-label: wontfix\n stale-issue-message: >\n This issue is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n stale-pr-label: wontfix\n stale-pr-message: >\n This PR is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n";
|
|
6007
6170
|
//#endregion
|
|
6008
6171
|
//#region src/templates/workflows/sync.yml
|
|
6009
|
-
var sync_default = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Sync repo from config\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Run holocron sync\n # Call the built entry directly — `pnpm exec holocron` relies on a\n # node_modules/.bin/holocron symlink that pnpm cannot create at install\n # time (dist/ does not exist yet), same as sync-github.yml.\n run: |\n if [ -n \"$STEPS\" ]; then\n # shellcheck disable=SC2086\n node packages/cli/dist/cli.mjs sync --steps $STEPS\n else\n node packages/cli/dist/cli.mjs sync\n fi\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n";
|
|
6172
|
+
var sync_default = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Sync repo from config\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: write\n pull-requests: write\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Run holocron sync\n # Call the built entry directly — `pnpm exec holocron` relies on a\n # node_modules/.bin/holocron symlink that pnpm cannot create at install\n # time (dist/ does not exist yet), same as sync-github.yml.\n run: |\n if [ -n \"$STEPS\" ]; then\n # shellcheck disable=SC2086\n node packages/cli/dist/cli.mjs sync --steps $STEPS\n else\n node packages/cli/dist/cli.mjs sync\n fi\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n branch: chore/auto-sync\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR if changes were committed\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync triggered by changes to config or package files. Merge to apply.\" \\\n --base main \\\n --head chore/auto-sync \\\n || echo \"PR already open — branch updated.\"\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n";
|
|
6010
6173
|
//#endregion
|
|
6011
6174
|
//#region src/templates/workflows/sync-dispatch.yml
|
|
6012
6175
|
var sync_dispatch_default = "name: Sync Dispatch\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n steps:\n description: >\n Sync steps to pass to each repo's sync.yml. Default is \"readme\"\n (only README marker blocks are updated).\n type: string\n required: false\n default: readme\n\npermissions:\n contents: read\n\njobs:\n broadcast:\n name: Broadcast sync to all repos\n runs-on: ubuntu-latest\n timeout-minutes: 15\n steps:\n - name: Dispatch sync to all repos with sync.yml\n run: |\n gh api /orgs/theholocron/repos --paginate --jq '.[].name' \\\n | while IFS= read -r repo; do\n gh api \"/repos/theholocron/$repo/contents/.github/workflows/sync.yml\" --silent 2>/dev/null || continue\n echo \"Dispatching sync to theholocron/$repo\"\n gh workflow run sync.yml \\\n --repo \"theholocron/$repo\" \\\n --field \"steps=$STEPS\" \\\n || echo \"Warning: could not dispatch to theholocron/$repo — skipping\"\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n STEPS: ${{ inputs.steps }}\n";
|
|
6013
6176
|
//#endregion
|
|
6014
6177
|
//#region src/templates/workflows/sync-github.yml
|
|
6015
|
-
var sync_github_default = "name: Sync workflow templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n";
|
|
6178
|
+
var sync_github_default = "name: Sync workflow templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# HOLOCRON_SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Actions: Read and write (dispatch workflow runs via gh workflow run)\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n HOLOCRON_SYNC_TOKEN:\n required: true\n HOLOCRON_READ_TOKEN:\n description: >\n Fine-grained PAT for read-only GitHub API calls (e.g. resolving git\n committer identity via `gh api user`). Falls back to HOLOCRON_SYNC_TOKEN.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for `gh` CLI calls. Used when neither\n HOLOCRON_READ_TOKEN nor HOLOCRON_SYNC_TOKEN is set.\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm build\n name: Build CLI\n\n - name: Cache actionlint\n id: cache-actionlint\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: /tmp/actionlint\n key: actionlint-v1.7.7-linux-amd64\n\n - name: Download actionlint\n if: steps.cache-actionlint.outputs.cache-hit != 'true'\n run: |\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$PRIMARY_REPO\" \"$SYNC_BRANCH\" 2>/dev/null || true\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n GH_TOKEN=\"$HOLOCRON_SYNC_TOKEN\" gh pr merge --auto --squash \\\n --repo \"$repo\" \"$SYNC_BRANCH\" 2>/dev/null || true\n done\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN || secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n";
|
|
6016
6179
|
//#endregion
|
|
6017
6180
|
//#region src/templates/workflows/tag.yml
|
|
6018
6181
|
var tag_default = "name: Tag\n\n# Release Please — fully automated tag and GitHub Release from Conventional Commits.\n# No package.json or npm publishing required. Operates in \"simple\" mode by default:\n# analyzes commits since the last tag, maintains a rolling Release PR, and creates\n# a tag + GitHub Release when that PR is merged.\n#\n# The calling repo must have two files at the root:\n# release-please-config.json — declares packages and release-type\n# .release-please-manifest.json — tracks the current version\n\non: # yamllint disable-line rule:truthy\n # Self-trigger: when this workflow lives in theholocron/.github itself,\n # push to main runs Release Please for that repo's own releases.\n push:\n branches:\n - main\n workflow_call:\n inputs:\n release-type:\n description: Release Please release type (simple, node, python, etc.)\n type: string\n required: false\n default: simple\n config-file:\n description: Path to release-please-config.json\n type: string\n required: false\n default: release-please-config.json\n manifest-file:\n description: Path to .release-please-manifest.json\n type: string\n required: false\n default: .release-please-manifest.json\n\njobs:\n tag:\n name: Tag release\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # v4.1.1\n name: Run Release Please\n with:\n release-type: ${{ inputs.release-type }}\n config-file: ${{ inputs.config-file }}\n manifest-file: ${{ inputs.manifest-file }}\n";
|
|
@@ -6146,6 +6309,14 @@ async function runSyncGithub(input) {
|
|
|
6146
6309
|
...r.message ? { reason: r.message } : {},
|
|
6147
6310
|
...r.prUrl ? { pr: r.prUrl } : {}
|
|
6148
6311
|
}, "sync-github: done");
|
|
6312
|
+
event("sync_github_run", {
|
|
6313
|
+
repo,
|
|
6314
|
+
status: r.status,
|
|
6315
|
+
...branch ? { branch } : {},
|
|
6316
|
+
repos_targeted: 1,
|
|
6317
|
+
files_changed: r.created + r.updated,
|
|
6318
|
+
pr_opened: Boolean(r.prUrl)
|
|
6319
|
+
});
|
|
6149
6320
|
return r;
|
|
6150
6321
|
};
|
|
6151
6322
|
if (input.outputDir) {
|
|
@@ -6631,70 +6802,6 @@ async function fileExists(path) {
|
|
|
6631
6802
|
}
|
|
6632
6803
|
}
|
|
6633
6804
|
//#endregion
|
|
6634
|
-
//#region src/telemetry.ts
|
|
6635
|
-
const FALLBACK_DSN = "https://95cbb72ad5636c94e119a5405ee8f55f@o4508238154104832.ingest.us.sentry.io/4511810950791168";
|
|
6636
|
-
/**
|
|
6637
|
-
* Resolve the Sentry DSN — the `errors` capability's self-contained
|
|
6638
|
-
* activation, per ADR-0007:
|
|
6639
|
-
*
|
|
6640
|
-
* HOLOCRON_SENTRY_DSN → SENTRY_DSN → built-in fallback
|
|
6641
|
-
*
|
|
6642
|
-
* A consumer repo with `SENTRY_DSN` set gets CLI errors routed to its own
|
|
6643
|
-
* project with no config. Opt out entirely with `HOLOCRON_TELEMETRY=false`.
|
|
6644
|
-
*/
|
|
6645
|
-
function resolveDsn() {
|
|
6646
|
-
return env.get("HOLOCRON_SENTRY_DSN") ?? env.get("SENTRY_DSN") ?? FALLBACK_DSN;
|
|
6647
|
-
}
|
|
6648
|
-
function isEnabled() {
|
|
6649
|
-
return !(env.get("HOLOCRON_TELEMETRY") === "false" || Boolean(env.get("NO_HOLOCRON_TELEMETRY"))) && resolveDsn() !== "";
|
|
6650
|
-
}
|
|
6651
|
-
function init(version) {
|
|
6652
|
-
if (!isEnabled()) return;
|
|
6653
|
-
Sentry.init({
|
|
6654
|
-
dsn: resolveDsn(),
|
|
6655
|
-
release: `holocron@${version}`,
|
|
6656
|
-
environment: env.get("CI") ? "ci" : "local",
|
|
6657
|
-
tracesSampleRate: 1,
|
|
6658
|
-
beforeSend: scrubError
|
|
6659
|
-
});
|
|
6660
|
-
Sentry.startSession();
|
|
6661
|
-
Sentry.setTag("os", process.platform);
|
|
6662
|
-
Sentry.setTag("node", process.version);
|
|
6663
|
-
Sentry.setTag("ci", String(Boolean(env.get("CI"))));
|
|
6664
|
-
}
|
|
6665
|
-
function startCommand(name) {
|
|
6666
|
-
if (!isEnabled()) return () => {};
|
|
6667
|
-
Sentry.setTag("command", name);
|
|
6668
|
-
const span = Sentry.startInactiveSpan({
|
|
6669
|
-
name,
|
|
6670
|
-
op: "holocron.command",
|
|
6671
|
-
forceTransaction: true
|
|
6672
|
-
});
|
|
6673
|
-
return (ok) => {
|
|
6674
|
-
span.setStatus({ code: ok ? 1 : 2 });
|
|
6675
|
-
span.end();
|
|
6676
|
-
};
|
|
6677
|
-
}
|
|
6678
|
-
function captureException(err) {
|
|
6679
|
-
if (!isEnabled()) return;
|
|
6680
|
-
Sentry.captureException(err);
|
|
6681
|
-
}
|
|
6682
|
-
function endSession() {
|
|
6683
|
-
if (!isEnabled()) return;
|
|
6684
|
-
Sentry.endSession();
|
|
6685
|
-
}
|
|
6686
|
-
async function flush() {
|
|
6687
|
-
if (!isEnabled()) return;
|
|
6688
|
-
await Sentry.close(2e3);
|
|
6689
|
-
}
|
|
6690
|
-
const TOKEN_RE = /\b(ghp_|ghs_|glpat-|xoxb-|xoxp-|npm_|sk-|[A-Z][A-Z0-9_]{2,}_TOKEN[=\s])[^\s"]*/g;
|
|
6691
|
-
function redact(raw) {
|
|
6692
|
-
return raw.replace(TOKEN_RE, "[REDACTED]");
|
|
6693
|
-
}
|
|
6694
|
-
function scrubError(event, _hint) {
|
|
6695
|
-
return JSON.parse(redact(JSON.stringify(event)));
|
|
6696
|
-
}
|
|
6697
|
-
//#endregion
|
|
6698
6805
|
//#region src/update-notifier.ts
|
|
6699
6806
|
const PACKAGE_NAME = "@theholocron/cli";
|
|
6700
6807
|
const CACHE_TTL_MS = 1440 * 60 * 1e3;
|
|
@@ -6887,12 +6994,12 @@ try {
|
|
|
6887
6994
|
describe: "Set the log level to error — suppress info and warn."
|
|
6888
6995
|
}).middleware((argv) => {
|
|
6889
6996
|
const name = argv._.slice(0, 2).join(" ") || "unknown";
|
|
6890
|
-
finishCommand = startCommand(name);
|
|
6891
6997
|
printRunId = Boolean(argv.debug || argv.verbose);
|
|
6892
6998
|
buildCliLogger(argv, {
|
|
6893
6999
|
command: name,
|
|
6894
7000
|
org: argv.org
|
|
6895
7001
|
});
|
|
7002
|
+
finishCommand = startCommand(name);
|
|
6896
7003
|
}).command("version", "Print the CLI version", () => {}, () => {
|
|
6897
7004
|
console.log(`holocron ${CLI_VERSION}`);
|
|
6898
7005
|
}).command("clone", "Clone all repos in a GitHub org as siblings under a single directory", (y) => y.option("org", {
|