Skip to content

Commit

Permalink
feat(docker): Load default build args into docker build
Browse files Browse the repository at this point in the history
* SRC_DIRECTORY = the name of the directory where the build is being
executed
* TARGET_PATH = the relative path from the root of the project to
SRC_DIRECTOR
* NPM_PACKAGE_NAME = the name of the package being built
* NPM_PACKAGE_SCOPE = the scope of the npm package being built
* CONFIG_NAME = the name of the image as defined by the configuration
* CONFIG_PROJECT = the name of the docker project as defined by the
config

Semver: minor
  • Loading branch information
esatterwhite committed Aug 6, 2020
1 parent 0140d66 commit 0760d5e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
public-hoist-pattern[]=*eslint*
hoist=true
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# 0000-BASE
FROM docker:latest
ARG SRC_DIR='.'
RUN apk update && apk upgrade && apk add nodejs npm
WORKDIR /opt/app
COPY ./package.json /opt/app/
COPY ${SRC_DIR}/package.json /opt/app/
RUN npm install
COPY . /opt/app
COPY ${SRC_DIR} /opt/app
WORkDIR /opt/app
22 changes: 19 additions & 3 deletions lib/build-config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict'

const path = require('path')
const readPkg = require('./read-pkg.js')
const object = require('./lang/object/index.js')
const parsePkgName = require('./parse-pkg-name.js')
const PWD = '.'

module.exports = buildConfig

Expand All @@ -18,22 +20,36 @@ async function buildConfig(build_id, config, context) {

let name = null
let scope = null
let pkg = {}
try {
const pkg = await readPkg({cwd: context.cwd})
pkg = await readPkg({cwd: context.cwd})
const parsed = parsePkgName(pkg.name)
name = parsed.name
scope = parsed.scope
} catch (_) {}

const project = object.has(config.docker, 'project') ? config.docker.project : scope
const root = object.get(context, 'options.root')
const target = path.relative(root || context.cwd, context.cwd) || PWD

return {
tags
, registry
, args
, dockerfile
, nocache
, pkg
, project
, args: {
SRC_DIRECTORY: path.basename(context.cwd)
, TARGET_PATH: target
, NPM_PACKAGE_NAME: object.get(pkg, 'name')
, NPM_PACKAGE_SCOPE: scope
, CONFIG_NAME: image || name
, CONFIG_PROJECT: project
, ...args
}
, name: image || name
, build: build_id
, project: object.has(config.docker, 'project') ? config.docker.project : scope
, context: config.context || '.'
}
}
11 changes: 8 additions & 3 deletions lib/docker/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ class Image {
}

