@toa.io/operations 1.0.0-alpha.274 → 1.0.0-alpha.277

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +8 -7
  3. package/src/deployment/.deployment/.describe/components.js +1 -5
  4. package/src/deployment/.deployment/.describe/compositions.js +3 -7
  5. package/src/deployment/.deployment/.describe/dependencies.js +1 -6
  6. package/src/deployment/.deployment/.describe/events.js +1 -5
  7. package/src/deployment/.deployment/.describe/index.js +4 -13
  8. package/src/deployment/.deployment/.describe/mounts.js +1 -5
  9. package/src/deployment/.deployment/.describe/resources.js +1 -5
  10. package/src/deployment/.deployment/.describe/services.js +2 -6
  11. package/src/deployment/.deployment/.describe/services.test.js +11 -11
  12. package/src/deployment/.deployment/.describe/variables.js +1 -5
  13. package/src/deployment/.deployment/declare.js +1 -5
  14. package/src/deployment/.deployment/describe.js +10 -10
  15. package/src/deployment/.deployment/index.js +3 -9
  16. package/src/deployment/.deployment/merge.js +1 -5
  17. package/src/deployment/.deployment/merge.test.js +10 -12
  18. package/src/deployment/chart/templates/mono.yaml +4 -0
  19. package/src/deployment/chart/templates/services.yaml +4 -0
  20. package/src/deployment/composition.js +1 -5
  21. package/src/deployment/deployment.js +10 -11
  22. package/src/deployment/factory.js +28 -22
  23. package/src/deployment/images/composition.Dockerfile +1 -1
  24. package/src/deployment/images/composition.js +11 -11
  25. package/src/deployment/images/factory.js +4 -8
  26. package/src/deployment/images/format.js +48 -0
  27. package/src/deployment/images/format.test.js +74 -0
  28. package/src/deployment/images/image.fixtures.js +11 -11
  29. package/src/deployment/images/image.js +7 -18
  30. package/src/deployment/images/image.test.js +6 -5
  31. package/src/deployment/images/index.js +1 -5
  32. package/src/deployment/images/mono.Dockerfile +1 -1
  33. package/src/deployment/images/mono.js +13 -12
  34. package/src/deployment/images/runtime-base.test.js +15 -14
  35. package/src/deployment/images/service.js +8 -8
  36. package/src/deployment/index.js +1 -5
  37. package/src/deployment/operator.js +2 -6
  38. package/src/deployment/operator.test.js +8 -7
  39. package/src/deployment/registry.js +3 -7
  40. package/src/deployment/registry.test.js +39 -37
  41. package/src/deployment/service.js +1 -5
  42. package/src/deployment/workspace.js +4 -8
  43. package/src/index.js +1 -3
  44. package/src/process.js +2 -6
  45. package/types/_deployment/composition.d.ts +1 -1
  46. package/types/_deployment/dependency.d.ts +1 -1
  47. package/types/_deployment/deployment.d.ts +3 -3
  48. package/types/_deployment/factory.d.ts +2 -2
  49. package/types/_deployment/images/factory.d.ts +2 -2
  50. package/types/_deployment/images/registry.d.ts +2 -2
  51. package/types/_deployment/operator.d.ts +2 -2
  52. package/types/_deployment/registry.d.ts +2 -2
  53. package/types/_deployment/service.d.ts +4 -1
  54. package/types/dependency.ts +2 -0
  55. package/types/index.ts +1 -1
@@ -1,10 +1,8 @@
1
- 'use strict'
1
+ import { Composition } from './composition.js'
2
+ import { Service } from './service.js'
3
+ import { Mono } from './mono.js'
2
4
 
