diff --git a/.github/scripts/pnpm-utils.mjs b/.github/scripts/pnpm-utils.mjs new file mode 100644 index 0000000000000..95ca5bd389aec --- /dev/null +++ b/.github/scripts/pnpm-utils.mjs @@ -0,0 +1,25 @@ +import child_process from 'child_process'; +import { promisify } from 'node:util'; + +const exec = promisify(child_process.exec); + +/** + * @typedef PnpmPackage + * @property { string } name + * @property { string } version + * @property { string } path + * @property { boolean } private + * */ + +/** + * @returns { Promise } + * */ +export async function getMonorepoProjects() { + return JSON.parse( + ( + await exec( + `pnpm ls -r --only-projects --json | jq -r '[.[] | { name: .name, version: .version, path: .path, private: .private}]'`, + ) + ).stdout, + ); +} diff --git a/.github/scripts/set-latest-for-monorepo-packages.mjs b/.github/scripts/set-latest-for-monorepo-packages.mjs new file mode 100644 index 0000000000000..40f3cf7f52b79 --- /dev/null +++ b/.github/scripts/set-latest-for-monorepo-packages.mjs @@ -0,0 +1,28 @@ +import { trySh } from './github-helpers.mjs'; +import { getMonorepoProjects } from './pnpm-utils.mjs'; + +async function setLatestForMonorepoPackages() { + const packages = await getMonorepoProjects(); + + const publishedPackages = packages // + .filter((pkg) => !pkg.private) + .filter((pkg) => pkg.version); + + for (const pkg of publishedPackages) { + const versionName = `${pkg.name}@${pkg.version}`; + const res = trySh('npm', ['dist-tag', 'add', versionName, 'latest']); + if (res.ok) { + console.log(`Set ${versionName} as latest`); + } else { + console.warn(`Update failed for ${versionName}`); + } + } +} + +// only run when executed directly, not when imported by tests +if (import.meta.url === `file://${process.argv[1]}`) { + setLatestForMonorepoPackages().catch((err) => { + console.error(err); + process.exit(1); + }); +} diff --git a/.github/workflows/release-publish-post-release.yml b/.github/workflows/release-publish-post-release.yml index 7d313b9176bec..38d7eba24c5bf 100644 --- a/.github/workflows/release-publish-post-release.yml +++ b/.github/workflows/release-publish-post-release.yml @@ -66,6 +66,14 @@ jobs: uses: ./.github/workflows/util-ensure-release-candidate-branches.yml secrets: inherit + ensure-correct-latest-version-on-npm: + name: Ensure correct latest version on npm + if: | + inputs.bump == 'minor' || + inputs.track == 'stable' + uses: ./.github/workflows/release-set-stable-npm-packages-to-latest.yml + secrets: inherit + populate-cloud-with-releases: name: 'Populate cloud database with releases' uses: ./.github/workflows/release-populate-cloud-with-releases.yml diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 9775442a434eb..ee7a87162b456 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -84,7 +84,7 @@ jobs: - name: Publish other packages to NPM env: PUBLISH_BRANCH: ${{ github.event.pull_request.base.ref }} - PUBLISH_TAG: ${{ needs.determine-version-info.outputs.track == 'stable' && 'latest' || needs.determine-version-info.outputs.track }} + PUBLISH_TAG: ${{ needs.determine-version-info.outputs.track }} run: | # Prefix version-like track names (e.g. "1", "v1") to avoid npm rejecting them as semver ranges if [[ "$PUBLISH_TAG" =~ ^v?[0-9] ]]; then diff --git a/.github/workflows/release-set-stable-npm-packages-to-latest.yml b/.github/workflows/release-set-stable-npm-packages-to-latest.yml new file mode 100644 index 0000000000000..6828f57549c22 --- /dev/null +++ b/.github/workflows/release-set-stable-npm-packages-to-latest.yml @@ -0,0 +1,35 @@ +name: 'Release: Set stable npm packages to latest' + +on: + workflow_call: + workflow_dispatch: + +permissions: + contents: write + +jobs: + promote-github-releases: + name: Promote current stable releases as latest + runs-on: ubuntu-slim + environment: release + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: refs/tags/stable + fetch-depth: 1 + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + with: + build-command: '' + install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace + + # Remove after https://github.com/npm/cli/issues/8547 gets resolved + - run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Set npm packages to latest + run: node ./.github/scripts/set-latest-for-monorepo-packages.mjs