From 82aef7cc106602b38abbf8e02b4bca9183b9d547 Mon Sep 17 00:00:00 2001 From: Maxim Belov Date: Fri, 14 Aug 2026 12:34:53 +0200 Subject: [PATCH] chore: publish from CI via Trusted Publishers The release pipeline was inherited from upstream and could not work in this fork. lerna version pushes a release commit and tag straight to stable, which is protected; there is no NPM_TOKEN secret here, so NODE_AUTH_TOKEN would have been an empty string; and 8.0.0 was in fact published by hand, with no provenance. publish:ci is now just npm publish, so nothing writes back to a protected branch, and authentication moves to npm's Trusted Publishers (OIDC) -- no token to store, and provenance attached automatically. Releasing is two steps: a human bumps the version in a pull request, and merging it publishes. A merge that does not change the version is not a release, so CD checks npm first and skips. The Docker steps go. They tagged the image from upstream's published version, unrelated to anything this fork releases, and nothing consumes the image. repository, homepage and bugs now point at this repository, which provenance requires as well. The README gains a short section on why the fork exists. CI dropped its Node 16 and 18 matrix -- both end-of-life, while CD publishes on 24 and every consumer installs on 24 -- for one job on 24. Its trigger was branches-ignore: [stable], and for pull_request that filters the base branch, so pull requests into stable were the only ones that got no checks at all. setup-node's own npm cache replaces the hand-rolled cache step. Verified with actionlint. --- .github/workflows/cd.yml | 65 ++++++++++++++++---------------- .github/workflows/ci.yml | 31 +++++++-------- README.md | 16 ++++++++ package.json | 2 +- packages/@ionic/cli/package.json | 6 +-- 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 7d82e66baf..5ab2785a46 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,47 +5,48 @@ on: branches: - stable +# id-token is what npm's Trusted Publishers exchanges for a short-lived +# credential, so no NPM_TOKEN secret is needed. Nothing here writes to the +# repository or to a registry other than npm. permissions: - contents: write + contents: read id-token: write - packages: write jobs: - build: - name: Build, Test, and Deploy + publish: + name: Publish to npm runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: 18 + # npm >= 11.5.1 is required for the OIDC exchange, which ships with Node 24. + node-version: 24 registry-url: https://registry.npmjs.org/ cache: npm cache-dependency-path: '**/package.json' - - run: npm install - - run: npm run bootstrap - - run: npm run publish:ci - env: - GIT_AUTHOR_NAME: Ionitron - GIT_AUTHOR_EMAIL: hi@ionicframework.com - GIT_COMMITTER_NAME: Ionitron - GIT_COMMITTER_EMAIL: hi@ionicframework.com - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Sleep while npm takes its time - run: sleep 20 - - name: GitHub Container Registry Login - run: echo ${{ github.token }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - name: Build Container + + # The version is bumped by a human in a pull request, not by the CD run, so + # most merges into stable are not releases. Without this the publish step + # would fail on every one of them with EPUBLISHCONFLICT. + - name: Decide whether this is a release + id: check run: | - docker build \ - --build-arg IONIC_CLI_VERSION=$(npm info @ionic/cli dist-tags.latest) \ - --tag ghcr.io/${{ github.repository }}:latest \ - --tag ghcr.io/${{ github.repository}}:$(npm info @ionic/cli dist-tags.latest) \ - . - - name: Push Container as latest - run: docker push ghcr.io/${{ github.repository }}:latest - - name: Push Container as version - run: docker push ghcr.io/${{ github.repository }}:$(npm info @ionic/cli dist-tags.latest) + NAME=$(node -p "require('./packages/@ionic/cli/package.json').name") + VERSION=$(node -p "require('./packages/@ionic/cli/package.json').version") + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + if npm view "$NAME@$VERSION" version > /dev/null 2>&1; then + echo "publish=false" >> "$GITHUB_OUTPUT" + echo "$NAME@$VERSION is already on npm - nothing to publish." + else + echo "publish=true" >> "$GITHUB_OUTPUT" + echo "$NAME@$VERSION is not on npm yet - publishing." + fi + + - if: steps.check.outputs.publish == 'true' + run: npm install + - if: steps.check.outputs.publish == 'true' + run: npm run bootstrap + - if: steps.check.outputs.publish == 'true' + run: npm run publish:ci diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc65031b87..ea5e31b92d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,33 +1,30 @@ name: CI +# Pull requests are checked whatever they target. The previous filter was +# branches-ignore: [stable], which meant the release branch was the one branch +# whose pull requests got no checks at all. on: push: - branches-ignore: + branches: - stable + - develop pull_request: - branches-ignore: - - stable jobs: build-and-test: - name: Build and Test (Node ${{ matrix.node }}) + name: Build and Test runs-on: ubuntu-latest timeout-minutes: 30 - strategy: - matrix: - node: - - 18.x - - 16.x steps: - - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - uses: actions/checkout@v3 - - name: Restore Dependency Cache - uses: actions/cache@v3 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: - path: ~/.npm - key: ${{ runner.OS }}-dependency-cache-${{ hashFiles('**/package.json') }} + # The one version that matters: what CD publishes with, and what the + # projects installing this CLI globally actually run. The matrix used to + # be 16.x and 18.x -- both end-of-life, and neither in use anywhere. + node-version: 24 + cache: npm + cache-dependency-path: '**/package.json' - run: npm install - run: npm run bootstrap - run: npm run lint diff --git a/README.md b/README.md index 9abf7f12f1..ceabaa1ed9 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,22 @@ The Ionic command line interface (CLI) is your go-to tool for developing [Ionic][ionic-homepage] apps. +## Why this fork exists + +Forked from [ionic-team/ionic-cli](https://github.com/ionic-team/ionic-cli) because the CLI looks +for Cordova's iOS build products in `platforms/ios/build/emulator` and +`platforms/ios/build/device`, which cordova-ios no longer writes to. The fix is submitted upstream +as [ionic-team/ionic-cli#5079](https://github.com/ionic-team/ionic-cli/pull/5079); it has been open +since 2024-02-16, so treat this fork as permanent until that merges and ships. + +Published as [`@herdwatch/ionic-cli`](https://www.npmjs.com/package/@herdwatch/ionic-cli). + +Changes from upstream, all on the `stable` branch: + +- Derive the iOS build output path from the Xcode configuration + (`build/Debug-iphonesimulator`, `build/Release-iphoneos`) instead of the removed + `emulator`/`device` directories. + ### Installation ``` diff --git a/package.json b/package.json index 31515dcfac..c1e71c7025 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "docs": "node packages/cli-scripts/bin/ionic-cli-scripts docs", "docs:watch": "chokidar 'packages/cli-scripts/dist/docs/**/*.js' -c 'npm run docs'", "publish:testing": "lerna publish prerelease --preid=testing --exact --no-git-tag-version --no-push --dist-tag=testing", - "publish:ci": "lerna version -m 'chore(release): publish [skip ci]' --exact --conventional-commits --yes && lerna exec --no-private --since HEAD~ -- npm publish" + "publish:ci": "cd packages/@ionic/cli && npm publish" }, "devDependencies": { "@types/inquirer": "0.0.43", diff --git a/packages/@ionic/cli/package.json b/packages/@ionic/cli/package.json index c3bf648888..80314dc86a 100644 --- a/packages/@ionic/cli/package.json +++ b/packages/@ionic/cli/package.json @@ -2,7 +2,7 @@ "name": "@herdwatch/ionic-cli", "version": "8.0.0", "description": "A tool for creating and developing Ionic Framework mobile apps.", - "homepage": "https://ionicframework.com", + "homepage": "https://github.com/herdwatch-apps/ionic-cli#readme", "author": "Ionic Team (https://ionicframework.com) ", "bin": { "ionic": "./bin/ionic" @@ -33,10 +33,10 @@ ], "repository": { "type": "git", - "url": "https://github.com/ionic-team/ionic-cli.git" + "url": "git+https://github.com/herdwatch-apps/ionic-cli.git" }, "bugs": { - "url": "https://github.com/ionic-team/ionic-cli/issues" + "url": "https://github.com/herdwatch-apps/ionic-cli/issues" }, "license": "MIT", "dependencies": {