3
- const { Composition } = require('./composition')
4
- const { Service } = require('./service')
5
- const { Mono } = require('./mono')
6
-
7
- class Factory {
5
+ export class Factory {
8
6
  /** @type {string} */
9
7
  #scope
10
8
 
@@ -58,5 +56,3 @@ class Factory {
58
56
  return instance
59
57
  }
60
58
  }
61
-
62
- exports.Factory = Factory
@@ -0,0 +1,48 @@
1
+ import { existsSync, readFileSync } from 'node:fs'
2
+ import { writeFile } from 'node:fs/promises'
3
+ import { dirname, join, parse } from 'node:path'
4
+
5
+ /**
6
+ * A component is copied into the image on its own, away from the package that
7
+ * declared what its files are. Node reads a `.js` as CommonJS unless a manifest
8
+ * beside it says otherwise, so the one the component was written under is
9
+ * restated where it lands.
10
+ *
11
+ * A component that ships its own manifest already says so, and is left alone.
12
+ *
13
+ * @param {string} source the component in the workspace
14
+ * @param {string} target where it was copied
15
+ * @param {string} name
16
+ */
17
+ export async function declare (source, target, name) {
18
+ if (existsSync(join(target, MANIFEST))) return
19
+
20
+ await writeFile(join(target, MANIFEST),
21
+ JSON.stringify({ name, private: true, type: format(source) }, null, 2) + '\n')
22
+ }
23
+
24
+ /**
25
+ * The module format a directory's files are read as, which the nearest manifest
26
+ * above it decides.
27
+ *
28
+ * @param {string} directory
29
+ * @returns {'module' | 'commonjs'}
30
+ */
31
+ export function format (directory) {
32
+ const { root } = parse(directory)
33
+
34
+ let current = directory
35
+
36
+ while (current !== root) {
37
+ const manifest = join(current, MANIFEST)
38
+
39
+ if (existsSync(manifest))
40
+ return JSON.parse(readFileSync(manifest, 'utf8')).type === 'module' ? 'module' : 'commonjs'
41
+
42
+ current = dirname(current)
43
+ }
44
+
45
+ return 'commonjs'
46
+ }
47
+
48
+ const MANIFEST = 'package.json'
@@ -0,0 +1,74 @@
1
+ import { it, describe, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { mkdtemp, mkdir, writeFile, readFile, rm } from 'node:fs/promises'
4
+ import { tmpdir } from 'node:os'
5
+ import { join } from 'node:path'
6
+
7
+ import { declare, format } from './format.js'
8
+
9
+ let root
10
+
11
+ before(async () => {
12
+ root = await mkdtemp(join(tmpdir(), 'format-'))
13
+ })
14
+
15
+ after(async () => {
16
+ await rm(root, { recursive: true, force: true })
17
+ })
18
+
19
+ describe('format', () => {
20
+ it('should read the nearest manifest above', async () => {
21
+ const workspace = join(root, 'modules')
22
+ const component = join(workspace, 'components', 'one')
23
+
24
+ await mkdir(component, { recursive: true })
25
+ await writeFile(join(workspace, 'package.json'), JSON.stringify({ type: 'module' }))
26
+
27
+ assert.strictEqual(format(component), 'module')
28
+ })
29
+
30
+ it('should default to commonjs', async () => {
31
+ const workspace = join(root, 'scripts')
32
+ const component = join(workspace, 'components', 'one')
33
+
34
+ await mkdir(component, { recursive: true })
35
+ await writeFile(join(workspace, 'package.json'), JSON.stringify({ name: 'scripts' }))
36
+
37
+ assert.strictEqual(format(component), 'commonjs')
38
+ })
39
+ })
40
+
41
+ describe('declare', () => {
42
+ it('should state the format the component was written under', async () => {
43
+ const workspace = join(root, 'stated')
44
+ const source = join(workspace, 'components', 'one')
45
+ const target = join(root, 'image', 'one')
46
+
47
+ await mkdir(source, { recursive: true })
48
+ await mkdir(target, { recursive: true })
49
+ await writeFile(join(workspace, 'package.json'), JSON.stringify({ type: 'module' }))
50
+
51
+ await declare(source, target, 'default-one')
52
+
53
+ const manifest = JSON.parse(await readFile(join(target, 'package.json'), 'utf8'))
54
+
55
+ assert.strictEqual(manifest.type, 'module')
56
+ assert.strictEqual(manifest.name, 'default-one')
57
+ assert.strictEqual(manifest.private, true)
58
+ })
59
+
60
+ it('should leave a manifest the component ships alone', async () => {
61
+ const source = join(root, 'own', 'components', 'one')
62
+ const target = join(root, 'image', 'own')
63
+
64
+ await mkdir(source, { recursive: true })
65
+ await mkdir(target, { recursive: true })
66
+
67
+ const own = JSON.stringify({ name: 'own', dependencies: { matchacho: '0.6.0' } })
68
+
69
+ await writeFile(join(target, 'package.json'), own)
70
+ await declare(source, target, 'default-own')
71
+
72
+ assert.strictEqual(await readFile(join(target, 'package.json'), 'utf8'), own)
73
+ })
74
+ })
@@ -1,7 +1,5 @@
1
- 'use strict'
2
-
3
- const { Image } = require('./image')
4
- const { generate } = require('randomstring')
1
+ import { Image } from './image.js'
2
+ import { generate } from 'randomstring'
5
3
 
6
4
  const version = '168b04ff'
7
5
  const name = generate()
@@ -29,10 +27,12 @@ const registry = {
29
27
  base: 'node:alpine'
30
28
  }
31
29
 
32
- exports.scope = generate()
33
- exports.name = name
34
- exports.version = 'ba2409fc'
35
- exports.Class = Class
36
- exports.runtime = runtime
37
- exports.registry = registry
38
- exports.process = process
30
+ export const scope = generate()
31
+
32
+ // distinct from the module's own `version` above
33
+ const published = 'ba2409fc'
34
+
35
+ // the fixture stands in for the global process
36
+ const current = process
37
+
38
+ export { name, Class, runtime, registry, current as process, published as version }
@@ -1,23 +1,15 @@
1
- 'use strict'
1
+ import { join, posix } from 'node:path'
2
+ import { readFile as read, writeFile as write } from 'node:fs/promises'
3
+ import { createHash } from 'node:crypto'
2
4
 
3
- const {
4
- join,
5
- posix
6
- } = require('node:path')
7
- const {
8
- readFile: read,
9
- writeFile: write
10
- } = require('node:fs/promises')
11
- const { createHash } = require('node:crypto')
12
-
13
- const { overwrite } = require('@toa.io/generic')
14
- const { mkdir } = require('node:fs/promises')
5
+ import { overwrite } from '@toa.io/generic'
6
+ import { mkdir } from 'node:fs/promises'
15
7
 
16
8
  /**
17
9
  * @implements {toa.deployment.images.Image}
18
10
  * @abstract
19
11
  */
20
- class Image {
12
+ export class Image {
21
13
  context
22
14
  reference
23
15
  dockerfile
@@ -127,7 +119,4 @@ function createArguments (variables) {
127
119
  return args.join('\n')
128
120
  }
129
121
 
130
- const RUNTIME_IMAGE = 'ghcr.io/toa-io/runtime'
131
-
132
- exports.Image = Image
133
- exports.RUNTIME_IMAGE = RUNTIME_IMAGE
122
+ export const RUNTIME_IMAGE = 'ghcr.io/toa-io/runtime'
@@ -1,7 +1,8 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const fixtures = require('./image.fixtures')
4
- const { generate } = require('randomstring')
4
+ import * as fixtures from './image.fixtures.js'
5
+ import { generate } from 'randomstring'
5
6
 
6
7
  /** @type {toa.deployment.images.Image} */
7
8
  let instance
@@ -13,11 +14,11 @@ beforeEach(() => {
13
14
  it('should assign url', () => {
14
15
  instance.tag()
15
16
 
16
- expect(instance.reference).toEqual(`${fixtures.registry.base}/${fixtures.scope}/${fixtures.name}:${fixtures.version}`)
17
+ assert.deepStrictEqual(instance.reference, `${fixtures.registry.base}/${fixtures.scope}/${fixtures.name}:${fixtures.version}`)
17
18
  })
18
19
 
19
20
  describe('prepare', () => {
20
21
  it('should throw error if no dockerfile specified', async () => {
21
- await expect(instance.prepare(generate())).rejects.toThrow(/Dockerfile isn't specified/)
22
+ await assert.rejects(instance.prepare(generate()), (error) => /Dockerfile isn't specified/.test(error.message))
22
23
  })
23
24
  })
@@ -1,5 +1 @@
1
- 'use strict'
2
-
3
- const { Factory } = require('./factory')
4
-
5
- exports.Factory = Factory
1
+ export { Factory } from './factory.js'
@@ -12,7 +12,7 @@ COPY --chown=node:node . /composition
12
12
  {{build.run}}
13
13
 
14
14
  RUN --mount=type=cache,target=/root/.npm \
15
- for entry in *; do if [ -f "$entry/package.json" ]; then (cd $entry && npm i --omit=dev); fi; done
15
+ for entry in *; do if grep -qs '"dependencies"' "$entry/package.json"; then (cd $entry && npm i --omit=dev); fi; done
16
16
 
17
17
  USER node
18
18
  CMD toa mono *
@@ -1,13 +1,12 @@
1
- 'use strict'
1
+ import { join } from 'node:path'
2
+ import fs from 'fs-extra'
3
+ import { createHash } from 'node:crypto'
2
4
 
3
- const { join } = require('node:path')
4
- const fs = require('fs-extra')
5
- const { createHash } = require('node:crypto')
5
+ import { Image } from './image.js'
6
+ import { declare } from './format.js'
6
7
 
7
- const { Image } = require('./image')
8
-
9
- class Mono extends Image {
10
- dockerfile = join(__dirname, 'mono.Dockerfile')
8
+ export class Mono extends Image {
9
+ dockerfile = join(import.meta.dirname, 'mono.Dockerfile')
11
10
 
12
11
  #image
13
12
  #components
@@ -61,11 +60,13 @@ class Mono extends Image {
61
60
  async prepare (root) {
62
61
  const context = await super.prepare(root)
63
62
 
64
- for (const component of this.#components)
65
- await fs.copy(component.path, join(context, component.locator.label))
63
+ for (const component of this.#components) {
64
+ const target = join(context, component.locator.label)
65
+
66
+ await fs.copy(component.path, target)
67
+ await declare(component.path, target, component.locator.label)
68
+ }
66
69
 
67
70
  return context
68
71
  }
69
72
  }
70
-
71
- exports.Mono = Mono
@@ -1,13 +1,14 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { join } = require('node:path')
4
- const { mkdtemp, readFile } = require('node:fs/promises')
5
- const { tmpdir } = require('node:os')
4
+ import { join } from 'node:path'
5
+ import { mkdtemp, readFile } from 'node:fs/promises'
6
+ import { tmpdir } from 'node:os'
6
7
 
7
- const { Image, RUNTIME_IMAGE } = require('./image')
8
+ import { Image, RUNTIME_IMAGE } from './image.js'
8
9
 
9
- const compositionDockerfile = join(__dirname, 'composition.Dockerfile')
10
- const serviceDockerfile = join(__dirname, 'service.Dockerfile')
10
+ const compositionDockerfile = join(import.meta.dirname, 'composition.Dockerfile')
11
+ const serviceDockerfile = join(import.meta.dirname, 'service.Dockerfile')
11
12
 
12
13
  class TestImage extends Image {
13
14
  dockerfile
@@ -51,8 +52,8 @@ describe('runtime base image', () => {
51
52
  const path = await image.prepare(root)
52
53
  const dockerfile = await readFile(join(path, 'Dockerfile'), 'utf8')
53
54
 
54
- expect(dockerfile).toContain(`FROM ${RUNTIME_IMAGE}:1.0.0-alpha.232`)
55
- expect(dockerfile).not.toMatch(/npm i -g @toa\.io\/runtime/)
55
+ assert.ok(dockerfile.includes(`FROM ${RUNTIME_IMAGE}:1.0.0-alpha.232`))
56
+ assert.doesNotMatch(dockerfile, /npm i -g @toa\.io\/runtime/)
56
57
  })
57
58
 
58
59
  it('should not install runtime in service Dockerfile template', async () => {
@@ -62,8 +63,8 @@ describe('runtime base image', () => {
62
63
  const path = await image.prepare(root)
63
64
  const dockerfile = await readFile(join(path, 'Dockerfile'), 'utf8')
64
65
 
65
- expect(dockerfile).toContain(`FROM ${RUNTIME_IMAGE}:1.0.0-alpha.99`)
66
- expect(dockerfile).not.toMatch(/npm i -g @toa\.io\/runtime/)
66
+ assert.ok(dockerfile.includes(`FROM ${RUNTIME_IMAGE}:1.0.0-alpha.99`))
67
+ assert.doesNotMatch(dockerfile, /npm i -g @toa\.io\/runtime/)
67
68
  })
68
69
 
69
70
  it('should allow registry.build.image override', async () => {
@@ -74,8 +75,8 @@ describe('runtime base image', () => {
74
75
  const path = await image.prepare(root)
75
76
  const dockerfile = await readFile(join(path, 'Dockerfile'), 'utf8')
76
77
 
77
- expect(dockerfile).toContain('FROM node:24.14.0-alpine3.22')
78
- expect(dockerfile).not.toContain(RUNTIME_IMAGE)
78
+ assert.ok(dockerfile.includes('FROM node:24.14.0-alpine3.22'))
79
+ assert.ok(!(dockerfile.includes(RUNTIME_IMAGE)))
79
80
  })
80
81
 
81
82
  it('should allow composition.image override via base', async () => {
@@ -85,6 +86,6 @@ describe('runtime base image', () => {
85
86
  const path = await image.prepare(root)
86
87
  const dockerfile = await readFile(join(path, 'Dockerfile'), 'utf8')
87
88
 
88
- expect(dockerfile).toContain('FROM custom.example/base:1')
89
+ assert.ok(dockerfile.includes('FROM custom.example/base:1'))
89
90
  })
90
91
  })
@@ -1,12 +1,14 @@
1
- 'use strict'
1
+ import { createRequire } from 'node:module'
2
+ import { join, dirname } from 'node:path'
2
3
 
3
- const { join, dirname } = require('node:path')
4
+ import { Image } from './image.js'
5
+ import fs from 'fs-extra'
4
6
 
5
- const { Image } = require('./image')
6
- const fs = require('fs-extra')
7
+ // a service is named the way a package is, and its directory is where it lives
8
+ const require = createRequire(import.meta.url)
7
9
 
8
- class Service extends Image {
9
- dockerfile = join(__dirname, 'service.Dockerfile')
10
+ export class Service extends Image {
11
+ dockerfile = join(import.meta.dirname, 'service.Dockerfile')
10
12
 
11
13
  /**
12
14
  * Used by Dockerfile
@@ -70,5 +72,3 @@ class Service extends Image {
70
72
  const find = (reference) => {
71
73
  return dirname(require.resolve(join(reference, 'package.json')))
72
74
  }
73
-
74
- exports.Service = Service
@@ -1,5 +1 @@
1
- 'use strict'
2
-
3
- const { Factory } = require('./factory')
4
-
5
- exports.Factory = Factory
1
+ export { Factory } from './factory.js'
@@ -1,8 +1,6 @@
1
- 'use strict'
1
+ import * as workspace from './workspace.js'
2
2
 
3
- const workspace = require('./workspace')
4
-
5
- class Operator {
3
+ export class Operator {
6
4
  /** @type {toa.deployment.Deployment} */
7
5
  #deployment
8
6
 
@@ -58,5 +56,3 @@ class Operator {
58
56
 
59
57
  /** @type {toa.deployment.installation.Options} */
60
58
  const OPTIONS = { wait: false }
61
-
62
- exports.Operator = Operator
@@ -1,10 +1,11 @@
1
- 'use strict'
1
+ import { describe, it, beforeEach, mock } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { Operator } = require('../../src/deployment/operator')
4
- const { generate } = require('randomstring')
4
+ import { Operator } from '../../src/deployment/operator.js'
5
+ import { generate } from 'randomstring'
5
6
 
6
7
  it('should be', async () => {
7
- expect(Operator).toBeInstanceOf(Function)
8
+ assert.ok(Operator instanceof Function)
8
9
  })
9
10
 
10
11
  /** @type {toa.deployment.Operator} */
@@ -25,7 +26,7 @@ describe('env', () => {
25
26
  it('should be', async () => {
26
27
  operator = new Operator(deployment, registry)
27
28
 
28
- expect(operator.variables).toBeInstanceOf(Function)
29
+ assert.ok(operator.variables instanceof Function)
29
30
  })
30
31
 
31
32
  it('should return variables', async () => {
@@ -33,12 +34,12 @@ describe('env', () => {
33
34
 
34
35
  deployment.variables =
35
36
  /** @type {typeof toa.deployment.Operator.variables} */
36
- jest.fn(() => variables)
37
+ mock.fn(() => variables)
37
38
 
38
39
  operator = new Operator(deployment, registry)
39
40
 
40
41
  const output = operator.variables()
41
42
 
42
- expect(output).toStrictEqual(variables)
43
+ assert.deepStrictEqual(output, variables)
43
44
  })
44
45
  })
@@ -1,12 +1,10 @@
1
- 'use strict'
2
-
3
- const { posix } = require('node:path')
4
- const workspace = require('./workspace')
1
+ import { posix } from 'node:path'
2
+ import * as workspace from './workspace.js'
5
3
 
6
4
  /**
7
5
  * @implements {toa.deployment.Registry}
8
6
  */
9
- class Registry {
7
+ export class Registry {
10
8
  #scope
11
9
 
12
10
  #registry
@@ -165,5 +163,3 @@ class Registry {
165
163
  }
166
164
 
167
165
  const BUILDER = 'toa'
168
-
169
- exports.Registry = Registry
@@ -1,6 +1,8 @@
1
- 'use strict'
1
+ import { it, beforeEach, mock } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { isDeepStrictEqual } from 'node:util'
2
4
 
3
- const { Registry } = require('./registry')
5
+ import { Registry } from './registry.js'
4
6
 
5
7
  /** @type {toa.operations.Process} */
6
8
  let process
@@ -14,7 +16,7 @@ let images
14
16
  beforeEach(() => {
15
17
  images = []
16
18
  process = /** @type {toa.operations.Process} */ {
17
- execute: jest.fn(async (cmd, args) => {
19
+ execute: mock.fn(async (cmd, args) => {
18
20
  if (args[0] === 'manifest')
19
21
  throw new Error('manifest unknown')
20
22
 
@@ -39,25 +41,25 @@ it('should reuse named builder across images', async () => {
39
41
 
40
42
  await registry.build()
41
43
 
42
- const creates = process.execute.mock.calls.filter(([, args]) =>
44
+ const creates = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
43
45
  args[0] === 'buildx' && args[1] === 'create')
44
46
 
45
- expect(creates).toHaveLength(1)
46
- expect(creates[0][1]).toEqual(['buildx', 'create', '--name', 'toa', '--bootstrap'])
47
+ assert.strictEqual(creates.length, 1)
48
+ assert.deepStrictEqual(creates[0].arguments[1], ['buildx', 'create', '--name', 'toa', '--bootstrap'])
47
49
 
48
- const builds = process.execute.mock.calls.filter(([, args]) =>
50
+ const builds = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
49
51
  args[0] === '--context=default' && args[1] === 'buildx' && args[2] === 'build')
50
52
 
51
- expect(builds).toHaveLength(2)
53
+ assert.strictEqual(builds.length, 2)
52
54
 
53
- for (const [, args] of builds) {
54
- expect(args).toContain('--builder')
55
- expect(args[args.indexOf('--builder') + 1]).toBe('toa')
55
+ for (const { arguments: [, args] } of builds) {
56
+ assert.ok(args.includes('--builder'))
57
+ assert.strictEqual(args[args.indexOf('--builder') + 1], 'toa')
56
58
  }
57
59
  })
58
60
 
59
61
  it('should not create builder when it already exists', async () => {
60
- process.execute = jest.fn(async (cmd, args) => {
62
+ process.execute = mock.fn(async (cmd, args) => {
61
63
  if (args[0] === 'manifest')
62
64
  throw new Error('manifest unknown')
63
65
 
@@ -70,10 +72,10 @@ it('should not create builder when it already exists', async () => {
70
72
 
71
73
  await registry.build()
72
74
 
73
- const creates = process.execute.mock.calls.filter(([, args]) =>
75
+ const creates = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
74
76
  args[0] === 'buildx' && args[1] === 'create')
75
77
 
76
- expect(creates).toHaveLength(0)
78
+ assert.strictEqual(creates.length, 0)
77
79
  })
78
80
 
79
81
  it('should add shared registry cache flags when base is set', async () => {
@@ -84,16 +86,16 @@ it('should add shared registry cache flags when base is set', async () => {
84
86
 
85
87
  await registry.build()
86
88
 
87
- const builds = process.execute.mock.calls.filter(([, args]) =>
89
+ const builds = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
88
90
  args[0] === '--context=default' && args[2] === 'build')
89
91
 
90
- expect(builds).toHaveLength(2)
92
+ assert.strictEqual(builds.length, 2)
91
93
 
92
- for (const [, args] of builds) {
93
- expect(args).toContain('--cache-from')
94
- expect(args).toContain('type=registry,ref=example.com/reg/acme/buildcache')
95
- expect(args).toContain('--cache-to')
96
- expect(args).toContain('type=registry,ref=example.com/reg/acme/buildcache,mode=max,image-manifest=true')
94
+ for (const { arguments: [, args] } of builds) {
95
+ assert.ok(args.includes('--cache-from'))
96
+ assert.ok(args.includes('type=registry,ref=example.com/reg/acme/buildcache'))
97
+ assert.ok(args.includes('--cache-to'))
98
+ assert.ok(args.includes('type=registry,ref=example.com/reg/acme/buildcache,mode=max,image-manifest=true'))
97
99
  }
98
100
  })
99
101
 
@@ -104,15 +106,15 @@ it('should omit cache flags when base is not set', async () => {
104
106
 
105
107
  await registry.build()
106
108
 
107
- const builds = process.execute.mock.calls.filter(([, args]) =>
109
+ const builds = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
108
110
  args[0] === '--context=default' && args[2] === 'build')
109
111
 
110
- expect(builds).toHaveLength(1)
112
+ assert.strictEqual(builds.length, 1)
111
113
 
112
- const [, args] = builds[0]
114
+ const { arguments: [, args] } = builds[0]
113
115
 
114
- expect(args).not.toContain('--cache-from')
115
- expect(args).not.toContain('--cache-to')
116
+ assert.ok(!(args.includes('--cache-from')))
117
+ assert.ok(!(args.includes('--cache-to')))
116
118
  })
117
119
 
118
120
  it('should use default builder when platforms is null', async () => {
@@ -122,20 +124,20 @@ it('should use default builder when platforms is null', async () => {
122
124
 
123
125
  await registry.build()
124
126
 
125
- const builds = process.execute.mock.calls.filter(([, args]) =>
127
+ const builds = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
126
128
  args[0] === '--context=default' && args[2] === 'build')
127
129
 
128
- expect(builds).toHaveLength(1)
130
+ assert.strictEqual(builds.length, 1)
129
131
 
130
- const [, args] = builds[0]
132
+ const { arguments: [, args] } = builds[0]
131
133
 
132
- expect(args[args.indexOf('--builder') + 1]).toBe('default')
133
- expect(args).not.toContain('--cache-from')
134
- expect(args).not.toContain('--platform')
134
+ assert.strictEqual(args[args.indexOf('--builder') + 1], 'default')
135
+ assert.ok(!(args.includes('--cache-from')))
136
+ assert.ok(!(args.includes('--platform')))
135
137
  })
136
138
 
137
139
  it('should skip build when image already exists', async () => {
138
- process.execute = jest.fn(async () => '')
140
+ process.execute = mock.fn(async () => '')
139
141
 
140
142
  const registry = createRegistry({ base: 'example.com/reg', platforms: ['linux/amd64'] })
141
143
 
@@ -143,11 +145,11 @@ it('should skip build when image already exists', async () => {
143
145
 
144
146
  await registry.build()
145
147
 
146
- const builds = process.execute.mock.calls.filter(([, args]) =>
148
+ const builds = process.execute.mock.calls.filter(({ arguments: [, args] }) =>
147
149
  args[0] === '--context=default' && args[2] === 'build')
148
150
 
149
- expect(builds).toHaveLength(0)
150
- expect(process.execute).toHaveBeenCalledWith('docker', ['manifest', 'inspect', images[0].reference], { silently: true })
151
+ assert.strictEqual(builds.length, 0)
152
+ assert.ok(process.execute.mock.calls.some((call) => call.arguments.length === 3 && isDeepStrictEqual(call.arguments[0], 'docker') && isDeepStrictEqual(call.arguments[1], ['manifest', 'inspect', images[0].reference]) && isDeepStrictEqual(call.arguments[2], { silently: true })))
151
153
  })
152
154
 
153
155
  /**
@@ -166,7 +168,7 @@ function createImage (name) {
166
168
  const image = /** @type {toa.deployment.images.Image} */ {
167
169
  reference: `example.com/reg/acme/${name}:abcdef12`,
168
170
  context: `/tmp/${name}`,
169
- prepare: jest.fn(async () => `/tmp/${name}`)
171
+ prepare: mock.fn(async () => `/tmp/${name}`)
170
172
  }
171
173
 
172
174
  images.push(image)
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- class Service {
1
+ export class Service {
4
2
  constructor (service, image) {
5
3
  Object.assign(this, service)
6
4
 
@@ -8,5 +6,3 @@ class Service {
8
6
  this.image = image.reference
9
7
  }
10
8
  }
11
-
12
- exports.Service = Service