@intentius/chant 0.105.1 → 0.106.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/dist/change-set.d.ts +30 -8
- package/dist/change-set.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/pr.d.ts +16 -2
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +7 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/changed-files.d.ts +8 -2
- package/dist/components/changed-files.d.ts.map +1 -1
- package/dist/components/fan-out-record.d.ts +24 -0
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/pr-pipeline.d.ts +67 -4
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-run.d.ts +94 -3
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/gated-waves.d.ts +4 -1
- package/dist/gated-waves.d.ts.map +1 -1
- package/dist/lexicon.d.ts +13 -2
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/op/gate-name.d.ts +7 -0
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-summary.d.ts +2 -0
- package/dist/op/gate-summary.d.ts.map +1 -1
- package/dist/op/gate.d.ts +10 -2
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/index.d.ts +2 -2
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +2 -2
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +29 -4
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/pr-loop.d.ts +32 -6
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade-cli.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.d.ts +15 -1
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +1 -1
- package/src/__fixtures__/change-set/warden.change-set.golden.json +2 -2
- package/src/__fixtures__/change-set/warden.plan.json +47 -40
- package/src/__fixtures__/plan-summary/normalization-vectors.json +275 -2
- package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +1 -1
- package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +2 -2
- package/src/__fixtures__/pr-loop/pr-plan.golden.json +2 -2
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +2 -2
- package/src/build.test.ts +1 -1
- package/src/build.ts +1 -1
- package/src/change-set.test.ts +42 -12
- package/src/change-set.ts +50 -11
- package/src/cli/commands/build.ts +33 -14
- package/src/cli/commands/lint.ts +34 -1
- package/src/cli/handlers/build-lexicon-output.test.ts +102 -0
- package/src/cli/handlers/build.ts +68 -0
- package/src/cli/handlers/fan-out.test.ts +12 -1
- package/src/cli/handlers/fan-out.ts +7 -3
- package/src/cli/handlers/operator.ts +1 -2
- package/src/cli/handlers/pr.ts +223 -35
- package/src/cli/handlers/promote.test.ts +15 -1
- package/src/cli/handlers/promote.ts +5 -3
- package/src/cli/handlers/run.test.ts +215 -1
- package/src/cli/handlers/run.ts +36 -15
- package/src/cli/main.ts +13 -1
- package/src/cli/mcp/never-over-mcp.test.ts +120 -0
- package/src/cli/mcp/op-approve-origin.test.ts +1 -1
- package/src/cli/mcp/op-tools.ts +14 -2
- package/src/cli/mcp/server.test.ts +2 -1
- package/src/cli/registry.ts +7 -0
- package/src/components/changed-files.test.ts +58 -0
- package/src/components/changed-files.ts +19 -4
- package/src/components/fan-out-record.test.ts +47 -2
- package/src/components/fan-out-record.ts +53 -0
- package/src/components/pr-pipeline.ts +96 -6
- package/src/components/pr-run.test.ts +311 -4
- package/src/components/pr-run.ts +198 -5
- package/src/gated-waves.test.ts +11 -0
- package/src/gated-waves.ts +7 -2
- package/src/lexicon.ts +13 -1
- package/src/lifecycle/gate-ledger.ts +4 -3
- package/src/op/gate-name.ts +17 -0
- package/src/op/gate-summary.test.ts +12 -0
- package/src/op/gate-summary.ts +3 -1
- package/src/op/gate.test.ts +15 -1
- package/src/op/gate.ts +21 -4
- package/src/op/index.ts +2 -2
- package/src/op/local-executor.test.ts +35 -0
- package/src/op/local-executor.ts +2 -2
- package/src/op/local-output.test.ts +20 -0
- package/src/op/local-output.ts +4 -4
- package/src/op/runtime.ts +31 -4
- package/src/op/runtimes/local.test.ts +15 -0
- package/src/op/runtimes/local.ts +3 -1
- package/src/pr-loop.test.ts +41 -1
- package/src/pr-loop.ts +41 -10
- package/src/workspace/change-set.schema.json +1 -1
- package/src/workspace/lineage-upgrade-cli.ts +4 -3
- package/src/workspace/lineage-upgrade.test.ts +40 -0
- package/src/workspace/member-pipeline.test.ts +28 -0
- package/src/workspace/member-pipeline.ts +21 -3
- package/src/workspace/pr-report.schema.json +14 -1
|
@@ -67,8 +67,11 @@ export declare function memberPipelineDir(provider: string): string | undefined;
|
|
|
67
67
|
* The default path of a member's component pipeline for one environment,
|
|
68
68
|
* relative to the repository root: `chant-<member>-<env>.yml` in the forge's
|
|
69
69
|
* workflow directory, or `.gitlab/ci/chant-<member>-<env>.gitlab-ci.yml`.
|
|
70
|
+
* A pull-request pipeline (`kind` `"pr"`, #3465) is `chant-pr.<member>.<env>`, with the dots the apply group uses so no
|
|
71
|
+
* two member and environment pairs share one name, and it sits beside the
|
|
72
|
+
* member's deploy pipeline for the same environment.
|
|
70
73
|
*/
|
|
71
|
-
export declare function memberPipelineFile(provider: string, member: string, env: string): string | undefined;
|
|
74
|
+
export declare function memberPipelineFile(provider: string, member: string, env: string, kind?: "components" | "pr"): string | undefined;
|
|
72
75
|
/** A repository-relative path for an absolute one. */
|
|
73
76
|
export declare function repoRelative(ctx: MemberContext, absolute: string): string;
|
|
74
77
|
/** Read a member's generated-file record, or an empty one. */
|
|
@@ -107,6 +110,17 @@ export interface ComponentPlanInput {
|
|
|
107
110
|
output?: string;
|
|
108
111
|
params?: string[];
|
|
109
112
|
paramsFile?: string;
|
|
113
|
+
/** `--pr-loop`, with its `--gate` and `--branch` (#3465). */
|
|
114
|
+
prLoop?: {
|
|
115
|
+
gate?: string;
|
|
116
|
+
branch?: string;
|
|
117
|
+
};
|
|
118
|
+
/** `--wave-gate` with its `--canary` and `--base` (#3049). */
|
|
119
|
+
waveGate?: {
|
|
120
|
+
gate: string;
|
|
121
|
+
canary?: string[];
|
|
122
|
+
base?: string;
|
|
123
|
+
};
|
|
110
124
|
}
|
|
111
125
|
/**
|
|
112
126
|
* Plan a member's component pipeline: which member, which file and which
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member-pipeline.d.ts","sourceRoot":"","sources":["../../src/workspace/member-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAA+E,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAG3I;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAqBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,aAAa,GAAG,SAAS,CA0B9G;AAUD,gJAAgJ;AAChJ,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEtE;AAED
|
|
1
|
+
{"version":3,"file":"member-pipeline.d.ts","sourceRoot":"","sources":["../../src/workspace/member-pipeline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://intentius.io/chant/schemas/workspace/change-set/v1/change-set.schema.json",
|
|
3
3
|
"contract": 1,
|
|
4
|
-
"digest": "jcs1-sha256:
|
|
4
|
+
"digest": "jcs1-sha256:a66846faed3900cffc37cfa1c31d2735358875375b7218faa7c605502a17a529",
|
|
5
5
|
"members": [
|
|
6
6
|
{
|
|
7
7
|
"member": "delivery",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://intentius.io/chant/schemas/workspace/change-set/v1/change-set.schema.json",
|
|
3
3
|
"contract": 1,
|
|
4
|
-
"digest": "jcs1-sha256:
|
|
4
|
+
"digest": "jcs1-sha256:266dbcb79b7922940f2b18bae4bebda8418422d4a5539eeeed119759694bd3a3",
|
|
5
5
|
"members": [
|
|
6
6
|
{
|
|
7
7
|
"member": "warden",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"planner": "warden",
|
|
10
10
|
"scope": "acme",
|
|
11
11
|
"status": "planned",
|
|
12
|
-
"planDigest": "jcs1-sha256:
|
|
12
|
+
"planDigest": "jcs1-sha256:0ae7141f1c5543916126f5162bd2ce3c9d3f240155b6b9965886280a9fc56e62",
|
|
13
13
|
"holes": []
|
|
14
14
|
}
|
|
15
15
|
],
|
|
@@ -1,44 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"org": "acme",
|
|
4
|
+
"entries": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "delete",
|
|
7
|
+
"resourceType": "team",
|
|
8
|
+
"key": "contractors",
|
|
9
|
+
"before": {
|
|
10
|
+
"privacy": "closed",
|
|
11
|
+
"description": "Old contractors"
|
|
12
|
+
},
|
|
13
|
+
"verb": "membership"
|
|
11
14
|
},
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
+
{
|
|
16
|
+
"kind": "update",
|
|
17
|
+
"resourceType": "team",
|
|
18
|
+
"key": "platform",
|
|
19
|
+
"before": {
|
|
20
|
+
"privacy": "secret",
|
|
21
|
+
"description": "Platform team"
|
|
22
|
+
},
|
|
23
|
+
"after": {
|
|
24
|
+
"privacy": "closed",
|
|
25
|
+
"description": "Platform team"
|
|
26
|
+
},
|
|
27
|
+
"fields": [
|
|
28
|
+
{
|
|
29
|
+
"field": "privacy",
|
|
30
|
+
"before": "secret",
|
|
31
|
+
"after": "closed"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"verb": "membership"
|
|
15
35
|
},
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"kind": "create",
|
|
26
|
-
"resourceType": "team",
|
|
27
|
-
"key": "release",
|
|
28
|
-
"after": {
|
|
29
|
-
"privacy": "secret",
|
|
30
|
-
"description": "Release managers"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"kind": "delete",
|
|
35
|
-
"resourceType": "team",
|
|
36
|
-
"key": "contractors",
|
|
37
|
-
"before": {
|
|
38
|
-
"privacy": "closed",
|
|
39
|
-
"description": "Old contractors"
|
|
36
|
+
{
|
|
37
|
+
"kind": "create",
|
|
38
|
+
"resourceType": "team",
|
|
39
|
+
"key": "release",
|
|
40
|
+
"after": {
|
|
41
|
+
"privacy": "secret",
|
|
42
|
+
"description": "Release managers"
|
|
43
|
+
},
|
|
44
|
+
"verb": "membership"
|
|
40
45
|
}
|
|
46
|
+
],
|
|
47
|
+
"managedCounts": {
|
|
48
|
+
"team": 2
|
|
41
49
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
"Each repo keeps its own grouping code and runs every row in CI.",
|
|
6
6
|
"rootPairs: a and b are two roots of a choudoufu live-plan-set -json document; summarize a set holding exactly the two, and they must land in one group iff group is true.",
|
|
7
7
|
"instancePairs: a and b are two resource_changes of one terraform show -json plan; summarize that plan, and the two instances must land in one group iff group is true.",
|
|
8
|
-
"Red first: a naive grouper (equal raw resource_changes) must fail every rootPairs row with group true, and a grouper that blanks every string value in before and after must falsely group exactly the rootPairs rows named in overEagerFalselyGroups."
|
|
8
|
+
"Red first: a naive grouper (equal raw resource_changes) must fail every rootPairs row with group true, and a grouper that blanks every string value in before and after must falsely group exactly the rootPairs rows named in overEagerFalselyGroups.",
|
|
9
|
+
"sensitive attribute: chant's change-set carries no value for an attribute marked in before_sensitive or after_sensitive, so two sensitive attributes group by path alone, and a sensitive attribute never groups with an unmarked one. read entry: a data source read carries no attributes, so reads of one address group whatever they returned."
|
|
9
10
|
],
|
|
10
11
|
"rootPairs": [
|
|
11
12
|
{
|
|
@@ -1379,6 +1380,277 @@
|
|
|
1379
1380
|
]
|
|
1380
1381
|
}
|
|
1381
1382
|
}
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
"name": "sensitive attribute with different values",
|
|
1386
|
+
"group": true,
|
|
1387
|
+
"a": {
|
|
1388
|
+
"root": "roots/acme",
|
|
1389
|
+
"estate": "acme",
|
|
1390
|
+
"status": "planned",
|
|
1391
|
+
"plan": {
|
|
1392
|
+
"format_version": "1.2",
|
|
1393
|
+
"resource_changes": [
|
|
1394
|
+
{
|
|
1395
|
+
"address": "aws_db_instance.main",
|
|
1396
|
+
"change": {
|
|
1397
|
+
"actions": [
|
|
1398
|
+
"update"
|
|
1399
|
+
],
|
|
1400
|
+
"before": {
|
|
1401
|
+
"password": "old-a",
|
|
1402
|
+
"instance_class": "db.t3.small"
|
|
1403
|
+
},
|
|
1404
|
+
"after": {
|
|
1405
|
+
"password": "new-a",
|
|
1406
|
+
"instance_class": "db.t3.small"
|
|
1407
|
+
},
|
|
1408
|
+
"before_sensitive": {
|
|
1409
|
+
"password": true
|
|
1410
|
+
},
|
|
1411
|
+
"after_sensitive": {
|
|
1412
|
+
"password": true
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
]
|
|
1417
|
+
}
|
|
1418
|
+
},
|
|
1419
|
+
"b": {
|
|
1420
|
+
"root": "roots/globex",
|
|
1421
|
+
"estate": "globex",
|
|
1422
|
+
"status": "planned",
|
|
1423
|
+
"plan": {
|
|
1424
|
+
"format_version": "1.2",
|
|
1425
|
+
"resource_changes": [
|
|
1426
|
+
{
|
|
1427
|
+
"address": "aws_db_instance.main",
|
|
1428
|
+
"change": {
|
|
1429
|
+
"actions": [
|
|
1430
|
+
"update"
|
|
1431
|
+
],
|
|
1432
|
+
"before": {
|
|
1433
|
+
"password": "old-b",
|
|
1434
|
+
"instance_class": "db.t3.small"
|
|
1435
|
+
},
|
|
1436
|
+
"after": {
|
|
1437
|
+
"password": "new-b",
|
|
1438
|
+
"instance_class": "db.t3.small"
|
|
1439
|
+
},
|
|
1440
|
+
"before_sensitive": {
|
|
1441
|
+
"password": true
|
|
1442
|
+
},
|
|
1443
|
+
"after_sensitive": {
|
|
1444
|
+
"password": true
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
]
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
"name": "sensitive against not sensitive on the same attribute",
|
|
1454
|
+
"group": false,
|
|
1455
|
+
"a": {
|
|
1456
|
+
"root": "roots/acme",
|
|
1457
|
+
"estate": "acme",
|
|
1458
|
+
"status": "planned",
|
|
1459
|
+
"plan": {
|
|
1460
|
+
"format_version": "1.2",
|
|
1461
|
+
"resource_changes": [
|
|
1462
|
+
{
|
|
1463
|
+
"address": "aws_db_instance.main",
|
|
1464
|
+
"change": {
|
|
1465
|
+
"actions": [
|
|
1466
|
+
"update"
|
|
1467
|
+
],
|
|
1468
|
+
"before": {
|
|
1469
|
+
"password": "same-old",
|
|
1470
|
+
"instance_class": "db.t3.small"
|
|
1471
|
+
},
|
|
1472
|
+
"after": {
|
|
1473
|
+
"password": "same-new",
|
|
1474
|
+
"instance_class": "db.t3.small"
|
|
1475
|
+
},
|
|
1476
|
+
"before_sensitive": {
|
|
1477
|
+
"password": true
|
|
1478
|
+
},
|
|
1479
|
+
"after_sensitive": {
|
|
1480
|
+
"password": true
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
]
|
|
1485
|
+
}
|
|
1486
|
+
},
|
|
1487
|
+
"b": {
|
|
1488
|
+
"root": "roots/globex",
|
|
1489
|
+
"estate": "globex",
|
|
1490
|
+
"status": "planned",
|
|
1491
|
+
"plan": {
|
|
1492
|
+
"format_version": "1.2",
|
|
1493
|
+
"resource_changes": [
|
|
1494
|
+
{
|
|
1495
|
+
"address": "aws_db_instance.main",
|
|
1496
|
+
"change": {
|
|
1497
|
+
"actions": [
|
|
1498
|
+
"update"
|
|
1499
|
+
],
|
|
1500
|
+
"before": {
|
|
1501
|
+
"password": "same-old",
|
|
1502
|
+
"instance_class": "db.t3.small"
|
|
1503
|
+
},
|
|
1504
|
+
"after": {
|
|
1505
|
+
"password": "same-new",
|
|
1506
|
+
"instance_class": "db.t3.small"
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
]
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
"name": "read entries whose results differ",
|
|
1516
|
+
"group": true,
|
|
1517
|
+
"a": {
|
|
1518
|
+
"root": "roots/acme",
|
|
1519
|
+
"estate": "acme",
|
|
1520
|
+
"status": "planned",
|
|
1521
|
+
"plan": {
|
|
1522
|
+
"format_version": "1.2",
|
|
1523
|
+
"resource_changes": [
|
|
1524
|
+
{
|
|
1525
|
+
"address": "data.aws_ami.base",
|
|
1526
|
+
"change": {
|
|
1527
|
+
"actions": [
|
|
1528
|
+
"read"
|
|
1529
|
+
],
|
|
1530
|
+
"after": {
|
|
1531
|
+
"id": "ami-0aaa111",
|
|
1532
|
+
"image_id": "ami-0aaa111",
|
|
1533
|
+
"owner": "amazon"
|
|
1534
|
+
},
|
|
1535
|
+
"after_unknown": {}
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
]
|
|
1539
|
+
}
|
|
1540
|
+
},
|
|
1541
|
+
"b": {
|
|
1542
|
+
"root": "roots/globex",
|
|
1543
|
+
"estate": "globex",
|
|
1544
|
+
"status": "planned",
|
|
1545
|
+
"plan": {
|
|
1546
|
+
"format_version": "1.2",
|
|
1547
|
+
"resource_changes": [
|
|
1548
|
+
{
|
|
1549
|
+
"address": "data.aws_ami.base",
|
|
1550
|
+
"change": {
|
|
1551
|
+
"actions": [
|
|
1552
|
+
"read"
|
|
1553
|
+
],
|
|
1554
|
+
"after": {
|
|
1555
|
+
"id": "ami-0bbb222",
|
|
1556
|
+
"image_id": "ami-0bbb222",
|
|
1557
|
+
"owner": "amazon"
|
|
1558
|
+
},
|
|
1559
|
+
"after_unknown": {}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
]
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
{
|
|
1567
|
+
"name": "a read of a different data source",
|
|
1568
|
+
"group": false,
|
|
1569
|
+
"a": {
|
|
1570
|
+
"root": "roots/acme",
|
|
1571
|
+
"estate": "acme",
|
|
1572
|
+
"status": "planned",
|
|
1573
|
+
"plan": {
|
|
1574
|
+
"format_version": "1.2",
|
|
1575
|
+
"resource_changes": [
|
|
1576
|
+
{
|
|
1577
|
+
"address": "data.aws_ami.base",
|
|
1578
|
+
"change": {
|
|
1579
|
+
"actions": [
|
|
1580
|
+
"read"
|
|
1581
|
+
],
|
|
1582
|
+
"after": {
|
|
1583
|
+
"id": "ami-0aaa111",
|
|
1584
|
+
"image_id": "ami-0aaa111",
|
|
1585
|
+
"owner": "amazon"
|
|
1586
|
+
},
|
|
1587
|
+
"after_unknown": {}
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
]
|
|
1591
|
+
}
|
|
1592
|
+
},
|
|
1593
|
+
"b": {
|
|
1594
|
+
"root": "roots/globex",
|
|
1595
|
+
"estate": "globex",
|
|
1596
|
+
"status": "planned",
|
|
1597
|
+
"plan": {
|
|
1598
|
+
"format_version": "1.2",
|
|
1599
|
+
"resource_changes": [
|
|
1600
|
+
{
|
|
1601
|
+
"address": "data.aws_ami.other",
|
|
1602
|
+
"change": {
|
|
1603
|
+
"actions": [
|
|
1604
|
+
"read"
|
|
1605
|
+
],
|
|
1606
|
+
"after": {
|
|
1607
|
+
"id": "ami-0aaa111",
|
|
1608
|
+
"image_id": "ami-0aaa111",
|
|
1609
|
+
"owner": "amazon"
|
|
1610
|
+
},
|
|
1611
|
+
"after_unknown": {}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
]
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
"name": "a read against a plan with no entry for it",
|
|
1620
|
+
"group": false,
|
|
1621
|
+
"a": {
|
|
1622
|
+
"root": "roots/acme",
|
|
1623
|
+
"estate": "acme",
|
|
1624
|
+
"status": "planned",
|
|
1625
|
+
"plan": {
|
|
1626
|
+
"format_version": "1.2",
|
|
1627
|
+
"resource_changes": [
|
|
1628
|
+
{
|
|
1629
|
+
"address": "data.aws_ami.base",
|
|
1630
|
+
"change": {
|
|
1631
|
+
"actions": [
|
|
1632
|
+
"read"
|
|
1633
|
+
],
|
|
1634
|
+
"after": {
|
|
1635
|
+
"id": "ami-0aaa111",
|
|
1636
|
+
"image_id": "ami-0aaa111",
|
|
1637
|
+
"owner": "amazon"
|
|
1638
|
+
},
|
|
1639
|
+
"after_unknown": {}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
]
|
|
1643
|
+
}
|
|
1644
|
+
},
|
|
1645
|
+
"b": {
|
|
1646
|
+
"root": "roots/globex",
|
|
1647
|
+
"estate": "globex",
|
|
1648
|
+
"status": "planned",
|
|
1649
|
+
"plan": {
|
|
1650
|
+
"format_version": "1.2",
|
|
1651
|
+
"resource_changes": []
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1382
1654
|
}
|
|
1383
1655
|
],
|
|
1384
1656
|
"instancePairs": [
|
|
@@ -1588,6 +1860,7 @@
|
|
|
1588
1860
|
"different policy document",
|
|
1589
1861
|
"different tag value that does not carry the estate",
|
|
1590
1862
|
"a tofu-estate marker naming some other estate",
|
|
1591
|
-
"the estate name inside a longer word is not the estate"
|
|
1863
|
+
"the estate name inside a longer word is not the estate",
|
|
1864
|
+
"sensitive against not sensitive on the same attribute"
|
|
1592
1865
|
]
|
|
1593
1866
|
}
|
|
@@ -10,7 +10,7 @@ Applied 2 members. Head `222222222222`, measured from `111111111111`.
|
|
|
10
10
|
|
|
11
11
|
A member whose inputs moved applied the plan it was approved with. The next run plans it against the new values.
|
|
12
12
|
|
|
13
|
-
Plan digest: `jcs1-sha256:
|
|
13
|
+
Plan digest: `jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0`
|
|
14
14
|
|
|
15
15
|
Approved by `github:alice` for this digest.
|
|
16
16
|
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
The apply refused. Head `222222222222`, measured from `111111111111`.
|
|
5
5
|
|
|
6
|
-
> The plan changed after review, so nothing was applied. approved: jcs1-sha256:0000000000000000000000000000000000000000000000000000000000000063; planned now: jcs1-sha256:
|
|
6
|
+
> The plan changed after review, so nothing was applied. approved: jcs1-sha256:0000000000000000000000000000000000000000000000000000000000000063; planned now: jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0. Read the new plan, and if it is right, approve it: chant approve pr-12 pr-apply --plan jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0 --approver <you> --sign; then run the apply again.
|
|
7
7
|
|
|
8
8
|
| Member | Component | Status | Create | Update | Replace | Delete |
|
|
9
9
|
|---|---|---|---:|---:|---:|---:|
|
|
10
10
|
| `a` | a | planned | 0 | 1 | 0 | 0 |
|
|
11
11
|
| `app` | app | planned | 0 | 0 | 0 | 0 |
|
|
12
12
|
|
|
13
|
-
Plan digest: `jcs1-sha256:
|
|
13
|
+
Plan digest: `jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0`
|
|
14
14
|
|
|
15
15
|
An approval stands for `jcs1-sha256:0000000000000000000000000000000000000000000000000000000000000063`, not for this digest: the plan changed since it was approved.
|
|
16
16
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"head": "2222222222222222222222222222222222222222",
|
|
9
9
|
"op": "pr-12",
|
|
10
10
|
"gate": "pr-apply",
|
|
11
|
-
"digest": "jcs1-sha256:
|
|
11
|
+
"digest": "jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0",
|
|
12
12
|
"status": "planned",
|
|
13
13
|
"approval": {
|
|
14
14
|
"status": "pending"
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"changeSet": {
|
|
61
61
|
"$schema": "https://intentius.io/chant/schemas/workspace/change-set/v1/change-set.schema.json",
|
|
62
62
|
"contract": 1,
|
|
63
|
-
"digest": "jcs1-sha256:
|
|
63
|
+
"digest": "jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0",
|
|
64
64
|
"members": [
|
|
65
65
|
{
|
|
66
66
|
"member": "a",
|
|
@@ -8,14 +8,14 @@ Planned 2 members. Head `222222222222`, measured from `111111111111`.
|
|
|
8
8
|
| `a` | a | planned | 0 | 1 | 0 | 0 |
|
|
9
9
|
| `app` | app | planned | 0 | 0 | 0 | 0 |
|
|
10
10
|
|
|
11
|
-
Plan digest: `jcs1-sha256:
|
|
11
|
+
Plan digest: `jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0`
|
|
12
12
|
|
|
13
13
|
Not approved yet.
|
|
14
14
|
|
|
15
15
|
A reviewer who approved this pull request approves the plan with:
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
chant approve pr-12 pr-apply --plan jcs1-sha256:
|
|
18
|
+
chant approve pr-12 pr-apply --plan jcs1-sha256:7623a8677afb0bf98d77c602521a3abfa96f76cff25675d350a28c2e26a7bad0 --approver github:<your-login> --sign
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
It applies on merge if the plan is still this one. If it moved, the apply refuses and names both digests.
|
package/src/build.test.ts
CHANGED
|
@@ -253,7 +253,7 @@ export const testEntity = {
|
|
|
253
253
|
const result = await build(testDir, []);
|
|
254
254
|
|
|
255
255
|
expect(result.warnings.length).toBeGreaterThan(0);
|
|
256
|
-
expect(result.warnings[0]).toContain('No serializer found for lexicon "unknown"');
|
|
256
|
+
expect(result.warnings[0]).toContain('No serializer found for lexicon "unknown". List the lexicon in chant.config.ts.');
|
|
257
257
|
});
|
|
258
258
|
});
|
|
259
259
|
|
package/src/build.ts
CHANGED
|
@@ -897,7 +897,7 @@ async function buildFromDiscoveryResult(
|
|
|
897
897
|
// designed shape until a lexicon materializes the receipt (#1835), not
|
|
898
898
|
// a missing-serializer problem.
|
|
899
899
|
} else {
|
|
900
|
-
warnings.push(`No serializer found for lexicon "${lexiconName}"
|
|
900
|
+
warnings.push(`No serializer found for lexicon "${lexiconName}". List the lexicon in chant.config.ts.`);
|
|
901
901
|
}
|
|
902
902
|
}
|
|
903
903
|
|
package/src/change-set.test.ts
CHANGED
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
* update. The update, delete, effect and hole mappings are pinned on typed
|
|
11
11
|
* entries below.
|
|
12
12
|
*
|
|
13
|
-
* `warden.plan.json` is
|
|
14
|
-
*
|
|
15
|
-
* update and one owned delete
|
|
16
|
-
*
|
|
13
|
+
* `warden.plan.json` is what github-warden's `reconcile --plan-json` wrote
|
|
14
|
+
* (github-warden#66) for a teams cycle in an org that declares `owned: true`:
|
|
15
|
+
* one create, one update and one owned delete, as a JSON array of reconcile
|
|
16
|
+
* change sets. It was produced by warden's own `runReconcile` and
|
|
17
|
+
* `teamsCycle` against a stubbed live state, not built here.
|
|
17
18
|
*
|
|
18
19
|
* Goldens regenerate with `UPDATE_GOLDEN=1`.
|
|
19
20
|
*/
|
|
@@ -24,6 +25,7 @@ import { describe, expect, test } from "vitest";
|
|
|
24
25
|
import {
|
|
25
26
|
CHANGE_SET_SCHEMA_ID,
|
|
26
27
|
changeSetDigest,
|
|
28
|
+
changeSetDocumentDigest,
|
|
27
29
|
composeChangeSet,
|
|
28
30
|
lifecyclePlanPart,
|
|
29
31
|
reconcilePlanPart,
|
|
@@ -140,10 +142,8 @@ describe("lifecyclePlanPart", () => {
|
|
|
140
142
|
});
|
|
141
143
|
|
|
142
144
|
describe("reconcilePlanPart", () => {
|
|
143
|
-
test("a warden's teams cycle, as
|
|
144
|
-
const
|
|
145
|
-
golden("warden.plan.json", plan);
|
|
146
|
-
const part = reconcilePlanPart({ member: "warden", plan: read(DIR, "warden.plan.json") as ReconcileChangeSet });
|
|
145
|
+
test("a warden's teams cycle, as `reconcile --plan-json` wrote it", () => {
|
|
146
|
+
const part = reconcilePlanPart({ member: "warden", plan: read(DIR, "warden.plan.json") as ReconcileChangeSet[] });
|
|
147
147
|
expect(part.entries.map((e) => [e.address, e.action, e.disruption ?? null])).toEqual([
|
|
148
148
|
["team.contractors", "delete", "destroy"],
|
|
149
149
|
["team.platform", "update", "unknown"],
|
|
@@ -167,11 +167,20 @@ describe("the digest", () => {
|
|
|
167
167
|
const warden = () => reconcilePlanPart({ member: "warden", plan: wardenPlan() });
|
|
168
168
|
const tofu = () => read(TF_DIR, "tofu.part.golden.json") as ChangeSetPart;
|
|
169
169
|
|
|
170
|
-
test("
|
|
170
|
+
test("binds the set digest over { member, planDigest }, the members' status and holes, the entries and the side effects, whatever order the parts come in", () => {
|
|
171
171
|
const doc = composeChangeSet([lifecycle(), warden(), tofu()]);
|
|
172
172
|
expect(composeChangeSet([tofu(), warden(), lifecycle()])).toEqual(doc);
|
|
173
173
|
const pairs = doc.members.map((m) => ({ member: m.member, planDigest: m.planDigest }));
|
|
174
|
-
expect(doc.
|
|
174
|
+
expect(changeSetDigest(doc.members)).toBe(computePlanDigest("change-set", pairs));
|
|
175
|
+
expect(doc.digest).toBe(
|
|
176
|
+
computePlanDigest("change-set-document", {
|
|
177
|
+
set: computePlanDigest("change-set", pairs),
|
|
178
|
+
members: doc.members.map((m) => ({ member: m.member, status: m.status, holes: m.holes })),
|
|
179
|
+
entries: doc.entries,
|
|
180
|
+
sideEffects: [],
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
expect(doc.digest).toBe(changeSetDocumentDigest({ ...doc, entries: [...doc.entries].reverse() }));
|
|
175
184
|
expect(doc.digest).toMatch(/^jcs1-sha256:[0-9a-f]{64}$/);
|
|
176
185
|
expect(verifyChangeSetDigest(doc)).toBe(true);
|
|
177
186
|
expect(verifyChangeSetDigest({ ...doc, digest: changeSetDigest(doc.members.slice(1)) })).toBe(false);
|
|
@@ -183,8 +192,29 @@ describe("the digest", () => {
|
|
|
183
192
|
const moved = wardenPlan();
|
|
184
193
|
moved.entries[0] = { ...moved.entries[0], after: { privacy: "closed", description: "Release engineers" } };
|
|
185
194
|
expect(composeChangeSet([lifecycle(), reconcilePlanPart({ member: "warden", plan: moved })]).digest).not.toBe(base);
|
|
186
|
-
// A wave is a subset of members: its digest is the
|
|
187
|
-
expect(changeSetDigest([lifecycle().member])).toBe(
|
|
195
|
+
// A wave is a subset of members: its digest is the set digest over them, which the document's digest binds.
|
|
196
|
+
expect(changeSetDigest([lifecycle().member])).toBe(computePlanDigest("change-set", [{ member: "delivery", planDigest: lifecycle().member.planDigest }]));
|
|
197
|
+
expect(changeSetDigest([lifecycle().member])).not.toBe(composeChangeSet([lifecycle()]).digest);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("moves when an entry, a hole, a member's status or a side effect does, so a document with edited entries does not verify (#3555)", () => {
|
|
201
|
+
const doc = composeChangeSet([lifecycle(), warden()]);
|
|
202
|
+
const [first, ...rest] = doc.entries;
|
|
203
|
+
const edited = [
|
|
204
|
+
{ ...doc, entries: rest },
|
|
205
|
+
{ ...doc, entries: [{ ...first, action: first.action === "delete" ? ("create" as const) : ("delete" as const) }, ...rest] },
|
|
206
|
+
{ ...doc, entries: [{ ...first, attributes: [...first.attributes, { path: "planted", after: "x" }] }, ...rest] },
|
|
207
|
+
{ ...doc, entries: [...doc.entries, { ...first, address: `${first.address}-planted` }] },
|
|
208
|
+
{ ...doc, members: doc.members.map((m) => ({ ...m, holes: [...m.holes, { address: "planted", reason: "unobserved" }] })) },
|
|
209
|
+
{ ...doc, members: doc.members.map((m, i) => (i === 0 ? { ...m, status: "failed" as const } : m)) },
|
|
210
|
+
{ ...doc, sideEffects: [{ member: doc.members[0].member, address: "action.aws_lambda_invoke.planted", type: "aws_lambda_invoke" }] },
|
|
211
|
+
];
|
|
212
|
+
expect(verifyChangeSetDigest(doc)).toBe(true);
|
|
213
|
+
for (const e of edited) {
|
|
214
|
+
expect(changeSetDocumentDigest(e)).not.toBe(doc.digest);
|
|
215
|
+
expect(verifyChangeSetDigest(e)).toBe(false);
|
|
216
|
+
}
|
|
217
|
+
expect(verifyChangeSetDigest({ ...doc, members: [...doc.members, doc.members[0]] })).toBe(false);
|
|
188
218
|
});
|
|
189
219
|
|
|
190
220
|
test("leaves provisional members out, so approving the document never covers them", () => {
|