@intentius/chant-lexicon-docker 0.102.0 → 0.104.1

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "e7a19357c7fdbc452830f8f1b348c87e98b2cb424e84b6aa584020b35b1f2650",
4
+ "manifest.json": "c39d048027ec61fa80629f8b22bd19cca47959e905133a147842d98d0a4e1046",
5
5
  "meta.json": "2996be8fdb14f3f935e1e1441fed8f69af7b6aeeefb14dac96301cc41eba8046",
6
6
  "types/index.d.ts": "7b2e6f784b7dbecbbe7924fa1aec7e2520ac0547069311253a006bc2267a5646",
7
7
  "rules/no-latest-tag.ts": "efd060453d8ca3d5b85c3972906c6650b6f63eb5f67cb6cdb0f16a41cad91228",
@@ -15,5 +15,5 @@
15
15
  "skills/chant-docker.md": "3ff0708e3c76e245f202948949c768464563af2b60cc9aa2ca52f494ef8357f1",
16
16
  "skills/chant-docker-patterns.md": "ad1b0196d8150b2df579a699ff107f604340c799c04f3460ebf65003e287b12a"
17
17
  },
18
- "composite": "14a64046d656bdf511370cac18a4325fbef0dea043179957339b9e08993fe703"
18
+ "composite": "f63ae956999279fd8dd17fbc85e3d090980676d936204471f882dab87662eda4"
19
19
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docker",
3
- "version": "0.102.0",
3
+ "version": "0.104.1",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Docker",
6
6
  "intrinsics": [
@@ -1 +1 @@
1
- {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAoB,UAAU,EAAoB,MAAM,6BAA6B,CAAC;AA+RlG,eAAO,MAAM,gBAAgB,EAAE,UAqE9B,CAAC"}
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAoB,UAAU,EAAoB,MAAM,6BAA6B,CAAC;AA6SlG,eAAO,MAAM,gBAAgB,EAAE,UAqE9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-docker",
3
- "version": "0.102.0",
3
+ "version": "0.104.1",
4
4
  "description": "Docker lexicon for chant — declarative IaC in TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -70,7 +70,7 @@
70
70
  "typescript": "^5.9.3"
71
71
  },
72
72
  "peerDependencies": {
73
- "@intentius/chant": "^0.102.0",
73
+ "@intentius/chant": "^0.104.1",
74
74
  "typescript": "^5.9.3"
75
75
  }
76
76
  }
@@ -75,7 +75,7 @@ export const DockerOtelCollector = Composite((props: DockerOtelCollectorProps) =
75
75
  image,
76
76
  command: [`--config=${COLLECTOR_CONFIG_PATH}`],
77
77
  configs: [{ source: config, target: COLLECTOR_CONFIG_PATH }],
78
- ...(publishPorts && ports.length > 0 ? { ports: ports.map((p) => `${p.port}:${p.port}`) } : {}),
78
+ ...(publishPorts && ports.length > 0 ? { ports: ports.map((p) => `${p.port}:${p.port}${p.protocol ? "/udp" : ""}`) } : {}),
79
79
  restart,
80
80
  }, defs?.service));
81
81
 
@@ -365,4 +365,15 @@ describe("telemetry attribution", () => {
365
365
  expect(out).not.toContain("OTEL_SERVICE_NAME=api");
366
366
  expect(out).toContain("- OTEL_RESOURCE_ATTRIBUTES=chant.workspace=acme,chant.member=delivery");
367
367
  });
368
+
369
+ test("the resource attributes end with the release reference a deploy fills, once (#3061)", () => {
370
+ expect(run({ image: "nginx:1" }, attrs)).toContain(
371
+ "OTEL_RESOURCE_ATTRIBUTES: chant.workspace=acme,chant.member=delivery,chant.decl=api,deployment.environment.name=prod${CHANT_RELEASE_ATTRIBUTES:-}",
372
+ );
373
+ const own = run({ image: "x", environment: { OTEL_RESOURCE_ATTRIBUTES: "team=pay${CHANT_RELEASE_ATTRIBUTES:-}" } }, { workspace: "acme" });
374
+ expect(own.match(/CHANT_RELEASE_ATTRIBUTES/g)).toHaveLength(1);
375
+ expect(run({ image: "x", environment: ["OTEL_RESOURCE_ATTRIBUTES=team=pay"] }, { workspace: "acme" })).toContain(
376
+ "- OTEL_RESOURCE_ATTRIBUTES=team=pay,chant.workspace=acme,chant.decl=api${CHANT_RELEASE_ATTRIBUTES:-}",
377
+ );
378
+ });
368
379
  });
package/src/serializer.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  import type { Declarable } from "@intentius/chant/declarable";
13
13
  import { isPropertyDeclarable, isResourceDeclarable } from "@intentius/chant/declarable";
14
14
  import type { SerializeContext, Serializer, SerializerResult } from "@intentius/chant/serializer";
