feat(esm): convert to esm (#2569)

for #2543

BREAKING CHANGE: semantic-release is now ESM-only. since it is used through its own executable, the impact on consuming projects should be minimal

BREAKING CHANGE: references to plugin files in configs need to include the file extension because of executing in an ESM context
This commit is contained in:
Matt Travi
2022-11-11 09:24:06 -06:00
committed by GitHub
parent 4012f75386
commit 9eab1adb9d
67 changed files with 3001 additions and 1761 deletions
+34 -59
View File
@@ -1,10 +1,10 @@
const tempy = require('tempy');
const execa = require('execa');
const fileUrl = require('file-url');
const pEachSeries = require('p-each-series');
const gitLogParser = require('git-log-parser');
const getStream = require('get-stream');
const {GIT_NOTE_REF} = require('../../lib/definitions/constants');
import {temporaryDirectory} from 'tempy';
import {execa} from 'execa';
import fileUrl from 'file-url';
import pEachSeries from 'p-each-series';
import gitLogParser from 'git-log-parser';
import getStream from 'get-stream';
import {GIT_NOTE_REF} from '../../lib/definitions/constants.js';
/**
* Commit message information.
@@ -23,8 +23,8 @@ const {GIT_NOTE_REF} = require('../../lib/definitions/constants');
* @param {Boolean} withRemote `true` to create a shallow clone of a bare repository.
* @return {String} The path of the repository
*/
async function initGit(withRemote) {
const cwd = tempy.directory();
export async function initGit(withRemote) {
const cwd = temporaryDirectory();
const args = withRemote ? ['--bare', '--initial-branch=master'] : ['--initial-branch=master'];
await execa('git', ['init', ...args], {cwd}).catch(() => {
@@ -45,7 +45,7 @@ async function initGit(withRemote) {
* @param {String} [branch='master'] The branch to initialize.
* @return {String} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.
*/
async function gitRepo(withRemote, branch = 'master') {
export async function gitRepo(withRemote, branch = 'master') {
let {cwd, repositoryUrl} = await initGit(withRemote);
if (withRemote) {
await initBareRepo(repositoryUrl, branch);
@@ -70,8 +70,8 @@ async function gitRepo(withRemote, branch = 'master') {
* @param {String} repositoryUrl The URL of the bare repository.
* @param {String} [branch='master'] the branch to initialize.
*/
async function initBareRepo(repositoryUrl, branch = 'master') {
const cwd = tempy.directory();
export async function initBareRepo(repositoryUrl, branch = 'master') {
const cwd = temporaryDirectory();
await execa('git', ['clone', '--no-hardlinks', repositoryUrl, cwd], {cwd});
await gitCheckout(branch, true, {cwd});
await gitCommits(['Initial commit'], {cwd});
@@ -86,7 +86,7 @@ async function initBareRepo(repositoryUrl, branch = 'master') {
*
* @returns {Array<Commit>} The created commits, in reverse order (to match `git log` order).
*/
async function gitCommits(messages, execaOptions) {
export async function gitCommits(messages, execaOptions) {
await pEachSeries(
messages,
async (message) =>
@@ -103,7 +103,7 @@ async function gitCommits(messages, execaOptions) {
*
* @return {Array<Object>} The list of parsed commits.
*/
async function gitGetCommits(from, execaOptions) {
export async function gitGetCommits(from, execaOptions) {
Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});
return (
await getStream.array(
@@ -126,7 +126,7 @@ async function gitGetCommits(from, execaOptions) {
* @param {Boolean} create to create the branch, `false` to checkout an existing branch.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitCheckout(branch, create, execaOptions) {
export async function gitCheckout(branch, create, execaOptions) {
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOptions);
}
@@ -136,7 +136,7 @@ async function gitCheckout(branch, create, execaOptions) {
* @param {String} repositoryUrl The repository remote URL.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitFetch(repositoryUrl, execaOptions) {
export async function gitFetch(repositoryUrl, execaOptions) {
await execa('git', ['fetch', repositoryUrl], execaOptions);
}
@@ -147,7 +147,7 @@ async function gitFetch(repositoryUrl, execaOptions) {
*
* @return {String} The sha of the head commit in the current git repository.
*/
async function gitHead(execaOptions) {
export async function gitHead(execaOptions) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;
}
@@ -158,7 +158,7 @@ async function gitHead(execaOptions) {
* @param {String} [sha] The commit on which to create the tag. If undefined the tag is created on the last commit.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitTagVersion(tagName, sha, execaOptions) {
export async function gitTagVersion(tagName, sha, execaOptions) {
await execa('git', sha ? ['tag', '-f', tagName, sha] : ['tag', tagName], execaOptions);
}
@@ -171,8 +171,8 @@ async function gitTagVersion(tagName, sha, execaOptions) {
* @param {Number} [depth=1] The number of commit to clone.
* @return {String} The path of the cloned repository.
*/
async function gitShallowClone(repositoryUrl, branch = 'master', depth = 1) {
const cwd = tempy.directory();
export async function gitShallowClone(repositoryUrl, branch = 'master', depth = 1) {
const cwd = temporaryDirectory();
await execa('git', ['clone', '--no-hardlinks', '--no-tags', '-b', branch, '--depth', depth, repositoryUrl, cwd], {
cwd,
@@ -187,8 +187,8 @@ async function gitShallowClone(repositoryUrl, branch = 'master', depth = 1) {
* @param {Number} head A commit sha of the remote repo that will become the detached head of the new one.
* @return {String} The path of the new repository.
*/
async function gitDetachedHead(repositoryUrl, head) {
const cwd = tempy.directory();
export async function gitDetachedHead(repositoryUrl, head) {
const cwd = temporaryDirectory();
await execa('git', ['init'], {cwd});
await execa('git', ['remote', 'add', 'origin', repositoryUrl], {cwd});
@@ -197,8 +197,8 @@ async function gitDetachedHead(repositoryUrl, head) {
return cwd;
}
async function gitDetachedHeadFromBranch(repositoryUrl, branch, head) {
const cwd = tempy.directory();
export async function gitDetachedHeadFromBranch(repositoryUrl, branch, head) {
const cwd = temporaryDirectory();
await execa('git', ['init'], {cwd});
await execa('git', ['remote', 'add', 'origin', repositoryUrl], {cwd});
@@ -215,7 +215,7 @@ async function gitDetachedHeadFromBranch(repositoryUrl, branch, head) {
* @param {String} value Config value.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitAddConfig(name, value, execaOptions) {
export async function gitAddConfig(name, value, execaOptions) {
await execa('git', ['config', '--add', name, value], execaOptions);
}
@@ -227,7 +227,7 @@ async function gitAddConfig(name, value, execaOptions) {
*
* @return {String} The sha of the commit associated with `tagName` on the local repository.
*/
async function gitTagHead(tagName, execaOptions) {
export async function gitTagHead(tagName, execaOptions) {
return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;
}
@@ -240,7 +240,7 @@ async function gitTagHead(tagName, execaOptions) {
*
* @return {String} The sha of the commit associated with `tagName` on the remote repository.
*/
async function gitRemoteTagHead(repositoryUrl, tagName, execaOptions) {
export async function gitRemoteTagHead(repositoryUrl, tagName, execaOptions) {
return (await execa('git', ['ls-remote', '--tags', repositoryUrl, tagName], execaOptions)).stdout
.split('\n')
.filter((tag) => Boolean(tag))
@@ -255,7 +255,7 @@ async function gitRemoteTagHead(repositoryUrl, tagName, execaOptions) {
*
* @return {String} The tag associatedwith the sha in parameter or `null`.
*/
async function gitCommitTag(gitHead, execaOptions) {
export async function gitCommitTag(gitHead, execaOptions) {
return (await execa('git', ['describe', '--tags', '--exact-match', gitHead], execaOptions)).stdout;
}
@@ -268,7 +268,7 @@ async function gitCommitTag(gitHead, execaOptions) {
*
* @throws {Error} if the push failed.
*/
async function gitPush(repositoryUrl, branch, execaOptions) {
export async function gitPush(repositoryUrl, branch, execaOptions) {
await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOptions);
}
@@ -278,7 +278,7 @@ async function gitPush(repositoryUrl, branch, execaOptions) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function merge(ref, execaOptions) {
export async function merge(ref, execaOptions) {
await execa('git', ['merge', '--no-ff', ref], execaOptions);
}
@@ -288,7 +288,7 @@ async function merge(ref, execaOptions) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function mergeFf(ref, execaOptions) {
export async function mergeFf(ref, execaOptions) {
await execa('git', ['merge', '--ff', ref], execaOptions);
}
@@ -298,7 +298,7 @@ async function mergeFf(ref, execaOptions) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function rebase(ref, execaOptions) {
export async function rebase(ref, execaOptions) {
await execa('git', ['rebase', ref], execaOptions);
}
@@ -309,7 +309,7 @@ async function rebase(ref, execaOptions) {
* @param {String} ref The ref to add the note to.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitAddNote(note, ref, execaOptions) {
export async function gitAddNote(note, ref, execaOptions) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-m', note, ref], execaOptions);
}
@@ -319,31 +319,6 @@ async function gitAddNote(note, ref, execaOptions) {
* @param {String} ref The ref to get the note from.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitGetNote(ref, execaOptions) {
export async function gitGetNote(ref, execaOptions) {
return (await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout;
}
module.exports = {
initGit,
gitRepo,
initBareRepo,
gitCommits,
gitGetCommits,
gitCheckout,
gitFetch,
gitHead,
gitTagVersion,
gitShallowClone,
gitDetachedHead,
gitDetachedHeadFromBranch,
gitAddConfig,
gitTagHead,
gitRemoteTagHead,
gitCommitTag,
gitPush,
merge,
mergeFf,
rebase,
gitAddNote,
gitGetNote,
};
+8 -10
View File
@@ -1,7 +1,7 @@
const Docker = require('dockerode');
const getStream = require('get-stream');
const pRetry = require('p-retry');
const {initBareRepo, gitShallowClone} = require('./git-utils');
import Docker from 'dockerode';
import getStream from 'get-stream';
import pRetry from 'p-retry';
import {gitShallowClone, initBareRepo} from './git-utils.js';
const IMAGE = 'semanticrelease/docker-gitbox:latest';
const SERVER_PORT = 80;
@@ -12,12 +12,12 @@ const GIT_PASSWORD = 'suchsecure';
const docker = new Docker();
let container;
const gitCredential = `${GIT_USERNAME}:${GIT_PASSWORD}`;
export const gitCredential = `${GIT_USERNAME}:${GIT_PASSWORD}`;
/**
* Download the `gitbox` Docker image, create a new container and start it.
*/
async function start() {
export async function start() {
await getStream(await docker.pull(IMAGE));
container = await docker.createContainer({
@@ -38,7 +38,7 @@ async function start() {
/**
* Stop and remote the `mockserver` Docker container.
*/
async function stop() {
export async function stop() {
await container.stop();
await container.remove();
}
@@ -51,7 +51,7 @@ async function stop() {
* @param {String} [description=`Repository ${name}`] The repository description.
* @return {Object} The `repositoryUrl` (URL without auth) and `authUrl` (URL with auth).
*/
async function createRepo(name, branch = 'master', description = `Repository ${name}`) {
export async function createRepo(name, branch = 'master', description = `Repository ${name}`) {
const exec = await container.exec({
Cmd: ['repo-admin', '-n', name, '-d', description],
AttachStdout: true,
@@ -68,5 +68,3 @@ async function createRepo(name, branch = 'master', description = `Repository ${n
return {cwd, repositoryUrl, authUrl};
}
module.exports = {start, stop, gitCredential, createRepo};
+10 -12
View File
@@ -1,8 +1,8 @@
const Docker = require('dockerode');
const getStream = require('get-stream');
const got = require('got');
const pRetry = require('p-retry');
const {mockServerClient} = require('mockserver-client');
import Docker from 'dockerode';
import getStream from 'get-stream';
import got from 'got';
import pRetry from 'p-retry';
import {mockServerClient} from 'mockserver-client';
const IMAGE = 'mockserver/mockserver:latest';
const MOCK_SERVER_PORT = 1080;
@@ -13,7 +13,7 @@ let container;
/**
* Download the `mockserver` Docker image, create a new container and start it.
*/
async function start() {
export async function start() {
await getStream(await docker.pull(IMAGE));
container = await docker.createContainer({
@@ -38,7 +38,7 @@ async function start() {
/**
* Stop and remove the `mockserver` Docker container.
*/
async function stop() {
export async function stop() {
await container.stop();
await container.remove();
}
@@ -50,7 +50,7 @@ const client = mockServerClient(MOCK_SERVER_HOST, MOCK_SERVER_PORT);
/**
* @type {string} the url of the `mockserver` instance
*/
const url = `http://${MOCK_SERVER_HOST}:${MOCK_SERVER_PORT}`;
export const url = `http://${MOCK_SERVER_HOST}:${MOCK_SERVER_PORT}`;
/**
* Set up the `mockserver` instance response for a specific request.
@@ -65,7 +65,7 @@ const url = `http://${MOCK_SERVER_HOST}:${MOCK_SERVER_PORT}`;
* @param {Object} response.body The JSON object to respond in the response body.
* @return {Object} An object representation the expectation. Pass to the `verify` function to validate the `mockserver` has been called with a `request` matching the expectations.
*/
async function mock(
export async function mock(
path,
{body: requestBody, headers: requestHeaders},
{method = 'POST', statusCode = 200, body: responseBody}
@@ -96,8 +96,6 @@ async function mock(
* @param {Object} expectation The expectation created with `mock` function.
* @return {Promise} A Promise that resolves if the expectation is met or reject otherwise.
*/
function verify(expectation) {
export function verify(expectation) {
return client.verify(expectation);
}
module.exports = {start, stop, mock, verify, url};
+12 -12
View File
@@ -1,9 +1,10 @@
const Docker = require('dockerode');
const getStream = require('get-stream');
const got = require('got');
const path = require('path');
const delay = require('delay');
const pRetry = require('p-retry');
import path, {dirname} from 'node:path';
import {fileURLToPath} from 'node:url';
import Docker from 'dockerode';
import getStream from 'get-stream';
import got from 'got';
import delay from 'delay';
import pRetry from 'p-retry';
const IMAGE = 'verdaccio/verdaccio:4';
const REGISTRY_PORT = 4873;
@@ -12,12 +13,13 @@ const NPM_USERNAME = 'integration';
const NPM_PASSWORD = 'suchsecure';
const NPM_EMAIL = 'integration@test.com';
const docker = new Docker();
const __dirname = dirname(fileURLToPath(import.meta.url));
let container;
/**
* Download the `npm-registry-docker` Docker image, create a new container and start it.
*/
async function start() {
export async function start() {
await getStream(await docker.pull(IMAGE));
container = await docker.createContainer({
@@ -55,9 +57,9 @@ async function start() {
});
}
const url = `http://${REGISTRY_HOST}:${REGISTRY_PORT}/`;
export const url = `http://${REGISTRY_HOST}:${REGISTRY_PORT}/`;
const authEnv = {
export const authEnv = {
npm_config_registry: url, // eslint-disable-line camelcase
NPM_USERNAME,
NPM_PASSWORD,
@@ -67,9 +69,7 @@ const authEnv = {
/**
* Stop and remote the `npm-registry-docker` Docker container.
*/
async function stop() {
export async function stop() {
await container.stop();
await container.remove();
}
module.exports = {start, stop, authEnv, url};
+2 -4
View File
@@ -1,7 +1,5 @@
const execa = require('execa');
import {execa} from 'execa';
async function npmView(packageName, env) {
export async function npmView(packageName, env) {
return JSON.parse((await execa('npm', ['view', packageName, '--json'], {env})).stdout);
}
module.exports = {npmView};