@checkstack/gitops-common 0.4.2 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # @checkstack/gitops-common
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b995afb: Surface per-variant config documentation for the `Automation` GitOps kind.
8
+
9
+ The GitOps editor and Kind Registry Browser now show the right config schema
10
+ for each automation trigger and provider action when authoring an
11
+ `Automation` YAML, mirroring how the `Healthcheck` kind documents its
12
+ strategy/collector configs:
13
+
14
+ - `triggers[].config` — one entry per registered trigger that declares a
15
+ `configSchema`, conditioned on the chosen `triggers[].event`.
16
+ - `actions[].config` — one entry per registered provider action,
17
+ conditioned on the chosen `actions[].action`.
18
+
19
+ New plugin-author contract on the entity kind registry:
20
+
21
+ - `@checkstack/gitops-common` / `@checkstack/gitops-backend`: add
22
+ `EntityKindRegistry.registerSpecSchemaDocumentationProvider(provider)`. The
23
+ provider is a thunk invoked on every `describeKinds()` (i.e. each time the
24
+ kind-browser RPC is queried), so the docs it returns reflect the current
25
+ state of whatever it reads — order-independent.
26
+
27
+ Why a lazy provider (and not the existing eager
28
+ `registerSpecSchemaDocumentation`): unlike Healthcheck, whose
29
+ strategy/collector registries are core services fully populated before any
30
+ plugin's `afterPluginsReady`, the automation trigger/action registries are
31
+ filled by other plugins across their `init` / `afterPluginsReady` phases with
32
+ no guaranteed ordering. Several plugins (catalog/maintenance/notification)
33
+ register their provider actions in their own `afterPluginsReady`, so the
34
+ previous one-shot eager registration snapshotted a half-populated (often
35
+ empty) registry and the Automation kind's "Additional Schemas" came up empty.
36
+ automation-backend now registers a provider instead, so trigger/action config
37
+ docs always reflect the fully-populated registries.
38
+
39
+ Documentation-only surface; no runtime reconcile behaviour changes.
40
+
41
+ ### Patch Changes
42
+
43
+ - 270ef29: Internal refactor: re-export the secret-name and `${{ secrets.NAME }}` template
44
+ helpers (`SECRET_NAME_REGEX`, `secretNameSchema`, `SECRET_TEMPLATE_REGEX`,
45
+ `secretTemplateSchema`, `collectSecretNames`, `SecretName`) from
46
+ `@checkstack/secrets-common`, which is now the single canonical source. No public
47
+ API or behavior change for consumers.
48
+ - Updated dependencies [b995afb]
49
+ - Updated dependencies [270ef29]
50
+ - Updated dependencies [270ef29]
51
+ - Updated dependencies [270ef29]
52
+ - Updated dependencies [270ef29]
53
+ - Updated dependencies [b995afb]
54
+ - @checkstack/secrets-common@0.1.0
55
+
3
56
  ## 0.4.2
4
57
 
5
58
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/gitops-common",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -9,14 +9,15 @@
9
9
  }
10
10
  },
11
11
  "dependencies": {
12
- "@checkstack/common": "0.11.0",
12
+ "@checkstack/common": "0.12.0",
13
+ "@checkstack/secrets-common": "0.0.1",
13
14
  "@orpc/contract": "^1.13.14",
14
15
  "zod": "^4.2.1"
15
16
  },
16
17
  "devDependencies": {
17
18
  "typescript": "^5.7.2",
18
19
  "@checkstack/tsconfig": "0.0.7",
19
- "@checkstack/scripts": "0.3.3"
20
+ "@checkstack/scripts": "0.3.4"
20
21
  },
21
22
  "scripts": {
22
23
  "typecheck": "tsgo -b",
@@ -154,6 +154,26 @@ export interface SpecSchemaDocumentation {
154
154
  }>;
155
155
  }
156
156
 
157
+ /**
158
+ * A lazy provider of spec-schema documentation. Invoked by the registry at
159
+ * describe time (when the kind-browser RPC is queried), NOT at registration
160
+ * time — so the returned entries reflect whatever state the provider reads
161
+ * at that moment.
162
+ *
163
+ * Use this when the documentation derives from registries that are populated
164
+ * across plugin lifecycle phases with no guaranteed ordering (e.g. the
165
+ * automation trigger/action registries, whose entries are contributed by
166
+ * other plugins in their `init` / `afterPluginsReady`). A one-shot eager
167
+ * `registerSpecSchemaDocumentation` call would snapshot a half-populated
168
+ * registry; a provider re-reads it every time.
169
+ */
170
+ export type SpecSchemaDocumentationProvider = () => Array<
171
+ {
172
+ apiVersion: string;
173
+ kind: string;
174
+ } & SpecSchemaDocumentation
175
+ >;
176
+
157
177
  /**
158
178
  * The registry interface exposed via the Extension Point.
159
179
  * Plugins call these methods during their `register()` phase.
@@ -174,4 +194,15 @@ export interface EntityKindRegistry {
174
194
  kind: string;
175
195
  } & SpecSchemaDocumentation,
176
196
  ): void;
197
+
198
+ /**
199
+ * Register a lazy provider of spec-schema documentation. The provider is
200
+ * invoked each time the kind registry is described, so the entries it
201
+ * returns always reflect the current state of whatever it reads. Prefer
202
+ * this over {@link registerSpecSchemaDocumentation} when the docs derive
203
+ * from registries populated with no guaranteed ordering.
204
+ */
205
+ registerSpecSchemaDocumentationProvider(
206
+ provider: SpecSchemaDocumentationProvider,
207
+ ): void;
177
208
  }
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ export {
24
24
  type EntityKindRegistry,
25
25
  type ReconcileContext,
26
26
  type SpecSchemaDocumentation,
27
+ type SpecSchemaDocumentationProvider,
27
28
  } from "./entity-kind-registry";