15
- import { mergeResourceAttributes, telemetryEnvironment, type TelemetryAttribution } from "@intentius/chant/telemetry-attribution";
15
+ import { mergeResourceAttributes, RELEASE_ATTRIBUTES_VARIABLE, telemetryEnvironment, type TelemetryAttribution } from "@intentius/chant/telemetry-attribution";
16
16
  import type { LexiconOutput } from "@intentius/chant/lexicon-output";
17
17
  import { walkValue, type SerializerVisitor } from "@intentius/chant/serializer-walker";
18
18
  import { INTRINSIC_MARKER } from "@intentius/chant/intrinsic";
@@ -107,11 +107,25 @@ function imageDigest(image: unknown): string | undefined {
107
107
  return at === -1 ? undefined : image.slice(at + 1);
108
108
  }
109
109
 
110
+ /** Compose's reference to the release attributes a deploy exports (#3061, ws-081), empty when unset. */
111
+ const RELEASE_REF = `\${${RELEASE_ATTRIBUTES_VARIABLE}:-}`;
112
+
113
+ /** A resource-attributes value that ends with the release reference, once. */
114
+ function withReleaseRef(value: string): string {
115
+ return value.includes(RELEASE_REF) ? value : `${value}${RELEASE_REF}`;
116
+ }
117
+
110
118
  /**
111
119
  * Stamp one service's attributes as `OTEL_SERVICE_NAME` and
112
120
  * `OTEL_RESOURCE_ATTRIBUTES` in its environment. A value the service already
113
121
  * sets is kept: its own `OTEL_SERVICE_NAME` wins, and its own resource
114
122
  * attributes keep their keys while the missing ones are appended.
123
+ *
124
+ * `OTEL_RESOURCE_ATTRIBUTES` ends with `${CHANT_RELEASE_ATTRIBUTES:-}`, which
125
+ * Compose fills from the environment of `docker compose up`: a release deploy
126
+ * exports `service.version` and `vcs.ref.head.revision` there (#3061,
127
+ * ws-081), and any other `up` leaves it empty, so this output does not change
128
+ * with a release.
115
129
  */
116
130
  function stampTelemetry(service: Record<string, unknown>, name: string, telemetry: TelemetryAttribution): void {
117
131
  const version = imageDigest(service.image);
@@ -122,9 +136,9 @@ function stampTelemetry(service: Record<string, unknown>, name: string, telemetr
122
136
  const has = (key: string) => entries.findIndex((e) => e === key || e.startsWith(`${key}=`));
123
137
  if (has("OTEL_SERVICE_NAME") === -1) entries.push(`OTEL_SERVICE_NAME=${vars.OTEL_SERVICE_NAME}`);
124
138
  const at = has("OTEL_RESOURCE_ATTRIBUTES");
125
- if (at === -1) entries.push(`OTEL_RESOURCE_ATTRIBUTES=${vars.OTEL_RESOURCE_ATTRIBUTES}`);
139
+ if (at === -1) entries.push(`OTEL_RESOURCE_ATTRIBUTES=${withReleaseRef(vars.OTEL_RESOURCE_ATTRIBUTES)}`);
126
140
  else if (entries[at]!.includes("=")) {
127
- entries[at] = `OTEL_RESOURCE_ATTRIBUTES=${mergeResourceAttributes(entries[at]!.slice(entries[at]!.indexOf("=") + 1), vars.OTEL_RESOURCE_ATTRIBUTES)}`;
141
+ entries[at] = `OTEL_RESOURCE_ATTRIBUTES=${withReleaseRef(mergeResourceAttributes(entries[at]!.slice(entries[at]!.indexOf("=") + 1), vars.OTEL_RESOURCE_ATTRIBUTES))}`;
128
142
  }
129
143
  service.environment = entries;
130
144
  return;
@@ -132,8 +146,8 @@ function stampTelemetry(service: Record<string, unknown>, name: string, telemetr
132
146
  const map: Record<string, unknown> = env && typeof env === "object" ? { ...(env as Record<string, unknown>) } : {};
133
147
  if (!("OTEL_SERVICE_NAME" in map)) map.OTEL_SERVICE_NAME = vars.OTEL_SERVICE_NAME;
134
148
  const own = map.OTEL_RESOURCE_ATTRIBUTES;
135
- if (own === undefined) map.OTEL_RESOURCE_ATTRIBUTES = vars.OTEL_RESOURCE_ATTRIBUTES;
136
- else if (typeof own === "string") map.OTEL_RESOURCE_ATTRIBUTES = mergeResourceAttributes(own, vars.OTEL_RESOURCE_ATTRIBUTES);
149
+ if (own === undefined) map.OTEL_RESOURCE_ATTRIBUTES = withReleaseRef(vars.OTEL_RESOURCE_ATTRIBUTES);
150
+ else if (typeof own === "string") map.OTEL_RESOURCE_ATTRIBUTES = withReleaseRef(mergeResourceAttributes(own, vars.OTEL_RESOURCE_ATTRIBUTES));
137
151
  service.environment = map;
138
152
  }
139
153