@toa.io/operations 1.0.0-alpha.305 → 1.0.0-alpha.306

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
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-alpha.306](https://github.com/toa-io/toa/compare/v1.0.0-alpha.305...v1.0.0-alpha.306) (2026-09-14)
7
+
8
+ **Note:** Version bump only for package @toa.io/operations
9
+
10
+
11
+
12
+
13
+
6
14
  # [1.0.0-alpha.305](https://github.com/toa-io/toa/compare/v1.0.0-alpha.304...v1.0.0-alpha.305) (2026-09-13)
7
15
 
8
16
  **Note:** Version bump only for package @toa.io/operations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/operations",
3
- "version": "1.0.0-alpha.305",
3
+ "version": "1.0.0-alpha.306",
4
4
  "type": "module",
5
5
  "description": "Toa Deployment",
6
6
  "homepage": "https://toa.io",
@@ -30,9 +30,9 @@
30
30
  "dependencies": {
31
31
  "@toa.io/generic": "1.0.0-alpha.304",
32
32
  "@toa.io/kubernetes": "1.0.0-alpha.301",
33
- "@toa.io/norm": "1.0.0-alpha.305",
33
+ "@toa.io/norm": "1.0.0-alpha.306",
34
34
  "oxc-parser": "0.149.0",
35
35
  "paseto": "4.0.1"
36
36
  },
37
- "gitHead": "6a28476303826e2484cc2ea6306efee6f19fb594"
37
+ "gitHead": "0693d180a8053a7d07dca879dac2a3c4784d6d45"
38
38
  }
@@ -1,3 +1,6 @@
1
+ import { map } from '@toa.io/norm'
2
+ import { MAP_DIRECTORY, MAP_FILE } from '@toa.io/definitions'
3
+
1
4
  import * as desc from './.describe/index.js'
2
5
  import { addVariables } from './.describe/variables.js'
3
6
  import { addMounts } from './.describe/mounts.js'
@@ -92,6 +95,7 @@ export const describe = (context, compositions, dependency, image) => {
92
95
  components: mono.components,
93
96
  services: [],
94
97
  credentials,
98
+ map: versions(context),
95
99
  mono
96
100
  }
97
101
 
@@ -109,7 +113,8 @@ export const describe = (context, compositions, dependency, image) => {
109
113
  compositions,
110
114
  components,
111
115
  services,
112
- credentials
116
+ credentials,
117
+ map: versions(context)
113
118
  }
114
119
 
115
120
  resources(context, values)
@@ -160,3 +165,13 @@ function unit(context, dependency) {
160
165
 
161
166
  return mono
162
167
  }
168
+
169
+ /**
170
+ * The component map every workload mounts: which version of a component a process asks what that
171
+ * component provides. Named rather than found, because a ConfigMap mounts as a directory.
172
+ *
173
+ * @param {toa.norm.Context} context
174
+ */
175
+ function versions(context) {
176
+ return { directory: MAP_DIRECTORY, file: MAP_FILE, components: map(context) }
177
+ }
@@ -0,0 +1,12 @@
1
+ {{- if .Values.map }}
2
+ # Which version of each component a process asks what that component provides. Mounted rather
3
+ # than rendered into a workload's environment: a variable would replace every pod of the context
4
+ # on every deployment, and a pod that came up between two of them could not be told.
5
+ apiVersion: v1
6
+ kind: ConfigMap
7
+ metadata:
8
+ name: components
9
+ data:
10
+ {{ .Values.map.file }}: |
11
+ {{ .Values.map.components | toPrettyJson | indent 4 }}
12
+ {{- end }}
@@ -90,12 +90,17 @@ spec:
90
90
  timeoutSeconds: 3
91
91
  failureThreshold: 5
92
92
  {{- end }}
93
- {{- if .mounts }}
93
+ {{- if or .mounts $.Values.map }}
94
94
  volumeMounts:
95
95
  {{- range .mounts }}
96
96
  - name: {{ .name }}
97
97
  mountPath: {{ .path }}
98
98
  {{- end }}
99
+ {{- if $.Values.map }}
100
+ - name: components
101
+ mountPath: {{ $.Values.map.directory }}
102
+ readOnly: true
103
+ {{- end }}
99
104
  {{- end }}
100
105
  lifecycle:
101
106
  preStop:
@@ -106,13 +111,18 @@ spec:
106
111
  imagePullSecrets:
107
112
  - name: {{ $.Values.credentials }}
108
113
  {{- end }}
109
- {{- if .mounts }}
114
+ {{- if or .mounts $.Values.map }}
110
115
  volumes:
111
116
  {{- range .mounts }}
112
117
  - name: {{ .name }}
113
118
  persistentVolumeClaim:
