@codedependant/semantic-release-docker 4.3.0 → 4.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Semantic Release Docker
2
2
 
3
+ # [4.4.0](https://github.com/esatterwhite/semantic-release-docker/compare/v4.3.0...v4.4.0) (2023-07-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * **image**: add support for cache-from build flag [efae32d](https://github.com/esatterwhite/semantic-release-docker/commit/efae32d760bc0ef1978ad97f834b4cb034199ace) - Eric Satterwhite, closes: [#35](https://github.com/esatterwhite/semantic-release-docker/issues/35)
9
+ * **image**: support arbitrary build flags [d7e875d](https://github.com/esatterwhite/semantic-release-docker/commit/d7e875d2b0b8de58e57c56e9ba24bf3c2db5df84) - Eric Satterwhite
10
+
3
11
  # [4.3.0](https://github.com/esatterwhite/semantic-release-docker/compare/v4.2.0...v4.3.0) (2022-12-29)
4
12
 
5
13
 
package/README.md CHANGED
@@ -42,20 +42,22 @@ omitted, it is assumed the docker daemon is already authenticated with the targe
42
42
 
43
43
  ### Options
44
44
 
45
- | Option | Description | Type | Default |
46
- |-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|---------------------------------------------------------------|
47
- | `dockerTags` | _Optional_. An array of strings allowing to specify additional tags to apply to the image. Supports templating | [Array][]<[String][]> | [`latest`, `{{major}}-latest`, `{{version}}`] |
48
- | `dockerImage` | _Optional_. The name of the image to release. | [String][] | Parsed from package.json `name` property |
49
- | `dockerRegistry` | _Optional_. The hostname and port used by the the registry in format `hostname[:port]`. Omit the port if the registry uses the default port | [String][] | `null` (dockerhub) |
50
- | `dockerProject` | _Optional_. The project or repository name to publish the image to | [String][] | For scoped packages, the scope will be used, otherwise `null` |
51
- | `dockerFile` | _Optional_. The path, relative to `$PWD` to a Docker file to build the target image with | [String][] | `Dockerfile` |
52
- | `dockerContext` | _Optional_. A path, relative to `$PWD` to use as the build context A | [String][] | `.` |
53
- | `dockerLogin` | _Optional_. Set to false it by pass docker login if the docker daemon is already authorized | [String][] | `true` |
54
- | `dockerArgs` | _Optional_. Include additional values for docker's `build-arg`. Supports templating | [Object][] | |
55
- | `dockerPublish` | _Optional_. Automatically push image tags during the publish phase. | [Boolean][] | `true` |
56
- | `dockerVerifyCmd` | _Optional_. If specified, during the verify stage, the specified command will execute in a container of the build image. If the command errors, the release will fail. | [String][] | `false` |
57
- | `dockerNetwork` | _Optional_. Specify the Docker network to use while the image is building. | [String][] | `default` |
58
- | `dockerAutoClean` | _Optional_. If set to true | [Boolean][] | `true` |
45
+ | Option | Description | Type | Default |
46
+ |------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|---------------------------------------------------------------|
47
+ | `dockerTags` | _Optional_. An array of strings allowing to specify additional tags to apply to the image. Supports templating | [Array][]<[String][]> | [`latest`, `{{major}}-latest`, `{{version}}`] |
48
+ | `dockerImage` | _Optional_. The name of the image to release. | [String][] | Parsed from package.json `name` property |
49
+ | `dockerRegistry` | _Optional_. The hostname and port used by the the registry in format `hostname[:port]`. Omit the port if the registry uses the default port | [String][] | `null` (dockerhub) |
50
+ | `dockerProject` | _Optional_. The project or repository name to publish the image to | [String][] | For scoped packages, the scope will be used, otherwise `null` |
51
+ | `dockerFile` | _Optional_. The path, relative to `$PWD` to a Docker file to build the target image with | [String][] | `Dockerfile` |
52
+ | `dockerContext` | _Optional_. A path, relative to `$PWD` to use as the build context A | [String][] | `.` |
53
+ | `dockerLogin` | _Optional_. Set to false it by pass docker login if the docker daemon is already authorized | [String][] | `true` |
54
+ | `dockerArgs` | _Optional_. Include additional values for docker's `build-arg`. Supports templating | [Object][] | |
55
+ | `dockerPublish` | _Optional_. Automatically push image tags during the publish phase. | [Boolean][] | `true` |
56
+ | `dockerVerifyCmd` | _Optional_. If specified, during the verify stage, the specified command will execute in a container of the build image. If the command errors, the release will fail. | [String][] | `false` |
57
+ | `dockerNetwork` | _Optional_. Specify the Docker network to use while the image is building. | [String][] | `default` |
58
+ | `dockerAutoClean` | _Optional_. If set to true | [Boolean][] | `true` |
59
+ | `dockerBuildFlags` | _Optional_. An object containing additional flags to the `docker build` command. Values can be strings or an array of strings | [Object][] | `{}` |
60
+ | `dockerBuildCacheFrom` | _Optional_. A list of external cache sources. See [--cache-from][] | [String][] | [Array][]<[String][]> | |
59
61
 
60
62
  ### Build Arguments
61
63
 
@@ -117,7 +119,50 @@ The following handlebars template helpers are pre installed
117
119
  | `startswith` | returns true if a string starts with another | [Boolean][] | <pre lang="hbs">{{#if (starts myvar 'foo')}}{{ othervar }}{{/if}}</pre> |
118
120
  | `upper` | returns the upper cased varient of the input string | [String][] | <pre lang="hbs">{{upper my_var}}</pre> |
119
121
 
122
+ ### Build Flags
120
123
 
124
+ Using the `dockerBuildFlags` option allows you to pass arbitrary flags to the build command.
125
+ If the standardized options are not sufficient, `dockerBuildFlags` is a perfect workaround
126
+ until first class support can be added. This is considered and advanced feature, and you should
127
+ know what you intend to do before using. There is no validation, and any configuration of the
128
+ docker daemon required is expected to be done before hand.
129
+
130
+ Keys found in `dockerBuildFlags` are normalized as command line flags in the following manner:
131
+
132
+ * If the key does not start with a `-` it will be prepended
133
+ * all occurences of `_` will be re-written as `-`
134
+ * Single letter keys are considered shorthands e.g. `p` becomes `-p`
135
+ * Multi letter keys are considered long form e.g. `foo_bar` becomes `--foo-bar`
136
+ * If the value is an array, the flag is repeated for each occurance
137
+ * A `null` value may be used to omit the value and only inject the flag itself
138
+
139
+ #### Example
140
+
141
+ ```javascript
142
+ {
143
+ plugins: [
144
+ ['@codedependant/semantic-release-docker', {
145
+ dockerImage: 'my-image',
146
+ dockerRegistry: 'quay.io',
147
+ dockerProject: 'codedependant',
148
+ dockerCacheFrom: 'myname/myapp'
149
+ dockerBuildFlags: {
150
+ pull: null
151
+ , target: 'release'
152
+ },
153
+ dockerArgs: {
154
+ GITHUB_TOKEN: null
155
+ }
156
+ }]
157
+ ]
158
+ }
159
+ ```
160
+
161
+ This configuration, will generate the following build command
162
+
163
+ ```bash
164
+ > docker build --network=default --quiet --tag quay.io/codedependant/my-image:abc123 --cache-from myname/myapp --build-arg GITHUB_TOKEN --pull --target release -f path/to/repo/Dockerfile /path/to/repo
165
+ ```
121
166
 
122
167
  ## Usage
123
168
 
@@ -135,8 +180,12 @@ module.exports = {
135
180
  dockerFile: 'Dockerfile',
136
181
  dockerRegistry: 'quay.io',
137
182
  dockerProject: 'codedependant',
183
+ dockerBuildFlags: {
184
+ pull: null
185
+ , target: 'release'
186
+ },
138
187
  dockerArgs: {
139
- API_TOKEN: true
188
+ API_TOKEN: null
140
189
  , RELEASE_DATE: new Date().toISOString()
141
190
  , RELEASE_VERSION: '{{next.version}}'
142
191
  }
@@ -233,3 +282,4 @@ $ openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout server.key -o
233
282
  [Array]: https://mdn.io/array
234
283
  [Object]: https://mdn.io/object
235
284
  [Number]: https://mdn.io/number
285
+ [--cache-from]: https://docs.docker.com/engine/reference/commandline/build/#cache-from
@@ -16,6 +16,8 @@ async function buildConfig(build_id, config, context) {
16
16
  , dockerNoCache: nocache = false
17
17
  , dockerTags: tags = ['latest', '{{major}}-latest', '{{version}}']
18
18
  , dockerArgs: args = {}
19
+ , dockerBuildFlags: build_flags = {}
20
+ , dockerBuildCacheFrom: cache_from
19
21
  , dockerRegistry: registry = null
20
22
  , dockerLogin: login = true
21
23
  , dockerImage: image
@@ -40,10 +42,14 @@ async function buildConfig(build_id, config, context) {
40
42
  const root = object.get(context, 'options.root')
41
43
  const target = path.relative(root || context.cwd, context.cwd) || PWD
42
44
  const {nextRelease = {}} = context
45
+
46
+ if (cache_from) build_flags.cache_from = array.toArray(cache_from)
47
+
43
48
  return {
44
49
  registry
45
50
  , dockerfile
46
51
  , nocache
52
+ , build_flags
47
53
  , pkg
48
54
  , project
49
55
  , publish
@@ -26,15 +26,16 @@ class Image {
26
26
 
27
27
  this.sha = sha
28
28
  this.opts = {
29
- args: new Map()
30
- , registry: registry
31
- , project: project
32
- , name: name
33
- , build_id: build_id
34
- , dockerfile: dockerfile
29
+ build_id: build_id
30
+ , args: new Map()
35
31
  , context: context
36
32
  , cwd: cwd
33
+ , dockerfile: dockerfile
34
+ , flags: new Map()
35
+ , name: name
37
36
  , network: network
37
+ , project: project
38
+ , registry: registry
38
39
  }
39
40
  }
40
41
 
@@ -72,27 +73,66 @@ class Image {
72
73
  return this.opts.network
73
74
  }
74
75
 
75
- arg(key, val) {
76
+ get flags() {
77
+ const output = []
78
+
79
+ for (const [key, value] of this.opts.flags.entries()) {
80
+ let normalized = key
81
+ if (!key.startsWith('-')) {
82
+ normalized = (key.length === 1 ? `-${key}` : `--${key}`)
83
+ .toLowerCase()
84
+ .replace(/_/g, '-')
85
+ }
86
+
87
+ if (value === null) {
88
+ output.push(normalized)
89
+ continue
90
+ }
91
+
92
+ for (const item of value) {
93
+ output.push(normalized, item)
94
+ }
95
+ }
96
+
97
+ return output
98
+ }
99
+
100
+ arg(key, val = null) {
101
+ if (val === true || val == null) { // eslint-disable-line no-eq-null
102
+ this.flag('build-arg', key)
103
+ } else {
104
+ this.flag('build-arg', `${key}=${val}`)
105
+ }
76
106
  this.opts.args.set(key, val)
77
107
  return this
78
108
  }
79
109
 
80
- get build_cmd() {
81
- const args = []
82
- for (const [name, value] of this.opts.args.entries()) {
83
- if (value === true || value == null) { // eslint-disable-line no-eq-null
84
- args.push('--build-arg', name)
85
- } else {
86
- args.push('--build-arg', `${name}=${value}`)
87
- }
110
+ flag(key, val) {
111
+ if (val === null) {
112
+ this.opts.flags.set(key, val)
113
+ return this
114
+ }
115
+
116
+ let value = this.opts.flags.get(key) || []
117
+
118
+ if (Array.isArray(val)) {
119
+ value = value.concat(val)
120
+ } else {
121
+ value.push(val)
88
122
  }
123
+
124
+ this.opts.flags.set(key, value)
125
+ return this
126
+ }
127
+
128
+ get build_cmd() {
89
129
  return [
90
130
  'build'
91
131
  , `--network=${this.network}`
92
132
  , '--quiet'
93
133
  , '--tag'
94
134
  , this.name
95
- , ...args
135
+ , ...this.flags
96
136
  , '-f'
97
137
  , this.dockerfile
98
138
  , this.context
package/lib/prepare.js CHANGED
@@ -20,15 +20,25 @@ async function dockerPrepare(opts, context) {
20
20
  , network: opts.network
21
21
  })
22
22
 
23
- const args = {
24
- ...opts.args
23
+ const vars = buildTemplateVars(opts, context)
24
+
25
+ function render(item, vars) {
26
+ if (Array.isArray(item)) {
27
+ return item.map((element) => {
28
+ return string.template(element)(vars)
29
+ })
30
+ }
31
+ return string.template(item)(vars)
25
32
  }
26
33
 
27
- const vars = buildTemplateVars(opts, context)
28
- for (const [key, value] of Object.entries(args)) {
34
+ for (const [key, value] of Object.entries(opts.args)) {
29
35
  image.arg(key, string.template(value)(vars))
30
36
  }
31
37
 
38
+ for (const [key, value] of Object.entries(opts.build_flags)) {
39
+ image.flag(key, render(value, vars))
40
+ }
41
+
32
42
  context.logger.info('building image', image.name)
33
43
  context.logger.debug('build command: docker %s', image.build_cmd.join(' '))
34
44
  await image.build(path.join(cwd, opts.context))
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codedependant/semantic-release-docker",
3
3
  "private": false,
4
- "version": "4.3.0",
4
+ "version": "4.4.0",
5
5
  "description": "docker package",
6
6
  "main": "index.js",
7
7
  "files": [