diff --git a/.npmrc b/.npmrc index 9c8bb32..537e99f 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -public-hoist-pattern[]=*eslint* +hoist=true diff --git a/Dockerfile b/Dockerfile index 5e64bc5..77b0a05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/lib/build-config.js b/lib/build-config.js index 16ae84a..e11a72d 100644 --- a/lib/build-config.js +++ b/lib/build-config.js @@ -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 @@ -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 || '.' } } diff --git a/lib/docker/image.js b/lib/docker/image.js index d4a3083..b64730f 100644 --- a/lib/docker/image.js +++ b/lib/docker/image.js @@ -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 @@ -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() { diff --git a/lib/prepare.js b/lib/prepare.js index 5444a92..3491f6e 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -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 @@ -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 } diff --git a/lib/publish.js b/lib/publish.js index 819a7b9..0d3c04a 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -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) } diff --git a/test/unit/build-config.js b/test/unit/build-config.js index 619b6d3..af08b8a 100644 --- a/test/unit/build-config.js +++ b/test/unit/build-config.js @@ -12,6 +12,11 @@ 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) => { @@ -19,11 +24,19 @@ test('build-config', async (t) => { }, { 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 @@ -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' @@ -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' @@ -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