From b548217936466c090738d35a85b04237b2f368b2 Mon Sep 17 00:00:00 2001 From: Michal Kimle Date: Mon, 24 Oct 2022 13:40:20 +0200 Subject: [PATCH] Allow publishing snapshot packages to the official NPM registry --- docker/Dockerfile | 5 ++++- docker/scripts/cli.ts | 3 --- docker/scripts/publish-packages.ts | 33 ++++++++++++++++++++++-------- package.json | 1 + 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e7a059c05b..f10fb2f1cf 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,9 @@ FROM node:14.19.3-alpine3.15 AS environment -ENV appDir="/app" +ENV appDir="/app" \ + # Settings to true to convince changesets that this is run in the CI and it shouldn't check for or require 2FA auth + # https://github.com/changesets/changesets/blob/8c0846977597ddaf51aaeb35f1f0f9428bf8ba14/packages/cli/src/commands/publish/publishPackages.ts#L57 + CI="true" RUN apk add --update --no-cache git rsync docker $([ $(arch) == "aarch64" ] && echo "python3 make g++") && \ yarn global add npm && \ diff --git a/docker/scripts/cli.ts b/docker/scripts/cli.ts index 0a64a67d8d..d1890efc9f 100644 --- a/docker/scripts/cli.ts +++ b/docker/scripts/cli.ts @@ -80,9 +80,6 @@ yargs(process.argv.slice(2)) logger.log(`Running command '${args._[0]}' with arguments ${longArguments(args)}`); // Temporary check for not yet supported functionality - if (args.npmRegistry === 'https://registry.npmjs.org/') { - throw new Error('Publishing packages to the official NPM registry is not supported yet'); - } if (!args.snapshot) { throw new Error('Only snapshot packages are supported at the moment'); } diff --git a/docker/scripts/publish-packages.ts b/docker/scripts/publish-packages.ts index 04e7126233..917927fb86 100755 --- a/docker/scripts/publish-packages.ts +++ b/docker/scripts/publish-packages.ts @@ -41,11 +41,9 @@ const buildProject = () => { runCommand('yarn build', { cwd: '/build' }); }; -const authNpmRegistry = async (npmRegistryUrl: string) => { +const registerUser = async (npmRegistryUrl: string) => { const dummyUser = randomBytes(4).toString('hex'); const dummyPassword = randomBytes(4).toString('hex'); - const npmrcPath = join(homedir(), '.npmrc'); - const yarnrcPath = join(homedir(), '.yarnrc'); const goAuthResponse = await go(() => axios.put( @@ -66,11 +64,15 @@ const authNpmRegistry = async (npmRegistryUrl: string) => { throw new Error(`Can't authenticate against NPM registry ${npmRegistryUrl}: ${goAuthResponse.error}`); } + return goAuthResponse.data.data.token; +}; + +const authNpmRegistry = (npmRegistryUrl: string, npmAuthToken: string) => { + const npmrcPath = join(homedir(), '.npmrc'); + const yarnrcPath = join(homedir(), '.yarnrc'); // It looks like the auth token must be present in the NPM configuration (even when using Yarn) but the // registry must be also in the Yarn configuration... - const newNpmrc = `${npmRegistryUrl.slice(npmRegistryUrl.indexOf(':') + 1)}/:_authToken="${ - goAuthResponse.data.data.token - }" + const newNpmrc = `${npmRegistryUrl.slice(npmRegistryUrl.indexOf(':') + 1)}/:_authToken="${npmAuthToken}" registry=${npmRegistryUrl} `; const newYarn = `registry "${npmRegistryUrl}" @@ -96,7 +98,7 @@ const simplifyChangesetConfig = () => { writeFileSync(changesetConfigPath, newChangesetConfig); }; -export const publishPackages = async (npmRegistry: string, npmTag: string, _snapshot: boolean) => { +export const publishPackages = async (npmRegistry: string, npmTag: string, snapshot: boolean) => { let npmRegistryUrl = npmRegistry; if (npmRegistry === 'local') { @@ -112,8 +114,23 @@ export const publishPackages = async (npmRegistry: string, npmTag: string, _snap fetchProject(); buildProject(); - await authNpmRegistry(npmRegistryUrl); + + let npmAuthToken = process.env.NPM_TOKEN; + if (npmRegistry === 'local') { + npmAuthToken = await registerUser(npmRegistryUrl); + } + + if (!npmAuthToken) { + throw new Error('Missing NPM authentication token'); + } + + authNpmRegistry(npmRegistryUrl, npmAuthToken); simplifyChangesetConfig(); + + // If in snapshot mode, prefix the NPM tag with a word `snapshot` unless we're using a local registry. + if (npmRegistry !== 'local' && snapshot) { + npmTag = `snapshot-${npmTag}`; + } // Ignoring commands' outputs because of the weird text colorization. runCommand(`yarn changeset version --snapshot ${npmTag}`, { cwd: '/build', stdio: 'ignore' }); runCommand(`yarn changeset publish --no-git-tag --snapshot --tag ${npmTag}`, { cwd: '/build', stdio: 'ignore' }); diff --git a/package.json b/package.json index 05dd88a45a..47fc25ab4e 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "docker:scripts:npm-registry:stop": "yarn docker:scripts:npm-registry stop", "docker:scripts:publish-packages": "docker run --rm -v $(pwd):/airnode -v /var/run/docker.sock:/var/run/docker.sock api3/airnode-packaging:latest publish-packages", "docker:scripts:publish-packages:local": "yarn docker:scripts:publish-packages --npm-registry local --npm-tag local --snapshot", + "docker:scripts:publish-packages:snapshot": "docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -e NPM_TOKEN api3/airnode-packaging:latest publish-packages --snapshot --npm-tag", "format:check": "yarn prettier:check && yarn terraform:fmt:check", "format:write": "yarn prettier:write && yarn terraform:fmt:write", "lint": "yarn run lint:eslint && yarn run lint:solhint && yarn format:check && yarn ts-node scripts/validate-ts-references.ts",