Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 27 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches:
- master

permissions:
contents: read

jobs:
publish:
if: |
Expand All @@ -15,29 +18,31 @@ jobs:

name: release

permissions:
contents: write
id-token: write

steps:
- name: Checkout Commit
uses: actions/checkout@v1
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Setup Node
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20

- name: Checkout Master
run: |
git branch -f master origin/master
git checkout master
- name: Install PNPM
uses: pnpm/action-setup@v4

- name: Sanity Check
run: |
echo branch `git branch --show-current`;
echo node `node -v`;
echo pnpm `pnpm -v`

- name: Install PNPM
uses: pnpm/action-setup@v4

- name: Set Git Config
run: |
git config pull.rebase false
Expand Down Expand Up @@ -65,8 +70,16 @@ jobs:
# Note: this satisfies aws sdk for @dot/config tests
AWS_REGION: 'us-east-1'

- name: OIDC Preflight
shell: bash
run: |
if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]; then
echo "Missing GitHub Actions OIDC env vars (ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN)." >&2
echo "Ensure the job requests permissions: id-token: write." >&2
exit 1
fi

echo "OIDC env vars detected."

- name: Release and Publish Changed Packages
run: pnpm --filter [HEAD^] --workspace-concurrency=1 release
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
4 changes: 2 additions & 2 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

# npm options
auth-type=legacy

# Publishing in CI uses GitHub OIDC (npm Trusted Publisher). For local publishing, authenticate via ~/.npmrc.

# pnpm options
always-auth = true
enable-pre-post-scripts = true
Expand Down
59 changes: 56 additions & 3 deletions packages/versioner/src/versioner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'source-map-support';

import { dirname, join, resolve } from 'path';
import { existsSync, readFileSync, writeFileSync } from 'fs';
import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
import { tmpdir } from 'os';

import { getLog } from '@dot/log';
import parser from 'conventional-commits-parser';
Expand All @@ -25,6 +26,8 @@ const parserOptions = {
noteKeywords: ['BREAKING CHANGE', 'Breaking Change']
};
const reBreaking = new RegExp(`(${parserOptions.noteKeywords.join(')|(')})`);
const NPM_CLI_SPEC = 'npm@11.5.1';
const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org';

type Commit = parser.Commit<string | number | symbol>;

Expand Down Expand Up @@ -151,9 +154,59 @@ const publish = async (cwd: string) => {
return;
}

log.info(chalk`\n{cyan Publishing to NPM}`);
const registryOverrideRaw = argv.registry;
if (argv.registry && typeof argv.registry !== 'string') {
throw new TypeError(
`--registry must be a string (e.g. "${DEFAULT_NPM_REGISTRY}"), received ${typeof registryOverrideRaw}: ${String(
argv.registry
)}`
);
}

const registry = argv.registry || DEFAULT_NPM_REGISTRY;

await execa('pnpm', ['publish', '--no-git-checks'], { cwd, stdio: 'inherit' });
log.info(chalk`\n{cyan Publishing to NPM}: {grey ${registry}}`);

const packDir = mkdtempSync(join(tmpdir(), 'versioner-pack-'));
try {
await execa('pnpm', ['pack', '--pack-destination', packDir], { cwd, stdio: 'inherit' });

const tarballs = readdirSync(packDir)
.filter((file) => file.endsWith('.tgz'))
.sort();

if (tarballs.length !== 1) {
throw new RangeError(
`Expected exactly 1 packed tarball in: ${packDir} for cwd=${cwd} (found ${
tarballs.length
}): ${tarballs.join(', ')}`
);
}

const tarballPath = join(packDir, tarballs[0]);
const hasOidcEnv =
!!process.env.ACTIONS_ID_TOKEN_REQUEST_URL && !!process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
const provenanceArgs = hasOidcEnv ? ['--provenance'] : [];

log.info(chalk`{grey Using npm CLI:} ${NPM_CLI_SPEC}`);

await execa(
'pnpm',
[
'dlx',
NPM_CLI_SPEC,
'publish',
'--no-git-checks',
'--registry',
registry,
...provenanceArgs,
tarballPath
],
{ cwd, stdio: 'inherit' }
);
} finally {
rmSync(packDir, { force: true, recursive: true });
}
};

const pull = async () => {
Expand Down
Loading