114
119
  claimName: {{ .claim }}
115
120
  {{- end }}
121
+ {{- if $.Values.map }}
122
+ - name: components
123
+ configMap:
124
+ name: components
125
+ {{- end }}
116
126
  {{- end }}
117
127
  topologySpreadConstraints:
118
128
  - maxSkew: 1
@@ -80,12 +80,17 @@ spec:
80
80
  timeoutSeconds: 3
81
81
  failureThreshold: 5
82
82
  {{- end }}
83
- {{- if .mounts }}
83
+ {{- if or .mounts $.Values.map }}
84
84
  volumeMounts:
85
85
  {{- range .mounts }}
86
86
  - name: {{ .name }}
87
87
  mountPath: {{ .path }}
88
88
  {{- end }}
89
+ {{- if $.Values.map }}
90
+ - name: components
91
+ mountPath: {{ $.Values.map.directory }}
92
+ readOnly: true
93
+ {{- end }}
89
94
  {{- end }}
90
95
  lifecycle:
91
96
  preStop:
@@ -96,13 +101,18 @@ spec:
96
101
  imagePullSecrets:
97
102
  - name: {{ $.Values.credentials }}
98
103
  {{- end }}
99
- {{- if .mounts }}
104
+ {{- if or .mounts $.Values.map }}
100
105
  volumes:
101
106
  {{- range .mounts }}
102
107
  - name: {{ .name }}
103
108
  persistentVolumeClaim:
104
109
  claimName: {{ .claim }}
105
110
  {{- end }}
111
+ {{- if $.Values.map }}
112
+ - name: components
113
+ configMap:
114
+ name: components
115
+ {{- end }}
106
116
  {{- end }}
107
117
  topologySpreadConstraints:
108
118
  - maxSkew: 1
@@ -73,10 +73,22 @@ spec:
73
73
  timeoutSeconds: 3
74
74
  failureThreshold: 5
75
75
  {{- end }}
76
+ {{- if $.Values.map }}
77
+ volumeMounts:
78
+ - name: components
79
+ mountPath: {{ $.Values.map.directory }}
80
+ readOnly: true
81
+ {{- end }}
76
82
  lifecycle:
77
83
  preStop:
78
84
  exec:
79
85
  command: [sleep, "5"]
86
+ {{- if $.Values.map }}
87
+ volumes:
88
+ - name: components
89
+ configMap:
90
+ name: components
91
+ {{- end }}
80
92
  terminationGracePeriodSeconds: 45
81
93
  topologySpreadConstraints:
82
94
  - maxSkew: 1
@@ -8,4 +8,4 @@ COPY --link . /composition
8
8
 
9
9
  # no USER: the runtime drops to `node` itself, and only a process that started as root can
10
10
  # close its environment under /proc — see runtime/runtime/bin/toa
11
- CMD toa compose *
11
+ CMD toa compose * --map {{map.file}}
@@ -213,7 +213,7 @@ describe('prepare', () => {
213
213
  assert.deepStrictEqual(lines, [
214
214
  `FROM ${image.dependencies.reference}`,
215
215
  'COPY --link . /composition',
216
- 'CMD toa compose *'
216
+ 'CMD toa compose * --map /etc/toa/components.json'
217
217
  ])
218
218
 
219
219
  const entries = (await readdir(context, { recursive: true })).sort()
@@ -3,6 +3,7 @@ import { readFile as read, writeFile as write } from 'node:fs/promises'
3
3
  import { createHash } from 'node:crypto'
4
4
 
5
5
  import { overwrite } from '@toa.io/generic'
6
+ import { MAP } from '@toa.io/definitions'
6
7
  import { mkdir } from 'node:fs/promises'
7
8
 
8
9
  /**
@@ -104,6 +105,7 @@ export class Image {
104
105
  }
105
106
 
106
107
  #setValues() {
108
+ this.#values.map = { file: MAP }
107
109
  this.#values.runtime = this.#runtime
108
110
  this.#values.build = overwrite(
109
111
  {
@@ -8,4 +8,4 @@ COPY --link . /composition
8
8
 
9
9
  # no USER: the runtime drops to `node` itself, and only a process that started as root can
10
10
  # close its environment under /proc — see runtime/runtime/bin/toa
11
- CMD toa mono *
11
+ CMD toa mono * --map {{map.file}}
@@ -23,4 +23,4 @@ RUN --mount=type=cache,target=/root/.npm,sharing=locked \
23
23
 
24
24
  # no USER: the runtime drops to `node` itself, and only a process that started as root can
25
25
  # close its environment under /proc — see runtime/runtime/bin/toa
26
- CMD toa serve .
26
+ CMD toa serve . --map {{map.file}}