@zgeoff/chex 0.0.2 → 0.0.3

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 CHANGED
@@ -80,7 +80,7 @@ skipped file back:
80
80
  `linguist-vendored`.
81
81
 
82
82
  `chex init` writes the `extends` line into `lefthook.yml` and adds a `check:docs` script of
83
- `chex prose length links` when the repo has none. A second run changes nothing.
83
+ `chex prose length links skill` when the repo has none. A second run changes nothing.
84
84
 
85
85
  ## The pre-push baseline
86
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zgeoff/chex",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Run each shared docs and repo check as one subcommand, with the lefthook pre-push baseline that calls them",
5
5
  "keywords": [
6
6
  "checks",
@@ -2,7 +2,7 @@ import { isRecord } from '@zgeoff/std';
2
2
 
3
3
  // The baseline's jobs run chex, the related tests through rig, and each job under diet's memory cap.
4
4
  export const baselinePackages = ['@zgeoff/chex', '@zgeoff/rig', '@zgeoff/diet'] as const;
5
- export const docsScript = 'chex prose length links';
5
+ export const docsScript = 'chex prose length links skill';
6
6
 
7
7
  export type PackageOutcome =
8
8
  | { readonly kind: 'missing'; readonly packages: readonly string[] }
@@ -0,0 +1,57 @@
1
+ import type { RunProgram } from './run-program.ts';
2
+
3
+ export type ChecksProfile = 'public' | 'private';
4
+
5
+ export interface ChecksProfileOptions {
6
+ readonly cwd: string;
7
+ readonly env: Readonly<Record<string, string | undefined>>;
8
+ readonly runProgram: RunProgram;
9
+ readonly writeError: (text: string) => void;
10
+ }
11
+
12
+ // bun-checks picks the profile from the repo's visibility, so a run that CHECKS_PROFILE gives no
13
+ // profile, such as a pre-push hook, asks GitHub for the same visibility.
14
+ export function readChecksProfile(
15
+ options: Readonly<ChecksProfileOptions>,
16
+ ): ChecksProfile | undefined {
17
+ const given = parseChecksProfile(options.env['CHECKS_PROFILE']);
18
+
19
+ if (given !== undefined) {
20
+ return given;
21
+ }
22
+
23
+ const visibility = readRepoVisibility(options);
24
+
25
+ if (visibility instanceof Error) {
26
+ options.writeError(
27
+ `workflows: the repo's visibility is unknown, so every rule applies: ${visibility.message}\n`,
28
+ );
29
+
30
+ return undefined;
31
+ }
32
+
33
+ return visibility;
34
+ }
35
+
36
+ function parseChecksProfile(value: string | undefined): ChecksProfile | undefined {
37
+ return value === 'public' || value === 'private' ? value : undefined;
38
+ }
39
+
40
+ const visibilityCommand = ['gh', 'repo', 'view', '--json', 'isPrivate', '--jq', '.isPrivate'];
41
+
42
+ function readRepoVisibility(options: Readonly<ChecksProfileOptions>): ChecksProfile | Error {
43
+ try {
44
+ const result = options.runProgram(visibilityCommand, { cwd: options.cwd, env: options.env });
45
+ const answer = result.stdout.trim();
46
+
47
+ if (result.exitCode === 0 && (answer === 'true' || answer === 'false')) {
48
+ return answer === 'true' ? 'private' : 'public';
49
+ }
50
+
51
+ return new Error(
52
+ `${visibilityCommand.join(' ')} exited ${result.exitCode}: ${result.stderr.trim() || answer}`,
53
+ );
54
+ } catch (error) {
55
+ return error instanceof Error ? error : new Error(String(error));
56
+ }
57
+ }
@@ -3,11 +3,11 @@ import { collectCommandNames } from './collect-command-names.ts';
3
3
  import { collectExpressionReferences } from './collect-expression-references.ts';
4
4
  import { findInstallCachePath } from './find-install-cache-path.ts';
5
5
  import { parseShellWords } from './parse-shell-words.ts';
6
+ import type { ChecksProfile } from './read-checks-profile.ts';
7
+ import { readChecksProfile } from './read-checks-profile.ts';
6
8
  import type { RunProgram } from './run-program.ts';
7
9
  import { runProgram } from './run-program.ts';
8
10
 
9
- export type ChecksProfile = 'public' | 'private';
10
-
11
11
  export interface WorkflowsCheckOptions {
12
12
  readonly cwd: string;
13
13
  readonly env: Readonly<Record<string, string | undefined>>;
@@ -15,7 +15,7 @@ export interface WorkflowsCheckOptions {
15
15
  // The workflow files to read, relative to the repo root; empty reads every one HEAD holds.
16
16
  readonly paths: readonly string[];
17
17
 
18
- // The bun-checks profile of the run; undefined when the check cannot see it, such as in a hook.
18
+ // The bun-checks profile of the run; undefined when it is unknown, which applies every rule.
19
19
  readonly profile: ChecksProfile | undefined;
20
20
 
21
21
  readonly runProgram: RunProgram;
@@ -552,7 +552,14 @@ export function runWorkflowsCommand(args: readonly string[]): number {
552
552
  cwd: process.cwd(),
553
553
  env: process.env,
554
554
  paths,
555
- profile: parseChecksProfile(process.env['CHECKS_PROFILE']),
555
+ profile: readChecksProfile({
556
+ cwd: process.cwd(),
557
+ env: process.env,
558
+ runProgram,
559
+ writeError: (text) => {
560
+ process.stderr.write(text);
561
+ },
562
+ }),
556
563
  runProgram,
557
564
  });
558
565
 
@@ -585,10 +592,6 @@ function parseCLIPaths(args: readonly string[]): string[] | Error {
585
592
  }
586
593
  }
587
594
 
588
- function parseChecksProfile(value: string | undefined): ChecksProfile | undefined {
589
- return value === 'public' || value === 'private' ? value : undefined;
590
- }
591
-
592
595
  // GitHub reads a workflow command's properties up to `,` and `::`, and its message up to a
593
596
  // newline, so each escapes its own characters.
594
597
  function formatAnnotation(finding: WorkflowFinding): string {