@gaia-ai/addon-deployment 0.9.2 → 0.11.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.
@@ -9,10 +9,27 @@ export interface GatherResult {
9
9
  }>;
10
10
  unresolved: string[];
11
11
  }
12
- /** Deduped GAIA-nnn from a git log, in first-seen order. */
12
+ /**
13
+ * Deduped ticket identifiers from a git log, in first-seen order — for any
14
+ * project key, not just `GAIA` (GAIA-392 AC-2).
15
+ *
16
+ * The parse admits *keys*, not tokens, in two passes: a key is admitted where
17
+ * it stands in one of the anchored positions above, and every identifier whose
18
+ * key was admitted is then collected — anchored or bare.
19
+ *
20
+ * The second pass is not optional: of the last 300 commits on `develop` only
21
+ * two carry a `ref:` trailer, the rest name the ticket in the subject, and a
22
+ * bare `GAIA-135` in a body is a real reference. What the rule gives up is one
23
+ * residual case — a delta in which a key appears *only* in bare mid-prose form,
24
+ * anchored nowhere, yields nothing for that key. That is the deliberate trade:
25
+ * such a token is indistinguishable from `AC-1` without hardcoding a project
26
+ * key, which is the defect this replaces. The cheap direction is the other one,
27
+ * a wrongly admitted key, because it surfaces in `unresolved` rather than as a
28
+ * wrong ticket.
29
+ */
13
30
  export declare function parseIdentifiers(gitLog: string): string[];
14
31
  /**
15
- * Compute the release batch from a git-log delta: parse GAIA-nnn identifiers and
32
+ * Compute the release batch from a git-log delta: parse ticket identifiers and
16
33
  * resolve each to a ticket. Unresolved identifiers are reported, never fatal
17
34
  * (the resolver returning null is not an error) — GAIA-153 AC-2.
18
35
  */
@@ -1,18 +1,79 @@
1
1
  import { exec } from '@gaia-ai/core';
2
- /** Deduped GAIA-nnn from a git log, in first-seen order. */
2
+ /**
3
+ * An identifier's shape: a project key plus its number. A key is validated as
4
+ * `/^[A-Z][A-Z0-9]{1,9}$/` and never contains a hyphen (`GaiaProject`), so this
5
+ * is the whole grammar — and it is also the shape of prose like `AC-1`,
6
+ * `UTF-8` or `SHA-256`, which is why matching it alone is not enough.
7
+ */
8
+ const IDENTIFIER = '[A-Z][A-Z0-9]{1,9}-\\d+';
9
+ /**
10
+ * What may precede a subject: the `%x1e` record separator and the abbreviated
11
+ * or full commit hash that `gaia deployment tickets` asks `git log` to print in
12
+ * front of `%s`. Both optional, so a bare subject line anchors too.
13
+ */
14
+ const SUBJECT_HEAD = '^\\x1e?(?:[0-9a-f]{2,40} )?';
15
+ /**
16
+ * The three positions in which an identifier can only be a ticket reference,
17
+ * and which therefore admit its project key:
18
+ *
19
+ * 1. the `ref:` trailer the commit convention prescribes — `ref:SHOP-42`;
20
+ * 2. a conventional-commit scope — `feat(GAIA-134): …`;
21
+ * 3. the head of a subject line — `GAIA-375: …`, the legacy form 298 of the
22
+ * last 300 commits on `develop` use.
23
+ *
24
+ * Positions 2 and 3 are deliberately anchored to the head of a line rather than
25
+ * to "any token before a colon" or "any parenthesised token": a body bullet
26
+ * `- AC-2: …` and a body line `(AC-5): parent = …` are exactly those two
27
+ * shapes, and both occur in this repository's real history. Admitting `AC` from
28
+ * them puts six phantom identifiers into a 300-commit release batch.
29
+ */
30
+ const ANCHORED = new RegExp([
31
+ `ref:[ \\t]*(${IDENTIFIER})\\b`,
32
+ `${SUBJECT_HEAD}[a-z]+!?\\((${IDENTIFIER})\\):`,
33
+ `${SUBJECT_HEAD}(${IDENTIFIER}):`,
34
+ ].join('|'), 'gm');
35
+ /**
36
+ * Deduped ticket identifiers from a git log, in first-seen order — for any
37
+ * project key, not just `GAIA` (GAIA-392 AC-2).
38
+ *
39
+ * The parse admits *keys*, not tokens, in two passes: a key is admitted where
40
+ * it stands in one of the anchored positions above, and every identifier whose
41
+ * key was admitted is then collected — anchored or bare.
42
+ *
43
+ * The second pass is not optional: of the last 300 commits on `develop` only
44
+ * two carry a `ref:` trailer, the rest name the ticket in the subject, and a
45
+ * bare `GAIA-135` in a body is a real reference. What the rule gives up is one
46
+ * residual case — a delta in which a key appears *only* in bare mid-prose form,
47
+ * anchored nowhere, yields nothing for that key. That is the deliberate trade:
48
+ * such a token is indistinguishable from `AC-1` without hardcoding a project
49
+ * key, which is the defect this replaces. The cheap direction is the other one,
50
+ * a wrongly admitted key, because it surfaces in `unresolved` rather than as a
51
+ * wrong ticket.
52
+ */
3
53
  export function parseIdentifiers(gitLog) {
54
+ const admitted = new Set();
55
+ for (const [, trailer, scope, subject] of gitLog.matchAll(ANCHORED)) {
56
+ const identifier = trailer ?? scope ?? subject;
57
+ if (identifier !== undefined) {
58
+ admitted.add(keyOf(identifier));
59
+ }
60
+ }
4
61
  const seen = new Set();
5
62
  const out = [];
6
- for (const m of gitLog.matchAll(/\bGAIA-\d+\b/g)) {
7
- if (!seen.has(m[0])) {
8
- seen.add(m[0]);
9
- out.push(m[0]);
63
+ for (const [identifier] of gitLog.matchAll(new RegExp(`\\b${IDENTIFIER}\\b`, 'g'))) {
64
+ if (admitted.has(keyOf(identifier)) && !seen.has(identifier)) {
65
+ seen.add(identifier);
66
+ out.push(identifier);
10
67
  }
11
68
  }
12
69
  return out;
13
70
  }
71
+ /** An identifier's project key — everything left of its `-<number>`. */
72
+ function keyOf(identifier) {
73
+ return identifier.slice(0, identifier.indexOf('-'));
74
+ }
14
75
  /**
15
- * Compute the release batch from a git-log delta: parse GAIA-nnn identifiers and
76
+ * Compute the release batch from a git-log delta: parse ticket identifiers and
16
77
  * resolve each to a ticket. Unresolved identifiers are reported, never fatal
17
78
  * (the resolver returning null is not an error) — GAIA-153 AC-2.
18
79
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaia-ai/addon-deployment",
3
- "version": "0.9.2",
3
+ "version": "0.11.0",
4
4
  "description": "GAIA deployment command plugin: `gaia deployment tickets` — the release batch computed from a git-log range.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "commander": "^12.1.0"
24
24
  },
25
25
  "peerDependencies": {
26
- "@gaia-ai/conductor": "^0.9.2",
27
- "@gaia-ai/core": "^0.9.2"
26
+ "@gaia-ai/conductor": "^0.11.0",
27
+ "@gaia-ai/core": "^0.11.0"
28
28
  }
29
29
  }