async build() {
const out = await execa('docker', this.build_cmd)
const {stdout} = out
const stream = execa('docker', this.build_cmd)
stream.stdout.pipe(process.stdout)
stream.stderr.pipe(process.stderr)
const {stdout} = await stream
const [_, sha] = stdout.split(':')
this.sha = sha.substring(0, 12)
return this.sha
Expand All @@ -103,7 +105,10 @@ class Image {
await execa('docker', ['tag', this.name, `${this.repo}:${tag}`])
if (!push) return

await execa('docker', ['push', `${this.repo}:${tag}`])
const stream = execa('docker', ['push', `${this.repo}:${tag}`])
stream.stdout.pipe(process.stdout)
stream.stderr.pipe(process.stderr)
await stream
}

async push() {
Expand Down
10 changes: 7 additions & 3 deletions lib/prepare.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

const path = require('path')
const debug = require('debug')('semantic-release:semantic-release-docker:prepare')
const docker = require('./docker/index.js')

module.exports = dockerPrepare
Expand All @@ -16,14 +17,17 @@ async function dockerPrepare(opts, context) {
, cwd: cwd
})

if (opts.args) {
for (const [key, value] of Object.entries(opts.args)) {
const args = {
...opts.args
}
if (args) {
for (const [key, value] of Object.entries(args)) {
image.arg(key, value)
}
}

context.logger.info('building image', image.name)

debug('build command', image.build_cmd)
await image.build(path.join(cwd, opts.context))
return image
}
2 changes: 1 addition & 1 deletion lib/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async function publish(opts, context) {

logger.info('tagging docker image', image.id)
for (const tag of tags) {
context.logger.info(`pushing image: ${image.repo} tag: ${tag}`)
console.log(`pushing image: ${image.repo} tag: ${tag}`)
await image.tag(tag)
}

Expand Down
82 changes: 74 additions & 8 deletions test/unit/build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,31 @@ test('build-config', async (t) => {
, scoped: {
'package.json': JSON.stringify({name: '@scope/this-is-scoped'})
}
, workspace: {
one: {
'package.json': JSON.stringify({name: '@internal/package'})
}
}
})

t.test('standard package', async (tt) => {
const config = await buildConfig('id', {
}, {
cwd: path.join(t.testdirName, 'standard')
})
tt.deepEqual(config, {
tt.match(config, {
dockerfile: 'Dockerfile'
, nocache: false
, tags: ['latest', '{major}-latest', '{version}']
, args: {}
, args: {
SRC_DIRECTORY: 'standard'
, TARGET_PATH: '.'
, NPM_PACKAGE_NAME: 'this-is-not-scoped'
, NPM_PACKAGE_SCOPE: null
, CONFIG_NAME: 'this-is-not-scoped'
, CONFIG_PROJECT: null
}
, pkg: Object
, registry: null
, name: 'this-is-not-scoped'
, project: null
Expand All @@ -32,17 +45,54 @@ test('build-config', async (t) => {
})
})

t.test('nested workspace: target resolution', async (tt) => {
const config = await buildConfig('id', {
}, {
options: {
root: t.testdirName
}
, cwd: path.join(t.testdirName, 'workspace', 'one')
})
tt.match(config, {
dockerfile: 'Dockerfile'
, nocache: false
, tags: ['latest', '{major}-latest', '{version}']
, args: {
SRC_DIRECTORY: 'one'
, TARGET_PATH: 'workspace/one'
, NPM_PACKAGE_NAME: 'package'
, NPM_PACKAGE_SCOPE: 'internal'
, CONFIG_NAME: 'package'
, CONFIG_PROJECT: 'internal'
}
, pkg: Object
, registry: null
, name: 'package'
, project: 'internal'
, build: 'id'
, context: '.'
})
})

t.test('scoped package', async (tt) => {
{
const config = await buildConfig('id', {
}, {
cwd: path.join(t.testdirName, 'scoped')
})
tt.deepEqual(config, {
tt.match(config, {
dockerfile: 'Dockerfile'
, nocache: false
, tags: ['latest', '{major}-latest', '{version}']
, args: {}
, args: {
SRC_DIRECTORY: 'scoped'
, TARGET_PATH: '.'
, NPM_PACKAGE_NAME: '@scope/this-is-scoped'
, NPM_PACKAGE_SCOPE: 'scope'
, CONFIG_NAME: 'this-is-scoped'
, CONFIG_PROJECT: 'scope'
}
, pkg: Object
, registry: null
, name: 'this-is-scoped'
, project: 'scope'
Expand All @@ -61,11 +111,19 @@ test('build-config', async (t) => {
}, {
cwd: path.join(t.testdirName, 'scoped')
})
tt.deepEqual(config, {
tt.match(config, {
dockerfile: 'Dockerfile.test'
, nocache: false
, tags: ['latest', '{major}-latest', '{version}']
, args: {}
, args: {
SRC_DIRECTORY: 'scoped'
, TARGET_PATH: '.'
, NPM_PACKAGE_NAME: '@scope/this-is-scoped'
, NPM_PACKAGE_SCOPE: 'scope'
, CONFIG_NAME: 'override'
, CONFIG_PROJECT: 'kittens'
}
, pkg: Object
, registry: null
, name: 'override'
, project: 'kittens'
Expand All @@ -84,11 +142,19 @@ test('build-config', async (t) => {
}, {
cwd: path.join(t.testdirName, 'scoped')
})
tt.deepEqual(config, {
tt.match(config, {
dockerfile: 'Dockerfile.test'
, nocache: false
, tags: ['latest', '{major}-latest', '{version}']
, args: {}
, args: {
SRC_DIRECTORY: 'scoped'
, TARGET_PATH: '.'
, NPM_PACKAGE_NAME: '@scope/this-is-scoped'
, NPM_PACKAGE_SCOPE: 'scope'
, CONFIG_NAME: 'override'
, CONFIG_PROJECT: null
}
, pkg: Object
, registry: null
, name: 'override'
, project: null
Expand Down

0 comments on commit 0760d5e

Please sign in to comment.