From 93e21e6019bc53ec049e0cbcd6587c2bb516da61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82uszniak?= Date: Tue, 4 Aug 2026 15:18:47 +0200 Subject: [PATCH 1/2] ci: make npm publish dist-tag an explicit choice The `latest-build` boolean had only two outcomes: true published under `latest`, and *anything else* fell through to nightly - both the `executorch-nightly` dist-tag and a rewritten `x.y.z-nightly--` version. There was no way to dispatch a `legacy` publish for a maintenance release, and picking "not latest" silently produced a nightly instead. Replace it with a `release-type` choice (nightly / latest / legacy) that maps to the dist-tag directly. Only `nightly` rewrites the version. The scheduled run passes no inputs, so RELEASE_TYPE defaults to nightly. --- .github/workflows/npm-publish.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 466d0f144e..d299b9fd80 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -5,10 +5,15 @@ on: - cron: '01 00 * * *' # Every day at 00:01 UTC workflow_dispatch: inputs: - latest-build: - description: 'Whether to publish as a latest build' + release-type: + description: 'Which npm dist-tag to publish under' required: true - type: boolean + type: choice + options: + - nightly # executorch-nightly, version suffixed with commit + date + - latest # current stable release + - legacy # maintenance release of an older line + default: nightly permissions: id-token: write @@ -31,6 +36,8 @@ jobs: EXECUTORCH_VERSION: PLACEHOLDER PACKAGE_NAME: PLACEHOLDER TAG: PLACEHOLDER + # `inputs` is empty on the scheduled run, which is always a nightly. + RELEASE_TYPE: ${{ inputs.release-type || 'nightly' }} steps: - name: Checkout uses: actions/checkout@v6 @@ -57,11 +64,12 @@ jobs: - name: Set tag run: | - if [[ "${{ inputs.latest-build }}" != "true" ]]; then - echo "TAG=executorch-nightly" >> $GITHUB_ENV - else - echo "TAG=latest" >> $GITHUB_ENV - fi + case "$RELEASE_TYPE" in + nightly) echo "TAG=executorch-nightly" >> $GITHUB_ENV ;; + latest) echo "TAG=latest" >> $GITHUB_ENV ;; + legacy) echo "TAG=legacy" >> $GITHUB_ENV ;; + *) echo "Unknown release type: $RELEASE_TYPE" >&2; exit 1 ;; + esac - name: Assert tag if: ${{ env.TAG == 'PLACEHOLDER' }} @@ -71,7 +79,7 @@ jobs: id: build working-directory: ${{ env.EXECUTORCH_DIR }} run: | - if [[ "${{ inputs.latest-build }}" != "true" ]]; then + if [[ "$RELEASE_TYPE" == "nightly" ]]; then ./scripts/create-package.sh generate_nightly_version else ./scripts/create-package.sh From 61540d66e0e090e76781ec879bfefd94b20c21ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82uszniak?= Date: Tue, 4 Aug 2026 15:46:51 +0200 Subject: [PATCH 2/2] ci: allow an explicit dist-tag override A single `legacy` dist-tag only points at one version, so once 0.9 takes it over, a later 0.8 patch published as `legacy` would demote 0.9 back down. Add an optional free-text `dist-tag` input for line-scoped tags like `v0.8`, so each maintenance line keeps a stable install target and nothing has to share `legacy`. Publishing under a throwaway tag and removing it afterwards is not an option here: npm's OIDC trusted publishing authorizes `npm publish` only, so a follow-up `npm dist-tag rm` has no credentials and the junk tag would stick around. The override moves the dist-tag only - the version still comes from release-type - so combining it with nightly is rejected, as is anything npm would refuse as a dist-tag. --- .github/workflows/npm-publish.yml | 36 +++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index d299b9fd80..45f4941a33 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -14,6 +14,11 @@ on: - latest # current stable release - legacy # maintenance release of an older line default: nightly + dist-tag: + description: 'Publish under this exact dist-tag instead, e.g. v0.8 for a maintenance line (leave empty to use release-type)' + required: false + type: string + default: '' permissions: id-token: write @@ -38,6 +43,7 @@ jobs: TAG: PLACEHOLDER # `inputs` is empty on the scheduled run, which is always a nightly. RELEASE_TYPE: ${{ inputs.release-type || 'nightly' }} + DIST_TAG_OVERRIDE: ${{ inputs.dist-tag || '' }} steps: - name: Checkout uses: actions/checkout@v6 @@ -64,12 +70,30 @@ jobs: - name: Set tag run: | - case "$RELEASE_TYPE" in - nightly) echo "TAG=executorch-nightly" >> $GITHUB_ENV ;; - latest) echo "TAG=latest" >> $GITHUB_ENV ;; - legacy) echo "TAG=legacy" >> $GITHUB_ENV ;; - *) echo "Unknown release type: $RELEASE_TYPE" >&2; exit 1 ;; - esac + if [[ -n "$DIST_TAG_OVERRIDE" ]]; then + # The override only moves the dist-tag; the version still comes from + # release-type. Pairing it with nightly would publish a throwaway + # `x.y.z-nightly--` under a tag meant to be stable, which + # is never what you want - fail instead of guessing. + if [[ "$RELEASE_TYPE" == "nightly" ]]; then + echo "dist-tag override needs a stable build: set release-type to latest or legacy." >&2 + exit 1 + fi + # npm rejects a dist-tag that parses as a semver range, so require a + # leading letter. That also rules out bare versions like `0.8`. + if [[ ! "$DIST_TAG_OVERRIDE" =~ ^[a-zA-Z][a-zA-Z0-9._-]*$ ]]; then + echo "Invalid dist-tag: '$DIST_TAG_OVERRIDE' (expected e.g. v0.8)" >&2 + exit 1 + fi + echo "TAG=$DIST_TAG_OVERRIDE" >> $GITHUB_ENV + else + case "$RELEASE_TYPE" in + nightly) echo "TAG=executorch-nightly" >> $GITHUB_ENV ;; + latest) echo "TAG=latest" >> $GITHUB_ENV ;; + legacy) echo "TAG=legacy" >> $GITHUB_ENV ;; + *) echo "Unknown release type: $RELEASE_TYPE" >&2; exit 1 ;; + esac + fi - name: Assert tag if: ${{ env.TAG == 'PLACEHOLDER' }}