28
29
  export { gitopsAccess, gitopsAccessRules } from "./access";
29
30
  export { gitopsRoutes } from "./routes";
@@ -1,82 +1,16 @@
1
- import { z } from "zod";
2
-
3
1
  /**
4
- * Valid characters for a secret name: letters, digits, underscores, and hyphens.
5
- * This must stay in sync with the capture group in {@link SECRET_TEMPLATE_REGEX}.
6
- */
7
- export const SECRET_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
8
-
9
- /**
10
- * Zod schema for validating secret names at creation time.
11
- * Ensures the name can be referenced via `${{ secrets.NAME }}`.
12
- */
13
- export const secretNameSchema = z
14
- .string()
15
- .min(1)
16
- .max(63)
17
- .regex(
18
- SECRET_NAME_REGEX,
19
- "Secret names must start with a letter and contain only letters, digits, underscores, or hyphens",
20
- );
21
-
22
- /**
23
- * Regex matching ${{ secrets.NAME }} template expressions in strings.
24
- * Captures the secret name in group 1.
25
- * Supports multiple occurrences within a single string value.
26
- *
27
- * @example
28
- * "${{ secrets.DB_PASS }}" → captures "DB_PASS"
29
- * "postgres://u:${{ secrets.PASS }}@${{ secrets.HOST }}/db" → captures "PASS", "HOST"
30
- */
31
- export const SECRET_TEMPLATE_REGEX =
32
- /\$\{\{\s*secrets\.([a-zA-Z0-9_-]+)\s*\}\}/g;
33
-
34
- /**
35
- * Zod schema for validating secret template strings.
36
- * Matches strings containing at least one ${{ secrets.NAME }} pattern.
37
- */
38
- export const secretTemplateSchema = z.string().regex(
39
- /\$\{\{\s*secrets\.[a-zA-Z0-9_-]+\s*\}\}/,
40
- "Must contain a ${{ secrets.NAME }} reference",
41
- );
42
-
43
- /**
44
- * Recursively walks a value and collects all unique secret names
45
- * referenced via ${{ secrets.NAME }} patterns in string values.
2
+ * Secret-name + `${{ secrets.NAME }}` template helpers.
46
3
  *
47
- * @returns Deduplicated array of secret names found in the value tree
4
+ * The canonical definitions live in `@checkstack/secrets-common` (the secrets
5
+ * platform owns this concern). This module re-exports them so existing
6
+ * `@checkstack/gitops-common` consumers keep their import paths unchanged and
7
+ * there is a single source of truth (no drift between two copies).
48
8
  */
49
- export function collectSecretNames(params: { value: unknown }): string[] {
50
- const names = new Set<string>();
51
- collectFromValue(params.value, names);
52
- return [...names];
53
- }
54
-
55
- function collectFromValue(value: unknown, names: Set<string>): void {
56
- if (value === null || value === undefined) {
57
- return;
58
- }
59
-
60
- if (typeof value === "string") {
61
- // Reset regex lastIndex for safe reuse (global flag)
62
- SECRET_TEMPLATE_REGEX.lastIndex = 0;
63
- let match: RegExpExecArray | null;
64
- while ((match = SECRET_TEMPLATE_REGEX.exec(value)) !== null) {
65
- names.add(match[1]);
66
- }
67
- return;
68
- }
69
-
70
- if (Array.isArray(value)) {
71
- for (const item of value) {
72
- collectFromValue(item, names);
73
- }
74
- return;
75
- }
76
-
77
- if (typeof value === "object") {
78
- for (const val of Object.values(value)) {
79
- collectFromValue(val, names);
80
- }
81
- }
82
- }
9
+ export {
10
+ SECRET_NAME_REGEX,
11
+ secretNameSchema,
12
+ SECRET_TEMPLATE_REGEX,
13
+ secretTemplateSchema,
14
+ collectSecretNames,
15
+ type SecretName,
16
+ } from "@checkstack/secrets-common";
package/tsconfig.json CHANGED
@@ -6,6 +6,9 @@
6
6
  "references": [
7
7
  {
8
8
  "path": "../common"
9
+ },
10
+ {
11
+ "path": "../secrets-common"
9
12
  }
10
13
  ]
11
14
  }