From 8c5d442f0d9a489d6b9627c8421c00e2c8ddb5e7 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 18:33:18 +0000 Subject: [PATCH 01/23] feat: Set up Craft-based release workflow for npm and GitHub Releases Configure the project for release as `sentry` package on npm (v0.2.0) using Craft and the getsentry/publish workflow. Distribution: - npm: Single bundled JS file (42KB) via esbuild for fast `npx sentry` startup - GitHub Releases: Native Bun binaries for all platforms Key changes: - Add .craft.yml with npm + github targets - Add build.yml workflow with matrix builds and smoke tests - Add release.yml and changelog-preview.yml workflows - Add esbuild bundler with Bun API polyfills for Node.js compatibility - Rename package to `sentry`, set version to 0.2.0 - Move all dependencies to devDependencies (bundled at build time) - Remove old publish.yml and platform package scripts --- .craft.yml | 20 ++++ .github/workflows/build.yml | 97 +++++++++++++++++ .github/workflows/changelog-preview.yml | 13 +++ .github/workflows/ci.yml | 54 ++++++---- .github/workflows/publish.yml | 91 ---------------- .github/workflows/release.yml | 29 +++++ .github/workflows/test.yml | 26 ++--- CHANGELOG.md | 3 + LICENSE.md | 105 ++++++++++++++++++ bun.lock | 135 ++++++++++++++++++------ package.json | 4 +- packages/cli/bin/sentry | 76 ------------- packages/cli/package.json | 33 +++--- packages/cli/script/build.ts | 54 ++-------- packages/cli/script/bundle.ts | 55 ++++++++++ packages/cli/script/node-polyfills.ts | 86 +++++++++++++++ packages/cli/script/package.ts | 123 --------------------- packages/cli/src/app.ts | 5 +- packages/cli/src/bin.ts | 2 +- 19 files changed, 585 insertions(+), 426 deletions(-) create mode 100644 .craft.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/changelog-preview.yml delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE.md delete mode 100755 packages/cli/bin/sentry create mode 100644 packages/cli/script/bundle.ts create mode 100644 packages/cli/script/node-polyfills.ts delete mode 100644 packages/cli/script/package.ts diff --git a/.craft.yml b/.craft.yml new file mode 100644 index 00000000..c5c4db74 --- /dev/null +++ b/.craft.yml @@ -0,0 +1,20 @@ +minVersion: '2.14.0' +changelog: + policy: auto +preReleaseCommand: >- + node -p " + const {execSync} = require('child_process'); + execSync('npm --no-git-tag-version version ' + process.env.CRAFT_NEW_VERSION, {cwd: 'packages/cli'}).toString(); + " +postReleaseCommand: >- + node -p " + const {execSync} = require('child_process'); + execSync('npm --no-git-tag-version version preminor --preid=dev', {cwd: 'packages/cli'}); + execSync('git diff --quiet || git commit -anm \"meta: Bump new development version\\n\\n#skip-changelog\" && git pull --rebase && git push').toString(); + " +requireNames: + - /^sentry-.+$/ + - /^sentry-.*\.tgz$/ +targets: + - name: npm + - name: github diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..85385800 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,97 @@ +name: Build +on: + push: + branches: [main, release/**] + pull_request: + workflow_call: + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-binary: + name: Build Binary (${{ matrix.target }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - target: darwin-arm64 + os: macos-latest + - target: darwin-x64 + os: macos-13 + - target: linux-arm64 + os: ubuntu-24.04-arm + - target: linux-x64 + os: ubuntu-latest + - target: windows-x64 + os: windows-latest + steps: + - uses: actions/checkout@v6 + - uses: oven-sh/setup-bun@v2 + - run: bun install + working-directory: packages/cli + - name: Build + working-directory: packages/cli + env: + SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + run: bun run build + - name: Smoke test + working-directory: packages/cli + shell: bash + run: | + if [[ "${{ matrix.target }}" == "windows-x64" ]]; then + ./dist/sentry-windows-x64/bin/sentry.exe --help + else + ./dist/sentry-${{ matrix.target }}/bin/sentry --help + fi + - name: Upload artifact + uses: actions/upload-artifact@v6 + with: + name: sentry-${{ matrix.target }} + path: packages/cli/dist/sentry-*/bin/sentry* + + build-npm: + name: Build npm Package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: oven-sh/setup-bun@v2 + - uses: actions/setup-node@v6 + with: + node-version: '22' + - run: bun install + working-directory: packages/cli + - name: Bundle + working-directory: packages/cli + env: + SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + run: bun run bundle + - name: Smoke test (Node.js) + working-directory: packages/cli + run: node dist/bin.mjs --help + - name: Pack + working-directory: packages/cli + run: npm pack + - name: Upload artifact + uses: actions/upload-artifact@v6 + with: + name: npm-package + path: packages/cli/*.tgz + + merge-artifacts: + name: Merge Artifacts + needs: [build-binary, build-npm] + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v7 + - name: List artifacts + run: find . -type f + - name: Upload combined artifacts + uses: actions/upload-artifact@v6 + with: + name: ${{ github.sha }} + path: | + sentry-*/ + npm-package/*.tgz diff --git a/.github/workflows/changelog-preview.yml b/.github/workflows/changelog-preview.yml new file mode 100644 index 00000000..75d37a28 --- /dev/null +++ b/.github/workflows/changelog-preview.yml @@ -0,0 +1,13 @@ +name: Changelog Preview +on: + pull_request_target: + types: [opened, synchronize, reopened, edited, labeled, unlabeled] + +permissions: + contents: read + pull-requests: write + +jobs: + changelog-preview: + uses: getsentry/craft/.github/workflows/changelog-preview.yml@v2 + secrets: inherit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd1c2951..586592b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,36 +5,44 @@ on: paths: - 'packages/cli/**' - '.github/workflows/ci.yml' + - '.github/workflows/build.yml' concurrency: group: ci-${{ github.ref }} cancel-in-progress: true -defaults: - run: - working-directory: packages/cli - jobs: - build: - name: Build + lint: + name: Lint & Typecheck runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/cli steps: - - uses: actions/checkout@v4 - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Install dependencies - run: bun install - - - name: Build (current platform only) + - uses: actions/checkout@v6 + - uses: oven-sh/setup-bun@v2 + - run: bun install + - run: bun run lint + - run: bun run typecheck + + test: + name: Test + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/cli + steps: + - uses: actions/checkout@v6 + - uses: oven-sh/setup-bun@v2 + - run: bun install + - name: Test env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} - run: bun run build + SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} + SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} + SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} + run: bun test - - name: Smoke test - run: | - ./dist/sentry-linux-x64/bin/sentry --help - echo "Build successful!" + build: + name: Build + uses: ./.github/workflows/build.yml + secrets: inherit diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 9ceaff0f..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: Publish to npm - -on: - push: - branches: [main] - paths: - - 'packages/cli/**' - - '.github/workflows/publish.yml' - workflow_dispatch: - -concurrency: - group: publish-${{ github.ref }} - cancel-in-progress: false - -defaults: - run: - working-directory: packages/cli - -jobs: - publish: - name: Build and Publish - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Install dependencies - run: bun install - - - name: Bump version - id: version - run: | - # Read current version - CURRENT_VERSION=$(jq -r '.version' package.json) - echo "Current version: $CURRENT_VERSION" - - # Parse major.minor.patch - MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1) - MINOR=$(echo $CURRENT_VERSION | cut -d. -f2) - PATCH=$(echo $CURRENT_VERSION | cut -d. -f3) - - # Increment minor version (0.X.Y -> 0.X+1.0) - NEW_MINOR=$((MINOR + 1)) - NEW_VERSION="${MAJOR}.${NEW_MINOR}.0" - echo "New version: $NEW_VERSION" - - # Update package.json - jq --arg v "$NEW_VERSION" '.version = $v' package.json > package.json.tmp - mv package.json.tmp package.json - - echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT - - - name: Build all platforms - env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} - run: bun run build:all - - - name: Package main CLI - run: bun run package - - - name: Setup npm - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - - - name: Publish platform packages - run: | - for pkg in sentry-darwin-arm64 sentry-darwin-x64 sentry-linux-arm64 sentry-linux-x64 sentry-windows-x64; do - echo "Publishing $pkg..." - cd dist/$pkg && npm publish --access public && cd ../.. - done - - - name: Publish main package - run: | - cd dist/@betegon-sentry && npm publish --access public - - - name: Commit version bump - run: | - cd ../.. - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git add packages/cli/package.json - git commit -m "chore: bump CLI version to ${{ steps.version.outputs.version }}" - git push diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..aba6a5fc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: Release +on: + workflow_dispatch: + inputs: + version: + description: Version to release (semver, bump type, or "auto") + required: true + default: 'auto' + force: + description: Force release even with blockers + required: false + +jobs: + build: + uses: ./.github/workflows/build.yml + permissions: + contents: read + secrets: inherit + + release: + needs: [build] + uses: getsentry/craft/.github/workflows/release.yml@v2 + with: + version: ${{ inputs.version }} + force: ${{ inputs.force }} + publish_repo: getsentry/publish + secrets: inherit + permissions: + contents: write diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84c8fb0b..3f059647 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,17 +6,10 @@ on: paths: - 'packages/cli/**' - '.github/workflows/test.yml' - pull_request: - branches: [main] - paths: - - 'packages/cli/**' - - '.github/workflows/test.yml' - workflow_dispatch: # Manual trigger + workflow_dispatch: permissions: contents: read - actions: read - pull-requests: write jobs: test: @@ -27,13 +20,9 @@ jobs: working-directory: packages/cli steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest + - uses: oven-sh/setup-bun@v2 - name: Install dependencies run: bun install @@ -43,11 +32,10 @@ jobs: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} - run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov + run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov - name: Upload Coverage - uses: getsentry/codecov-action@main + uses: codecov/codecov-action@v5 with: - token: ${{ secrets.GITHUB_TOKEN }} - post-pr-comment: true - + token: ${{ secrets.CODECOV_TOKEN }} + files: packages/cli/coverage/lcov.info diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..fccde639 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..6e9bafc7 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,105 @@ +# Functional Source License, Version 1.1, Apache 2.0 Future License + +## Abbreviation + +FSL-1.1-Apache-2.0 + +## Notice + +Copyright 2025 Functional Software, Inc. dba Sentry + +## Terms and Conditions + +### Licensor ("We") + +The party offering the Software under these Terms and Conditions. + +### The Software + +The "Software" is each version of the software that we make available under +these Terms and Conditions, as indicated by our inclusion of these Terms and +Conditions with the Software. + +### License Grant + +Subject to your compliance with this License Grant and the Patents, +Redistribution and Trademark clauses below, we hereby grant you the right to +use, copy, modify, create derivative works, publicly perform, publicly display +and redistribute the Software for any Permitted Purpose identified below. + +### Permitted Purpose + +A Permitted Purpose is any purpose other than a Competing Use. A Competing Use +means making the Software available to others in a commercial product or +service that: + +1. substitutes for the Software; + +2. substitutes for any other product or service we offer using the Software + that exists as of the date we make the Software available; or + +3. offers the same or substantially similar functionality as the Software. + +Permitted Purposes specifically include using the Software: + +1. for your internal use and access; + +2. for non-commercial education; + +3. for non-commercial research; and + +4. in connection with professional services that you provide to a licensee + using the Software in accordance with these Terms and Conditions. + +### Patents + +To the extent your use for a Permitted Purpose would necessarily infringe our +patents, the license grant above includes a license under our patents. If you +make a claim against any party that the Software infringes or contributes to +the infringement of any patent, then your patent license to the Software ends +immediately. + +### Redistribution + +The Terms and Conditions apply to all copies, modifications and derivatives of +the Software. + +If you redistribute any copies, modifications or derivatives of the Software, +you must include a copy of or a link to these Terms and Conditions and not +remove any copyright notices provided in or with the Software. + +### Disclaimer + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR +PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT. + +IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE +SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, +EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE. + +### Trademarks + +Except for displaying the License Details and identifying us as the origin of +the Software, you have no right under these Terms and Conditions to use our +trademarks, trade names, service marks or product names. + +## Grant of Future License + +We hereby irrevocably grant you an additional license to use the Software under +the Apache License, Version 2.0 that is effective on the second anniversary of +the date we make the Software available. On or after that date, you may use the +Software under the Apache License, Version 2.0, in which case the following +will apply: + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/bun.lock b/bun.lock index 6fcdffe3..73d782f3 100644 --- a/bun.lock +++ b/bun.lock @@ -12,51 +12,28 @@ }, }, "packages/cli": { - "name": "@betegon/sentry", - "version": "0.16.0", + "name": "sentry", + "version": "0.2.0", "bin": { - "sentry": "./bin/sentry", + "sentry": "./dist/bin.mjs", }, - "dependencies": { - "@ast-grep/napi": "^0.31.0", + "devDependencies": { "@stricli/auto-complete": "^1.2.4", "@stricli/core": "^1.2.4", - "chalk": "^5.6.2", - "ky": "^1.14.2", - "qrcode-terminal": "^0.12.0", - "zod": "^3.24.0", - }, - "devDependencies": { "@types/bun": "latest", "@types/node": "^20", "@types/qrcode-terminal": "^0.12.2", + "chalk": "^5.6.2", + "esbuild": "^0.25.0", + "fast-glob": "^3.3.3", + "ky": "^1.14.2", + "qrcode-terminal": "^0.12.0", "typescript": "^5", + "zod": "^3.24.0", }, }, }, "packages": { - "@ast-grep/napi": ["@ast-grep/napi@0.31.1", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.31.1", "@ast-grep/napi-darwin-x64": "0.31.1", "@ast-grep/napi-linux-arm64-gnu": "0.31.1", "@ast-grep/napi-linux-arm64-musl": "0.31.1", "@ast-grep/napi-linux-x64-gnu": "0.31.1", "@ast-grep/napi-linux-x64-musl": "0.31.1", "@ast-grep/napi-win32-arm64-msvc": "0.31.1", "@ast-grep/napi-win32-ia32-msvc": "0.31.1", "@ast-grep/napi-win32-x64-msvc": "0.31.1" } }, "sha512-XOFCIeCYdXeRhp1OesRtes/sjPlTSe9Q7tKLLztM8sbDVYgla8k1eCTU3ia7xYIwdK3pjwc39akb8Z7qlOpzHg=="], - - "@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-i2GOKyowGyGWwnwBmzZj8MFACTh5QzWrYTV7Si7V+4JjYLlrm94A/KgxBWX16mwXQr1qxziS6GjlQDqRSBxCtw=="], - - "@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-oUyxBoWT6o1hsJ1H0id9PkK2jgwDS1RSziZ+ORJxlV+VuvXbqPC2yrrqjWK60yBSK49GPNQjuQueGC3Js9Zqhg=="], - - "@ast-grep/napi-linux-arm64-gnu": ["@ast-grep/napi-linux-arm64-gnu@0.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-UVGjseE/RLW2Qx21t8TSGArFgmud2YPqdpgneLuRiW4unM9FIM1PKyxnm9AKzkQbJJzpG7CSWBnMbVkmvWMB/A=="], - - "@ast-grep/napi-linux-arm64-musl": ["@ast-grep/napi-linux-arm64-musl@0.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-K6LBPjbd1ugHYG4EPaepYgfg7M2UOpTC1fFGkViLuONDfpiH5A/i0HAkcDBkEbfzcOGv2WU7aqnHJ2rqKDLodg=="], - - "@ast-grep/napi-linux-x64-gnu": ["@ast-grep/napi-linux-x64-gnu@0.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-VeJ5XVFyETypqIxTcB0JaMt+dadOHzXnrU5qSrbUsrnhtIUoleazvxHEzaoXQ0wglCVgl0odLAwgcwkHRxJ/Pg=="], - - "@ast-grep/napi-linux-x64-musl": ["@ast-grep/napi-linux-x64-musl@0.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-6pGQDPiaMqSHXCahVoJCpThc8TEk7HaJBP/n+xay/OTwqrqe54nS6baRnEm9k5q9vh4V2ceaOVf3754tkg8TSg=="], - - "@ast-grep/napi-win32-arm64-msvc": ["@ast-grep/napi-win32-arm64-msvc@0.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-JVIFHBDPoxVjG5c/XauJywypn1wkv0I+WqiwIzlMTNpqmEoJEnJGIom3gJZGqgrFmPpc6/PiATTw6DEjGJs4QA=="], - - "@ast-grep/napi-win32-ia32-msvc": ["@ast-grep/napi-win32-ia32-msvc@0.31.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-PTyEPvJgNuvzj0kWyR9/0+AAL13LftvGijp5sZ0lgXIpig8MfF3czIU62Nf6AMpABhsu0h+u4KmD4DaMxdw0EA=="], - - "@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-tEgj2Fp2Pi5qXXDLR3AWkZwQTj8yeSN3I7Pvw2DOfINu9imE2EY+Aq5kOhfvduGWVPmP8az68xUFC4b29+yrUw=="], - - "@betegon/sentry": ["@betegon/sentry@workspace:packages/cli"], - "@biomejs/biome": ["@biomejs/biome@2.3.8", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.8", "@biomejs/cli-darwin-x64": "2.3.8", "@biomejs/cli-linux-arm64": "2.3.8", "@biomejs/cli-linux-arm64-musl": "2.3.8", "@biomejs/cli-linux-x64": "2.3.8", "@biomejs/cli-linux-x64-musl": "2.3.8", "@biomejs/cli-win32-arm64": "2.3.8", "@biomejs/cli-win32-x64": "2.3.8" }, "bin": { "biome": "bin/biome" } }, "sha512-Qjsgoe6FEBxWAUzwFGFrB+1+M8y/y5kwmg5CHac+GSVOdmOIqsAiXM5QMVGZJ1eCUCLlPZtq4aFAQ0eawEUuUA=="], "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HM4Zg9CGQ3txTPflxD19n8MFPrmUAjaC7PQdLkugeeC0cQ+PiVrd7i09gaBS/11QKsTDBJhVg85CEIK9f50Qww=="], @@ -79,10 +56,68 @@ "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@stricli/auto-complete": ["@stricli/auto-complete@1.2.4", "", { "dependencies": { "@stricli/core": "^1.2.4" }, "bin": { "auto-complete": "dist/bin/cli.js" } }, "sha512-MxGgeBbFyH+YtzhIjJeOr68NSx0r8mn4+hWRGgWn31YTG9u0Oa2y9oGHPY+PHeoTfvS7vhgllFvOrHcTVpwTrA=="], "@stricli/core": ["@stricli/core@1.2.4", "", {}, "sha512-ujvJDQpC2FINWvlTjkFz+Qzw/vsB8p/LyZEW18idisqIyjXR6yb+sF3WTUPksl+5ZON5r4fHQnCqQWnJxeqSzg=="], @@ -95,6 +130,8 @@ "@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="], + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -109,16 +146,36 @@ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], "ky": ["ky@1.14.2", "", {}, "sha512-q3RBbsO5A5zrPhB6CaCS8ZUv+NWCXv6JJT4Em0i264G9W0fdPB8YRfnnEi7Dm7X7omAkBIPojzYJ2D1oHTHqug=="], "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], @@ -131,14 +188,26 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], "qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "sentry": ["sentry@workspace:packages/cli"], + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "trpc-cli": ["trpc-cli@0.12.1", "", { "dependencies": { "commander": "^14.0.0" }, "peerDependencies": { "@orpc/server": "^1.0.0", "@trpc/server": "^10.45.2 || ^11.0.1", "@valibot/to-json-schema": "^1.1.0", "effect": "^3.14.2 || ^4.0.0", "valibot": "^1.1.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@orpc/server", "@trpc/server", "@valibot/to-json-schema", "effect", "valibot", "zod"], "bin": { "trpc-cli": "dist/bin.js" } }, "sha512-/D/mIQf3tUrS7ZKJZ1gmSPJn2psAABJfkC5Eevm55SZ4s6KwANOUNlwhAGXN9HT4VSJVfoF2jettevE9vHPQlg=="], "turbo": ["turbo@2.6.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.3", "turbo-darwin-arm64": "2.6.3", "turbo-linux-64": "2.6.3", "turbo-linux-arm64": "2.6.3", "turbo-windows-64": "2.6.3", "turbo-windows-arm64": "2.6.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA=="], diff --git a/package.json b/package.json index 80c3f551..9be4e343 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "sentry-cli-next", - "version": "0.1.0", + "name": "sentry-cli-monorepo", + "version": "0.2.0", "private": true, "packageManager": "bun@1.3.3", "description": "A gh-like CLI for Sentry", diff --git a/packages/cli/bin/sentry b/packages/cli/bin/sentry deleted file mode 100755 index 36366ee5..00000000 --- a/packages/cli/bin/sentry +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env node - -const childProcess = require("child_process") -const fs = require("fs") -const path = require("path") -const os = require("os") - -function run(target) { - const result = childProcess.spawnSync(target, process.argv.slice(2), { - stdio: "inherit", - }) - if (result.error) { - console.error(result.error.message) - process.exit(1) - } - const code = typeof result.status === "number" ? result.status : 0 - process.exit(code) -} - -const platformMap = { - darwin: "darwin", - linux: "linux", - win32: "windows", -} - -const archMap = { - x64: "x64", - arm64: "arm64", -} - -let platform = platformMap[os.platform()] -if (!platform) { - console.error(`Unsupported platform: ${os.platform()}`) - process.exit(1) -} - -let arch = archMap[os.arch()] -if (!arch) { - console.error(`Unsupported architecture: ${os.arch()}`) - process.exit(1) -} - -const packageName = `sentry-${platform}-${arch}` -const binaryName = platform === "windows" ? "sentry.exe" : "sentry" - -function findBinary(startDir) { - let current = startDir - for (;;) { - const modules = path.join(current, "node_modules") - if (fs.existsSync(modules)) { - const candidate = path.join(modules, packageName, "bin", binaryName) - if (fs.existsSync(candidate)) { - return candidate - } - } - const parent = path.dirname(current) - if (parent === current) { - return null - } - current = parent - } -} - -const scriptDir = path.dirname(fs.realpathSync(__filename)) -const resolved = findBinary(scriptDir) - -if (!resolved) { - console.error( - `Could not find the sentry binary for your platform.\n` + - `Expected package: ${packageName}\n` + - `You can try manually installing it: npm install ${packageName}` - ) - process.exit(1) -} - -run(resolved) diff --git a/packages/cli/package.json b/packages/cli/package.json index 3dc790c0..dde92df8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,17 +1,19 @@ { - "name": "@betegon/sentry", - "version": "0.19.0", - "description": "A gh-like CLI for Sentry", + "name": "sentry", + "version": "0.2.0", + "description": "Sentry CLI - A command-line interface for Sentry", "type": "module", "bin": { - "sentry": "./bin/sentry" + "sentry": "./dist/bin.mjs" }, + "files": [ + "dist/bin.mjs" + ], "scripts": { "dev": "bun run src/bin.ts", "build": "bun run script/build.ts --single", "build:all": "bun run script/build.ts", - "package": "bun run script/package.ts", - "prepublish": "bun run script/build.ts && bun run script/package.ts", + "bundle": "bun run script/bundle.ts", "typecheck": "tsc --noEmit", "lint": "bunx ultracite check", "lint:fix": "bunx ultracite fix", @@ -19,18 +21,25 @@ "test:e2e": "bun test test/e2e" }, "devDependencies": { + "@stricli/auto-complete": "^1.2.4", + "@stricli/core": "^1.2.4", "@types/bun": "latest", "@types/node": "^20", "@types/qrcode-terminal": "^0.12.2", - "typescript": "^5" - }, - "dependencies": { - "@ast-grep/napi": "^0.31.0", - "@stricli/auto-complete": "^1.2.4", - "@stricli/core": "^1.2.4", "chalk": "^5.6.2", + "esbuild": "^0.25.0", + "fast-glob": "^3.3.3", "ky": "^1.14.2", "qrcode-terminal": "^0.12.0", + "typescript": "^5", "zod": "^3.24.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/getsentry/cli.git" + }, + "license": "FSL-1.1-Apache-2.0", + "engines": { + "node": ">=18" } } diff --git a/packages/cli/script/build.ts b/packages/cli/script/build.ts index e63ca29d..6ded3b82 100644 --- a/packages/cli/script/build.ts +++ b/packages/cli/script/build.ts @@ -3,7 +3,7 @@ * Build script for Sentry CLI * * Creates standalone executables for multiple platforms using Bun.build(). - * Each platform gets its own npm package structure in dist/. + * Binaries are uploaded to GitHub Releases. * * Usage: * bun run script/build.ts # Build for all platforms @@ -13,10 +13,8 @@ * dist/ * sentry-darwin-arm64/ * bin/sentry - * package.json * sentry-darwin-x64/ * bin/sentry - * package.json * ... */ @@ -25,14 +23,10 @@ import pkg from "../package.json"; const VERSION = pkg.version; -/** - * Build-time constants injected into the binary - */ +/** Build-time constants injected into the binary */ const SENTRY_CLIENT_ID = process.env.SENTRY_CLIENT_ID ?? ""; -/** - * Build targets configuration - */ +/** Build targets configuration */ type BuildTarget = { os: "darwin" | "linux" | "win32"; arch: "arm64" | "x64"; @@ -46,24 +40,18 @@ const ALL_TARGETS: BuildTarget[] = [ { os: "win32", arch: "x64" }, ]; -/** - * Get package name for a target (uses "windows" instead of "win32" for npm) - */ +/** Get package name for a target (uses "windows" instead of "win32") */ function getPackageName(target: BuildTarget): string { const platformName = target.os === "win32" ? "windows" : target.os; return `sentry-${platformName}-${target.arch}`; } -/** - * Get Bun compile target string - */ +/** Get Bun compile target string */ function getBunTarget(target: BuildTarget): string { return `bun-${target.os}-${target.arch}`; } -/** - * Build for a single target - */ +/** Build for a single target */ async function buildTarget(target: BuildTarget): Promise { const packageName = getPackageName(target); const binaryName = target.os === "win32" ? "sentry.exe" : "sentry"; @@ -100,30 +88,12 @@ async function buildTarget(target: BuildTarget): Promise { return false; } - // Create package.json for this platform package - // Note: os field uses "win32" for Windows (npm's convention) - await Bun.file(`dist/${packageName}/package.json`).write( - JSON.stringify( - { - name: packageName, - version: VERSION, - os: [target.os], - cpu: [target.arch], - description: "Platform-specific binary for @betegon/sentry CLI", - }, - null, - 2 - ) - ); - console.log(` -> ${outfile}`); return true; } -/** - * Main build function - */ -async function build(): Promise> { +/** Main build function */ +async function build(): Promise { const args = process.argv.slice(2); const singleBuild = args.includes("--single"); @@ -165,7 +135,6 @@ async function build(): Promise> { console.log(""); // Build all targets - const binaries: Record = {}; let successCount = 0; let failCount = 0; @@ -173,7 +142,6 @@ async function build(): Promise> { const success = await buildTarget(target); if (success) { successCount += 1; - binaries[getPackageName(target)] = VERSION; } else { failCount += 1; } @@ -186,10 +154,6 @@ async function build(): Promise> { if (failCount > 0) { process.exit(1); } - - return binaries; } -// Run build and export binaries for use by package.ts -const binaries = await build(); -export { binaries, VERSION }; +await build(); diff --git a/packages/cli/script/bundle.ts b/packages/cli/script/bundle.ts new file mode 100644 index 00000000..1aaaf848 --- /dev/null +++ b/packages/cli/script/bundle.ts @@ -0,0 +1,55 @@ +#!/usr/bin/env bun +/** + * Bundle script for npm package + * + * Creates a single-file Node.js bundle using esbuild. + * Injects Bun polyfills for Node.js compatibility. + * + * Usage: + * bun run script/bundle.ts + * + * Output: + * dist/bin.mjs - Minified, single-file bundle for npm + */ +import { build } from "esbuild"; +import pkg from "../package.json"; + +const VERSION = pkg.version; +const SENTRY_CLIENT_ID = process.env.SENTRY_CLIENT_ID ?? ""; + +console.log(`\nBundling sentry v${VERSION} for npm`); +console.log("=".repeat(40)); + +if (!SENTRY_CLIENT_ID) { + console.warn( + "\nWarning: SENTRY_CLIENT_ID not set. OAuth will not work in the bundled package." + ); + console.warn(" Set it via: SENTRY_CLIENT_ID=xxx bun run bundle\n"); +} + +const result = await build({ + entryPoints: ["./src/bin.ts"], + bundle: true, + minify: true, + platform: "node", + target: "node18", + format: "esm", + outfile: "./dist/bin.mjs", + inject: ["./script/node-polyfills.ts"], + define: { + SENTRY_CLI_VERSION: JSON.stringify(VERSION), + SENTRY_CLIENT_ID_BUILD: JSON.stringify(SENTRY_CLIENT_ID), + }, + // Keep Node.js built-ins external - they're available in the runtime + packages: "external", + metafile: true, +}); + +// Calculate bundle size +const outputs = Object.values(result.metafile?.outputs || {}); +const bundleSize = outputs.reduce((sum, out) => sum + out.bytes, 0); +const bundleSizeKB = (bundleSize / 1024).toFixed(1); + +console.log(`\n -> dist/bin.mjs (${bundleSizeKB} KB)`); +console.log(`\n${"=".repeat(40)}`); +console.log("Bundle complete!"); diff --git a/packages/cli/script/node-polyfills.ts b/packages/cli/script/node-polyfills.ts new file mode 100644 index 00000000..63dc8c43 --- /dev/null +++ b/packages/cli/script/node-polyfills.ts @@ -0,0 +1,86 @@ +/** + * Node.js polyfills for Bun APIs + * + * Injected at esbuild bundle time to provide Node.js-compatible + * implementations of Bun globals. This allows the same source code + * to run on both Bun (native) and Node.js (polyfilled). + */ +import { execSync, spawn as nodeSpawn } from "node:child_process"; +import { access, readFile, writeFile } from "node:fs/promises"; + +import fg from "fast-glob"; + +declare global { + var Bun: typeof BunPolyfill; +} + +const BunPolyfill = { + file(path: string) { + return { + async exists(): Promise { + try { + await access(path); + return true; + } catch { + return false; + } + }, + text(): Promise { + return readFile(path, "utf-8"); + }, + async json(): Promise { + const text = await readFile(path, "utf-8"); + return JSON.parse(text); + }, + }; + }, + + async write(path: string, content: string): Promise { + await writeFile(path, content, "utf-8"); + }, + + which(command: string): string | null { + try { + const isWindows = process.platform === "win32"; + const cmd = isWindows ? `where ${command}` : `which ${command}`; + return ( + execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }) + .trim() + .split("\n")[0] || null + ); + } catch { + return null; + } + }, + + spawn(cmd: string[], opts?: { stdio?: string[] }) { + const [command, ...args] = cmd; + const proc = nodeSpawn(command, args, { + detached: true, + stdio: (opts?.stdio as "ignore") || "ignore", + }); + return { + unref() { + proc.unref(); + }, + }; + }, + + sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); + }, + + Glob: class BunGlobPolyfill { + private pattern: string; + constructor(pattern: string) { + this.pattern = pattern; + } + scan(opts?: { cwd?: string }): AsyncIterable { + return fg.stream(this.pattern, { + cwd: opts?.cwd || process.cwd(), + }) as AsyncIterable; + } + }, +}; + +globalThis.Bun = BunPolyfill as typeof Bun; diff --git a/packages/cli/script/package.ts b/packages/cli/script/package.ts deleted file mode 100644 index 78517a3e..00000000 --- a/packages/cli/script/package.ts +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env bun -/** - * Package script for Sentry CLI - * - * Creates the main @betegon/sentry package with: - * - bin/sentry launcher script (Node.js) - * - package.json with optionalDependencies on platform packages - * - * Run this after build.ts to prepare all packages for publishing. - * - * Usage: - * bun run script/package.ts - * - * Output: - * dist/@betegon/sentry/ - * bin/sentry - * package.json - */ - -import { $ } from "bun"; -import path from "path"; -import { fileURLToPath } from "url"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const cliDir = path.resolve(__dirname, ".."); - -process.chdir(cliDir); - -// Import binaries from build (assumes build.ts was run) -import pkg from "../package.json"; - -const VERSION = pkg.version; -const MAIN_PACKAGE_NAME = "@betegon/sentry"; - -// Platform packages that should exist in dist/ -const PLATFORM_PACKAGES = [ - "sentry-darwin-arm64", - "sentry-darwin-x64", - "sentry-linux-arm64", - "sentry-linux-x64", - "sentry-windows-x64", -]; - -async function packageMain(): Promise { - console.log(`\nPackaging ${MAIN_PACKAGE_NAME} v${VERSION}`); - console.log("=".repeat(40)); - - // Verify platform packages exist - console.log("\nVerifying platform packages..."); - const binaries: Record = {}; - - for (const name of PLATFORM_PACKAGES) { - const pkgPath = `dist/${name}/package.json`; - const exists = await Bun.file(pkgPath).exists(); - if (exists) { - binaries[name] = VERSION; - console.log(` Found ${name}`); - } else { - console.warn(` Warning: ${name} not found - run build.ts first`); - } - } - - if (Object.keys(binaries).length === 0) { - console.error("\nNo platform packages found. Run build.ts first:"); - console.error(" bun run script/build.ts"); - process.exit(1); - } - - // Create main package directory - const mainPkgDir = `dist/${MAIN_PACKAGE_NAME.replace("/", "-")}`; - await $`mkdir -p ${mainPkgDir}/bin`; - - // Copy launcher script - console.log("\nCopying launcher script..."); - await $`cp bin/sentry ${mainPkgDir}/bin/sentry`; - await $`chmod +x ${mainPkgDir}/bin/sentry`; - console.log(` -> ${mainPkgDir}/bin/sentry`); - - // Create package.json for main package - console.log("\nCreating package.json..."); - const mainPkg = { - name: MAIN_PACKAGE_NAME, - version: VERSION, - description: "A gh-like CLI for Sentry", - bin: { - sentry: "./bin/sentry", - }, - optionalDependencies: binaries, - repository: { - type: "git", - url: "https://github.com/betegon/sentry-cli-next", - }, - license: "MIT", - engines: { - node: ">=18", - }, - }; - - await Bun.file(`${mainPkgDir}/package.json`).write( - JSON.stringify(mainPkg, null, 2) - ); - console.log(` -> ${mainPkgDir}/package.json`); - - // Summary - console.log(`\n${"=".repeat(40)}`); - console.log("Packaging complete!"); - console.log("\nPackages ready for publishing:"); - console.log(` Main: ${mainPkgDir}/`); - for (const name of Object.keys(binaries)) { - console.log(` Platform: dist/${name}/`); - } - - console.log("\nTo publish manually:"); - console.log(" # First, publish platform packages:"); - for (const name of Object.keys(binaries)) { - console.log(` cd dist/${name} && npm publish --access public && cd ../..`); - } - console.log("\n # Then, publish main package:"); - console.log(` cd ${mainPkgDir} && npm publish --access public`); -} - -await packageMain(); diff --git a/packages/cli/src/app.ts b/packages/cli/src/app.ts index 0cf4fc28..4b76e72b 100644 --- a/packages/cli/src/app.ts +++ b/packages/cli/src/app.ts @@ -24,9 +24,12 @@ const routes = buildRouteMap({ }, }); +declare const SENTRY_CLI_VERSION: string; + export const app = buildApplication(routes, { name: "sentry", versionInfo: { - currentVersion: "0.1.0", + currentVersion: + typeof SENTRY_CLI_VERSION !== "undefined" ? SENTRY_CLI_VERSION : "0.0.0", }, }); diff --git a/packages/cli/src/bin.ts b/packages/cli/src/bin.ts index 0995a3ba..21eaa1f2 100755 --- a/packages/cli/src/bin.ts +++ b/packages/cli/src/bin.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env bun +#!/usr/bin/env node import { run } from "@stricli/core"; import { app } from "./app.js"; import { buildContext } from "./context.js"; From b119aafab90d3cc323fcaeb6e2d6398c10e25408 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 18:56:06 +0000 Subject: [PATCH 02/23] fix: resolve pre-existing lint issues - Add biome-ignore comments for intentional barrel files - Add biome-ignore for formatEventDetails complexity (formatting logic) - Configure biome overrides for test files (regex in assertions, delete, etc.) - Apply auto-fixes from biome (numeric separators, formatting) - Add .turbo to .gitignore --- .gitignore | 1 + biome.jsonc | 22 +++++++++++++++++++++- packages/cli/src/lib/dsn/index.ts | 1 + packages/cli/src/lib/formatters/human.ts | 1 + packages/cli/src/lib/formatters/index.ts | 1 + packages/cli/src/types/index.ts | 1 + packages/cli/test/commands/api.test.ts | 1 + packages/cli/test/e2e/event.test.ts | 2 +- packages/cli/test/e2e/project.test.ts | 2 +- packages/cli/test/fixture.ts | 4 ++-- packages/cli/test/lib/dsn/detector.test.ts | 4 +++- packages/cli/test/preload.ts | 16 ++++++++++------ 12 files changed, 44 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 6d1fc723..8ed1cd20 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json .eslintcache .cache *.tsbuildinfo +.turbo # IntelliJ based IDEs .idea diff --git a/biome.jsonc b/biome.jsonc index a36fa09f..8dcab375 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -3,5 +3,25 @@ "extends": ["ultracite/core"], "javascript": { "globals": ["Bun"] - } + }, + "overrides": [ + { + "includes": ["packages/cli/test/**/*.ts"], + "linter": { + "rules": { + "performance": { + "useTopLevelRegex": "off", + "noDelete": "off" + }, + "style": { + "useBlockStatements": "off", + "noNonNullAssertion": "off" + }, + "suspicious": { + "useAwait": "off" + } + } + } + } + ] } diff --git a/packages/cli/src/lib/dsn/index.ts b/packages/cli/src/lib/dsn/index.ts index ed716b16..af2541e5 100644 --- a/packages/cli/src/lib/dsn/index.ts +++ b/packages/cli/src/lib/dsn/index.ts @@ -1,3 +1,4 @@ +// biome-ignore-all lint/performance/noBarrelFile: intentional public API /** * DSN Detection Module * diff --git a/packages/cli/src/lib/formatters/human.ts b/packages/cli/src/lib/formatters/human.ts index a944744d..49bcbdd5 100644 --- a/packages/cli/src/lib/formatters/human.ts +++ b/packages/cli/src/lib/formatters/human.ts @@ -368,6 +368,7 @@ export function formatIssueDetails(issue: SentryIssue): string[] { * @param header - Optional header text (defaults to "Latest Event") * @returns Array of formatted lines */ +// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: formatting logic export function formatEventDetails( event: SentryEvent, header = "Latest Event" diff --git a/packages/cli/src/lib/formatters/index.ts b/packages/cli/src/lib/formatters/index.ts index 7fa2aa73..18b088a9 100644 --- a/packages/cli/src/lib/formatters/index.ts +++ b/packages/cli/src/lib/formatters/index.ts @@ -1,3 +1,4 @@ +// biome-ignore-all lint/performance/noBarrelFile: intentional public API /** * Formatters * diff --git a/packages/cli/src/types/index.ts b/packages/cli/src/types/index.ts index cc01d24b..d172efc1 100644 --- a/packages/cli/src/types/index.ts +++ b/packages/cli/src/types/index.ts @@ -1,3 +1,4 @@ +// biome-ignore-all lint/performance/noBarrelFile: intentional public API /** * Type definitions for the Sentry CLI * diff --git a/packages/cli/test/commands/api.test.ts b/packages/cli/test/commands/api.test.ts index 143d5581..bfed9232 100644 --- a/packages/cli/test/commands/api.test.ts +++ b/packages/cli/test/commands/api.test.ts @@ -1,3 +1,4 @@ +// biome-ignore-all lint/performance/useTopLevelRegex: regex in test assertions is fine /** * API Command Unit Tests * diff --git a/packages/cli/test/e2e/event.test.ts b/packages/cli/test/e2e/event.test.ts index df159122..8b5b5d6b 100644 --- a/packages/cli/test/e2e/event.test.ts +++ b/packages/cli/test/e2e/event.test.ts @@ -42,7 +42,7 @@ afterEach(() => { if (originalConfigDir) { process.env.SENTRY_CLI_CONFIG_DIR = originalConfigDir; } else { - delete process.env.SENTRY_CLI_CONFIG_DIR; + process.env.SENTRY_CLI_CONFIG_DIR = undefined; } }); diff --git a/packages/cli/test/e2e/project.test.ts b/packages/cli/test/e2e/project.test.ts index bdbafb29..ca736190 100644 --- a/packages/cli/test/e2e/project.test.ts +++ b/packages/cli/test/e2e/project.test.ts @@ -243,6 +243,6 @@ describe("sentry project get", () => { expect(result.exitCode).toBe(1); expect(result.stderr + result.stdout).toMatch(/not found|error|404/i); }, - { timeout: 15000 } + { timeout: 15_000 } ); }); diff --git a/packages/cli/test/fixture.ts b/packages/cli/test/fixture.ts index 8a9b7783..849c226b 100644 --- a/packages/cli/test/fixture.ts +++ b/packages/cli/test/fixture.ts @@ -89,11 +89,11 @@ export function mockProcess() { // CLI Runner // ───────────────────────────────────────────────────────────────────────────── -export interface CliResult { +export type CliResult = { stdout: string; stderr: string; exitCode: number; -} +}; /** * Run CLI command and capture output diff --git a/packages/cli/test/lib/dsn/detector.test.ts b/packages/cli/test/lib/dsn/detector.test.ts index b55d606c..0be67d8d 100644 --- a/packages/cli/test/lib/dsn/detector.test.ts +++ b/packages/cli/test/lib/dsn/detector.test.ts @@ -169,7 +169,9 @@ describe("DSN Detector (New Module)", () => { const distDsn = "https://dist@o222.ingest.sentry.io/222"; // Put DSNs in directories that should be skipped - mkdirSync(join(testDir, "node_modules/some-package"), { recursive: true }); + mkdirSync(join(testDir, "node_modules/some-package"), { + recursive: true, + }); writeFileSync( join(testDir, "node_modules/some-package/index.js"), `Sentry.init({ dsn: "${nodeModulesDsn}" })` diff --git a/packages/cli/test/preload.ts b/packages/cli/test/preload.ts index b2653075..52ae099e 100644 --- a/packages/cli/test/preload.ts +++ b/packages/cli/test/preload.ts @@ -16,10 +16,14 @@ if (existsSync(envLocalPath)) { const content = readFileSync(envLocalPath, "utf-8"); for (const line of content.split("\n")) { const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith("#")) continue; + if (!trimmed || trimmed.startsWith("#")) { + continue; + } const eqIndex = trimmed.indexOf("="); - if (eqIndex === -1) continue; + if (eqIndex === -1) { + continue; + } const key = trimmed.slice(0, eqIndex).trim(); let value = trimmed.slice(eqIndex + 1).trim(); @@ -48,10 +52,10 @@ process.env.SENTRY_CLI_CONFIG_DIR = testDir; // Clear Sentry environment variables to ensure clean state // (but preserve SENTRY_TEST_* vars for E2E tests) -delete process.env.SENTRY_DSN; -delete process.env.SENTRY_AUTH_TOKEN; -delete process.env.SENTRY_CLIENT_ID; -delete process.env.SENTRY_URL; +process.env.SENTRY_DSN = undefined; +process.env.SENTRY_AUTH_TOKEN = undefined; +process.env.SENTRY_CLIENT_ID = undefined; +process.env.SENTRY_URL = undefined; // Cleanup after all tests process.on("exit", () => { From 0d939073b4e9c3a6a5f7987a6fbe8ce9191dc5bb Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:07:34 +0000 Subject: [PATCH 03/23] refactor: merge test into CI workflow with build dependency - CI workflow now includes lint, test, and build jobs - Build jobs depend on lint and test passing first - Revert test.yml to original (main branch) state - Keep build.yml as reusable workflow for release.yml - Use v4 for all actions (checkout, setup-node, upload/download-artifact) --- .github/workflows/build.yml | 22 ++++++++-------------- .github/workflows/ci.yml | 11 +++++++++-- .github/workflows/test.yml | 26 +++++++++++++++++++------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85385800..4a61443d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,14 +1,8 @@ name: Build + on: - push: - branches: [main, release/**] - pull_request: workflow_call: -concurrency: - group: build-${{ github.ref }} - cancel-in-progress: true - jobs: build-binary: name: Build Binary (${{ matrix.target }}) @@ -28,7 +22,7 @@ jobs: - target: windows-x64 os: windows-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install working-directory: packages/cli @@ -47,7 +41,7 @@ jobs: ./dist/sentry-${{ matrix.target }}/bin/sentry --help fi - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v4 with: name: sentry-${{ matrix.target }} path: packages/cli/dist/sentry-*/bin/sentry* @@ -56,9 +50,9 @@ jobs: name: Build npm Package runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - - uses: actions/setup-node@v6 + - uses: actions/setup-node@v4 with: node-version: '22' - run: bun install @@ -75,7 +69,7 @@ jobs: working-directory: packages/cli run: npm pack - name: Upload artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v4 with: name: npm-package path: packages/cli/*.tgz @@ -85,11 +79,11 @@ jobs: needs: [build-binary, build-npm] runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v7 + - uses: actions/download-artifact@v4 - name: List artifacts run: find . -type f - name: Upload combined artifacts - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v4 with: name: ${{ github.sha }} path: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 586592b9..e0793dcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ name: CI on: + push: + branches: [main, release/**] + paths: + - 'packages/cli/**' + - '.github/workflows/ci.yml' + - '.github/workflows/build.yml' pull_request: paths: - 'packages/cli/**' @@ -19,7 +25,7 @@ jobs: run: working-directory: packages/cli steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bun run lint @@ -32,7 +38,7 @@ jobs: run: working-directory: packages/cli steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - name: Test @@ -44,5 +50,6 @@ jobs: build: name: Build + needs: [lint, test] uses: ./.github/workflows/build.yml secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f059647..84c8fb0b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,10 +6,17 @@ on: paths: - 'packages/cli/**' - '.github/workflows/test.yml' - workflow_dispatch: + pull_request: + branches: [main] + paths: + - 'packages/cli/**' + - '.github/workflows/test.yml' + workflow_dispatch: # Manual trigger permissions: contents: read + actions: read + pull-requests: write jobs: test: @@ -20,9 +27,13 @@ jobs: working-directory: packages/cli steps: - - uses: actions/checkout@v6 + - name: Checkout + uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest - name: Install dependencies run: bun install @@ -32,10 +43,11 @@ jobs: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} - run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov + run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov - name: Upload Coverage - uses: codecov/codecov-action@v5 + uses: getsentry/codecov-action@main with: - token: ${{ secrets.CODECOV_TOKEN }} - files: packages/cli/coverage/lcov.info + token: ${{ secrets.GITHUB_TOKEN }} + post-pr-comment: true + From 6548c7a5a6cf3d56bf5e02f127dd64eaddbe4c30 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:09:35 +0000 Subject: [PATCH 04/23] chore: remove debug step from build workflow --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a61443d..d5036484 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,8 +80,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 - - name: List artifacts - run: find . -type f - name: Upload combined artifacts uses: actions/upload-artifact@v4 with: From 80e3b5f9a20b2827f9e3ad9cf9acbf4142e8b453 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:11:10 +0000 Subject: [PATCH 05/23] refactor: consolidate build into CI workflow with caching - Merge build.yml into ci.yml for simplicity - Add Bun dependency caching via setup-bun cache option - Use --frozen-lockfile for reproducible installs - Update release.yml to use ci.yml workflow - Delete standalone build.yml --- .github/workflows/build.yml | 89 ---------------------------- .github/workflows/ci.yml | 106 +++++++++++++++++++++++++++++++--- .github/workflows/release.yml | 6 +- 3 files changed, 101 insertions(+), 100 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index d5036484..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Build - -on: - workflow_call: - -jobs: - build-binary: - name: Build Binary (${{ matrix.target }}) - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - target: darwin-arm64 - os: macos-latest - - target: darwin-x64 - os: macos-13 - - target: linux-arm64 - os: ubuntu-24.04-arm - - target: linux-x64 - os: ubuntu-latest - - target: windows-x64 - os: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - - run: bun install - working-directory: packages/cli - - name: Build - working-directory: packages/cli - env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} - run: bun run build - - name: Smoke test - working-directory: packages/cli - shell: bash - run: | - if [[ "${{ matrix.target }}" == "windows-x64" ]]; then - ./dist/sentry-windows-x64/bin/sentry.exe --help - else - ./dist/sentry-${{ matrix.target }}/bin/sentry --help - fi - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: sentry-${{ matrix.target }} - path: packages/cli/dist/sentry-*/bin/sentry* - - build-npm: - name: Build npm Package - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - - uses: actions/setup-node@v4 - with: - node-version: '22' - - run: bun install - working-directory: packages/cli - - name: Bundle - working-directory: packages/cli - env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} - run: bun run bundle - - name: Smoke test (Node.js) - working-directory: packages/cli - run: node dist/bin.mjs --help - - name: Pack - working-directory: packages/cli - run: npm pack - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: npm-package - path: packages/cli/*.tgz - - merge-artifacts: - name: Merge Artifacts - needs: [build-binary, build-npm] - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v4 - - name: Upload combined artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ github.sha }} - path: | - sentry-*/ - npm-package/*.tgz diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0793dcb..a288bc42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,12 +6,11 @@ on: paths: - 'packages/cli/**' - '.github/workflows/ci.yml' - - '.github/workflows/build.yml' pull_request: paths: - 'packages/cli/**' - '.github/workflows/ci.yml' - - '.github/workflows/build.yml' + workflow_call: concurrency: group: ci-${{ github.ref }} @@ -27,7 +26,10 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - - run: bun install + with: + cache: true + cache-dependency-path: packages/cli/bun.lock + - run: bun install --frozen-lockfile - run: bun run lint - run: bun run typecheck @@ -40,7 +42,10 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - - run: bun install + with: + cache: true + cache-dependency-path: packages/cli/bun.lock + - run: bun install --frozen-lockfile - name: Test env: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} @@ -48,8 +53,93 @@ jobs: SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} run: bun test - build: - name: Build + build-binary: + name: Build Binary (${{ matrix.target }}) needs: [lint, test] - uses: ./.github/workflows/build.yml - secrets: inherit + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - target: darwin-arm64 + os: macos-latest + - target: darwin-x64 + os: macos-13 + - target: linux-arm64 + os: ubuntu-24.04-arm + - target: linux-x64 + os: ubuntu-latest + - target: windows-x64 + os: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + cache: true + cache-dependency-path: packages/cli/bun.lock + - run: bun install --frozen-lockfile + working-directory: packages/cli + - name: Build + working-directory: packages/cli + env: + SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + run: bun run build + - name: Smoke test + working-directory: packages/cli + shell: bash + run: | + if [[ "${{ matrix.target }}" == "windows-x64" ]]; then + ./dist/sentry-windows-x64/bin/sentry.exe --help + else + ./dist/sentry-${{ matrix.target }}/bin/sentry --help + fi + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: sentry-${{ matrix.target }} + path: packages/cli/dist/sentry-*/bin/sentry* + + build-npm: + name: Build npm Package + needs: [lint, test] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + cache: true + cache-dependency-path: packages/cli/bun.lock + - uses: actions/setup-node@v4 + with: + node-version: '22' + - run: bun install --frozen-lockfile + working-directory: packages/cli + - name: Bundle + working-directory: packages/cli + env: + SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + run: bun run bundle + - name: Smoke test (Node.js) + working-directory: packages/cli + run: node dist/bin.mjs --help + - name: Pack + working-directory: packages/cli + run: npm pack + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: npm-package + path: packages/cli/*.tgz + + merge-artifacts: + name: Merge Artifacts + needs: [build-binary, build-npm] + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + - uses: actions/upload-artifact@v4 + with: + name: ${{ github.sha }} + path: | + sentry-*/ + npm-package/*.tgz diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aba6a5fc..3c772e80 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,14 +11,14 @@ on: required: false jobs: - build: - uses: ./.github/workflows/build.yml + ci: + uses: ./.github/workflows/ci.yml permissions: contents: read secrets: inherit release: - needs: [build] + needs: [ci] uses: getsentry/craft/.github/workflows/release.yml@v2 with: version: ${{ inputs.version }} From a7fdec8d6bd9709f0ade41baff12cdd65ec7c751 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:14:22 +0000 Subject: [PATCH 06/23] fix: require SENTRY_CLIENT_ID for build The CLI is useless without OAuth, so fail the build if SENTRY_CLIENT_ID environment variable is not set. --- packages/cli/script/build.ts | 8 +++++--- packages/cli/script/bundle.ts | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/cli/script/build.ts b/packages/cli/script/build.ts index 6ded3b82..253e56ca 100644 --- a/packages/cli/script/build.ts +++ b/packages/cli/script/build.ts @@ -101,10 +101,12 @@ async function build(): Promise { console.log("=".repeat(40)); if (!SENTRY_CLIENT_ID) { - console.warn( - "\nWarning: SENTRY_CLIENT_ID not set. OAuth will not work in the built binary." + console.error( + "\nError: SENTRY_CLIENT_ID environment variable is required." ); - console.warn(" Set it via: SENTRY_CLIENT_ID=xxx bun run build\n"); + console.error(" The CLI requires OAuth to function."); + console.error(" Set it via: SENTRY_CLIENT_ID=xxx bun run build\n"); + process.exit(1); } // Determine targets diff --git a/packages/cli/script/bundle.ts b/packages/cli/script/bundle.ts index 1aaaf848..2686d93a 100644 --- a/packages/cli/script/bundle.ts +++ b/packages/cli/script/bundle.ts @@ -21,10 +21,10 @@ console.log(`\nBundling sentry v${VERSION} for npm`); console.log("=".repeat(40)); if (!SENTRY_CLIENT_ID) { - console.warn( - "\nWarning: SENTRY_CLIENT_ID not set. OAuth will not work in the bundled package." - ); - console.warn(" Set it via: SENTRY_CLIENT_ID=xxx bun run bundle\n"); + console.error("\nError: SENTRY_CLIENT_ID environment variable is required."); + console.error(" The CLI requires OAuth to function."); + console.error(" Set it via: SENTRY_CLIENT_ID=xxx bun run bundle\n"); + process.exit(1); } const result = await build({ From b974b5330c038763752e37d1571d9817d5c23c9e Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:22:10 +0000 Subject: [PATCH 07/23] refactor: flatten repo structure (remove monorepo layout) - Move packages/cli/* to root (src/, test/, script/) - Merge package.json files, remove turbo dependency - Remove turbo.json - Update all workflow files to use root paths - Update biome.jsonc test overrides path - Update documentation (AGENTS.md, README.md, DEVELOPMENT.md) This simplifies the repo since it's not actually a monorepo. --- .github/workflows/ci.yml | 40 ++++++------- .github/workflows/test.yml | 27 ++++----- AGENTS.md | 52 ++++++++-------- DEVELOPMENT.md | 15 +---- README.md | 7 +-- biome.jsonc | 2 +- bun.lock | 59 ++++--------------- packages/cli/bunfig.toml => bunfig.toml | 0 package.json | 53 ++++++++++++----- packages/cli/package.json | 45 -------------- {packages/cli/script => script}/build.ts | 0 {packages/cli/script => script}/bundle.ts | 0 .../cli/script => script}/node-polyfills.ts | 0 {packages/cli/src => src}/app.ts | 0 {packages/cli/src => src}/bin.ts | 0 {packages/cli/src => src}/commands/api.ts | 0 .../cli/src => src}/commands/auth/index.ts | 0 .../cli/src => src}/commands/auth/login.ts | 0 .../cli/src => src}/commands/auth/logout.ts | 0 .../cli/src => src}/commands/auth/status.ts | 0 .../cli/src => src}/commands/event/get.ts | 0 .../cli/src => src}/commands/event/index.ts | 0 .../cli/src => src}/commands/issue/get.ts | 0 .../cli/src => src}/commands/issue/index.ts | 0 .../cli/src => src}/commands/issue/list.ts | 0 {packages/cli/src => src}/commands/org/get.ts | 0 .../cli/src => src}/commands/org/index.ts | 0 .../cli/src => src}/commands/org/list.ts | 0 .../cli/src => src}/commands/project/get.ts | 0 .../cli/src => src}/commands/project/index.ts | 0 .../cli/src => src}/commands/project/list.ts | 0 {packages/cli/src => src}/context.ts | 0 {packages/cli/src => src}/lib/api-client.ts | 0 {packages/cli/src => src}/lib/browser.ts | 0 {packages/cli/src => src}/lib/config.ts | 0 {packages/cli/src => src}/lib/dsn/cache.ts | 0 {packages/cli/src => src}/lib/dsn/detector.ts | 0 {packages/cli/src => src}/lib/dsn/env-file.ts | 0 {packages/cli/src => src}/lib/dsn/env.ts | 0 {packages/cli/src => src}/lib/dsn/errors.ts | 0 {packages/cli/src => src}/lib/dsn/index.ts | 0 .../cli/src => src}/lib/dsn/languages/go.ts | 0 .../src => src}/lib/dsn/languages/index.ts | 0 .../cli/src => src}/lib/dsn/languages/java.ts | 0 .../lib/dsn/languages/javascript.ts | 0 .../cli/src => src}/lib/dsn/languages/php.ts | 0 .../src => src}/lib/dsn/languages/python.ts | 0 .../cli/src => src}/lib/dsn/languages/ruby.ts | 0 .../src => src}/lib/dsn/languages/types.ts | 0 {packages/cli/src => src}/lib/dsn/parser.ts | 0 {packages/cli/src => src}/lib/dsn/resolver.ts | 0 {packages/cli/src => src}/lib/dsn/types.ts | 0 {packages/cli/src => src}/lib/errors.ts | 0 .../cli/src => src}/lib/formatters/colors.ts | 0 .../cli/src => src}/lib/formatters/human.ts | 0 .../cli/src => src}/lib/formatters/index.ts | 0 .../cli/src => src}/lib/formatters/json.ts | 0 .../cli/src => src}/lib/formatters/output.ts | 0 {packages/cli/src => src}/lib/oauth.ts | 2 +- {packages/cli/src => src}/lib/qrcode.ts | 0 .../cli/src => src}/lib/resolve-target.ts | 0 {packages/cli/src => src}/types/config.ts | 0 {packages/cli/src => src}/types/index.ts | 0 {packages/cli/src => src}/types/oauth.ts | 0 {packages/cli/src => src}/types/sentry.ts | 0 .../cli/test => test}/commands/api.test.ts | 0 {packages/cli/test => test}/e2e/api.test.ts | 0 {packages/cli/test => test}/e2e/auth.test.ts | 0 {packages/cli/test => test}/e2e/event.test.ts | 0 {packages/cli/test => test}/e2e/issue.test.ts | 0 .../cli/test => test}/e2e/project.test.ts | 0 {packages/cli/test => test}/fixture.ts | 0 .../cli/test => test}/lib/config.test.ts | 0 {packages/cli/test => test}/lib/dsn.test.ts | 0 .../cli/test => test}/lib/dsn/cache.test.ts | 0 .../test => test}/lib/dsn/detector.test.ts | 0 .../lib/dsn/languages/go.test.ts | 0 .../lib/dsn/languages/java.test.ts | 0 .../lib/dsn/languages/javascript.test.ts | 0 .../lib/dsn/languages/php.test.ts | 0 .../lib/dsn/languages/python.test.ts | 0 .../lib/dsn/languages/ruby.test.ts | 0 {packages/cli/test => test}/preload.ts | 0 packages/cli/tsconfig.json => tsconfig.json | 0 turbo.json | 22 ------- 85 files changed, 110 insertions(+), 214 deletions(-) rename packages/cli/bunfig.toml => bunfig.toml (100%) delete mode 100644 packages/cli/package.json rename {packages/cli/script => script}/build.ts (100%) rename {packages/cli/script => script}/bundle.ts (100%) rename {packages/cli/script => script}/node-polyfills.ts (100%) rename {packages/cli/src => src}/app.ts (100%) rename {packages/cli/src => src}/bin.ts (100%) rename {packages/cli/src => src}/commands/api.ts (100%) rename {packages/cli/src => src}/commands/auth/index.ts (100%) rename {packages/cli/src => src}/commands/auth/login.ts (100%) rename {packages/cli/src => src}/commands/auth/logout.ts (100%) rename {packages/cli/src => src}/commands/auth/status.ts (100%) rename {packages/cli/src => src}/commands/event/get.ts (100%) rename {packages/cli/src => src}/commands/event/index.ts (100%) rename {packages/cli/src => src}/commands/issue/get.ts (100%) rename {packages/cli/src => src}/commands/issue/index.ts (100%) rename {packages/cli/src => src}/commands/issue/list.ts (100%) rename {packages/cli/src => src}/commands/org/get.ts (100%) rename {packages/cli/src => src}/commands/org/index.ts (100%) rename {packages/cli/src => src}/commands/org/list.ts (100%) rename {packages/cli/src => src}/commands/project/get.ts (100%) rename {packages/cli/src => src}/commands/project/index.ts (100%) rename {packages/cli/src => src}/commands/project/list.ts (100%) rename {packages/cli/src => src}/context.ts (100%) rename {packages/cli/src => src}/lib/api-client.ts (100%) rename {packages/cli/src => src}/lib/browser.ts (100%) rename {packages/cli/src => src}/lib/config.ts (100%) rename {packages/cli/src => src}/lib/dsn/cache.ts (100%) rename {packages/cli/src => src}/lib/dsn/detector.ts (100%) rename {packages/cli/src => src}/lib/dsn/env-file.ts (100%) rename {packages/cli/src => src}/lib/dsn/env.ts (100%) rename {packages/cli/src => src}/lib/dsn/errors.ts (100%) rename {packages/cli/src => src}/lib/dsn/index.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/go.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/index.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/java.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/javascript.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/php.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/python.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/ruby.ts (100%) rename {packages/cli/src => src}/lib/dsn/languages/types.ts (100%) rename {packages/cli/src => src}/lib/dsn/parser.ts (100%) rename {packages/cli/src => src}/lib/dsn/resolver.ts (100%) rename {packages/cli/src => src}/lib/dsn/types.ts (100%) rename {packages/cli/src => src}/lib/errors.ts (100%) rename {packages/cli/src => src}/lib/formatters/colors.ts (100%) rename {packages/cli/src => src}/lib/formatters/human.ts (100%) rename {packages/cli/src => src}/lib/formatters/index.ts (100%) rename {packages/cli/src => src}/lib/formatters/json.ts (100%) rename {packages/cli/src => src}/lib/formatters/output.ts (100%) rename {packages/cli/src => src}/lib/oauth.ts (99%) rename {packages/cli/src => src}/lib/qrcode.ts (100%) rename {packages/cli/src => src}/lib/resolve-target.ts (100%) rename {packages/cli/src => src}/types/config.ts (100%) rename {packages/cli/src => src}/types/index.ts (100%) rename {packages/cli/src => src}/types/oauth.ts (100%) rename {packages/cli/src => src}/types/sentry.ts (100%) rename {packages/cli/test => test}/commands/api.test.ts (100%) rename {packages/cli/test => test}/e2e/api.test.ts (100%) rename {packages/cli/test => test}/e2e/auth.test.ts (100%) rename {packages/cli/test => test}/e2e/event.test.ts (100%) rename {packages/cli/test => test}/e2e/issue.test.ts (100%) rename {packages/cli/test => test}/e2e/project.test.ts (100%) rename {packages/cli/test => test}/fixture.ts (100%) rename {packages/cli/test => test}/lib/config.test.ts (100%) rename {packages/cli/test => test}/lib/dsn.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/cache.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/detector.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/go.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/java.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/javascript.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/php.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/python.test.ts (100%) rename {packages/cli/test => test}/lib/dsn/languages/ruby.test.ts (100%) rename {packages/cli/test => test}/preload.ts (100%) rename packages/cli/tsconfig.json => tsconfig.json (100%) delete mode 100644 turbo.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a288bc42..b9042403 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,19 @@ on: push: branches: [main, release/**] paths: - - 'packages/cli/**' + - 'src/**' + - 'test/**' + - 'script/**' + - 'package.json' + - 'bun.lock' - '.github/workflows/ci.yml' pull_request: paths: - - 'packages/cli/**' + - 'src/**' + - 'test/**' + - 'script/**' + - 'package.json' + - 'bun.lock' - '.github/workflows/ci.yml' workflow_call: @@ -20,15 +28,12 @@ jobs: lint: name: Lint & Typecheck runs-on: ubuntu-latest - defaults: - run: - working-directory: packages/cli steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: cache: true - cache-dependency-path: packages/cli/bun.lock + cache-dependency-path: bun.lock - run: bun install --frozen-lockfile - run: bun run lint - run: bun run typecheck @@ -36,15 +41,12 @@ jobs: test: name: Test runs-on: ubuntu-latest - defaults: - run: - working-directory: packages/cli steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: cache: true - cache-dependency-path: packages/cli/bun.lock + cache-dependency-path: bun.lock - run: bun install --frozen-lockfile - name: Test env: @@ -76,16 +78,13 @@ jobs: - uses: oven-sh/setup-bun@v2 with: cache: true - cache-dependency-path: packages/cli/bun.lock + cache-dependency-path: bun.lock - run: bun install --frozen-lockfile - working-directory: packages/cli - name: Build - working-directory: packages/cli env: SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} run: bun run build - name: Smoke test - working-directory: packages/cli shell: bash run: | if [[ "${{ matrix.target }}" == "windows-x64" ]]; then @@ -97,7 +96,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: sentry-${{ matrix.target }} - path: packages/cli/dist/sentry-*/bin/sentry* + path: dist/sentry-*/bin/sentry* build-npm: name: Build npm Package @@ -108,28 +107,23 @@ jobs: - uses: oven-sh/setup-bun@v2 with: cache: true - cache-dependency-path: packages/cli/bun.lock + cache-dependency-path: bun.lock - uses: actions/setup-node@v4 with: node-version: '22' - run: bun install --frozen-lockfile - working-directory: packages/cli - name: Bundle - working-directory: packages/cli env: SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} run: bun run bundle - name: Smoke test (Node.js) - working-directory: packages/cli run: node dist/bin.mjs --help - - name: Pack - working-directory: packages/cli - run: npm pack + - run: npm pack - name: Upload artifact uses: actions/upload-artifact@v4 with: name: npm-package - path: packages/cli/*.tgz + path: '*.tgz' merge-artifacts: name: Merge Artifacts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84c8fb0b..2704216a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,14 +4,20 @@ on: push: branches: [main] paths: - - 'packages/cli/**' + - 'src/**' + - 'test/**' + - 'package.json' + - 'bun.lock' - '.github/workflows/test.yml' pull_request: branches: [main] paths: - - 'packages/cli/**' + - 'src/**' + - 'test/**' + - 'package.json' + - 'bun.lock' - '.github/workflows/test.yml' - workflow_dispatch: # Manual trigger + workflow_dispatch: permissions: contents: read @@ -22,32 +28,25 @@ jobs: test: name: Run Tests runs-on: ubuntu-latest - defaults: - run: - working-directory: packages/cli steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Setup Bun - uses: oven-sh/setup-bun@v2 + - uses: oven-sh/setup-bun@v2 with: bun-version: latest - - name: Install dependencies - run: bun install + - run: bun install - name: Test env: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} - run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov + run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov - name: Upload Coverage uses: getsentry/codecov-action@main with: token: ${{ secrets.GITHUB_TOKEN }} post-pr-comment: true - diff --git a/AGENTS.md b/AGENTS.md index b27fdc33..ec73573f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,25 +11,23 @@ Before working on this codebase, read the Cursor rules: ## Quick Reference: Commands -> **Note**: Always check `package.json` and `packages/cli/package.json` for the latest scripts. +> **Note**: Always check `package.json` for the latest scripts. ```bash # Development bun install # Install dependencies -bun run dev # Run CLI in dev mode (from packages/cli) -bun run --env-file=../../.env.local src/bin.ts # Dev with env vars +bun run dev # Run CLI in dev mode +bun run --env-file=.env.local src/bin.ts # Dev with env vars # Build bun run build # Build for current platform bun run build:all # Build for all platforms -turbo build # Build all packages # Type Checking -turbo typecheck # Check all packages -bun run typecheck # Check single package (from packages/cli) +bun run typecheck # Check types # Linting & Formatting -bun run lint # Check for issues (via turbo) +bun run lint # Check for issues bun run lint:fix # Auto-fix issues (run before committing) # Testing @@ -70,20 +68,18 @@ mkdirSync(dir, { recursive: true, mode: 0o700 }); ## Architecture ``` -stellar-orchid/ -├── packages/ -│ └── cli/ # Main CLI package -│ ├── src/ -│ │ ├── bin.ts # Entry point -│ │ ├── app.ts # Stricli application setup -│ │ ├── context.ts # Dependency injection context -│ │ ├── commands/ # CLI commands (auth/, issue/, org/, project/) -│ │ ├── lib/ # Shared utilities (api-client, config, oauth) -│ │ └── types/ # TypeScript types and Zod schemas -│ └── script/ # Build scripts -├── .cursor/rules/ # Cursor AI rules (read these!) -├── biome.jsonc # Linting config (extends ultracite) -└── turbo.json # Turborepo config +sentry-cli/ +├── src/ +│ ├── bin.ts # Entry point +│ ├── app.ts # Stricli application setup +│ ├── context.ts # Dependency injection context +│ ├── commands/ # CLI commands (auth/, issue/, org/, project/) +│ ├── lib/ # Shared utilities (api-client, config, oauth) +│ └── types/ # TypeScript types and Zod schemas +├── test/ # Test files (mirrors src/ structure) +├── script/ # Build scripts +├── .cursor/rules/ # Cursor AI rules (read these!) +└── biome.jsonc # Linting config (extends ultracite) ``` ## Key Patterns @@ -232,7 +228,7 @@ Minimal comments, maximum clarity. Comments explain **intent and reasoning**, no ## Testing (bun:test) -**Test files go in `packages/cli/test/`**, not alongside source files. +**Test files go in `test/`**, not alongside source files. - Name test files: `*.test.ts` - Mirror source structure: `test/lib/config.test.ts` tests `src/lib/config.ts` - E2E tests go in `test/e2e/` @@ -256,9 +252,9 @@ mock.module("./some-module", () => ({ | What | Where | |------|-------| -| Add new command | `packages/cli/src/commands//` | -| Add API types | `packages/cli/src/types/sentry.ts` | -| Add config types | `packages/cli/src/types/config.ts` | -| Add utility | `packages/cli/src/lib/` | -| Build scripts | `packages/cli/script/` | -| Add tests | `packages/cli/test/` (mirror `src/` structure) | +| Add new command | `src/commands//` | +| Add API types | `src/types/sentry.ts` | +| Add config types | `src/types/config.ts` | +| Add utility | `src/lib/` | +| Build scripts | `script/` | +| Add tests | `test/` (mirror `src/` structure) | diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index d029729a..cf532e2f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -5,14 +5,6 @@ - [Bun](https://bun.sh/) installed - A Sentry OAuth application (create one at https://sentry.io/settings/account/api/applications/) -## Project Structure - -``` -sentry-cli-next/ -└── packages/ - └── cli/ # The Sentry CLI -``` - ## Setup 1. Install dependencies: @@ -34,8 +26,7 @@ Get the client ID from your Sentry OAuth application settings. ## Running Locally ```bash -cd packages/cli -bun run --env-file=../../.env.local src/bin.ts auth login +bun run --env-file=.env.local src/bin.ts auth login ``` ## Testing the Device Flow @@ -43,8 +34,7 @@ bun run --env-file=../../.env.local src/bin.ts auth login 1. Run the CLI login command: ```bash -cd packages/cli -bun run --env-file=../../.env.local src/bin.ts auth login +bun run --env-file=.env.local src/bin.ts auth login ``` 2. You'll see output like: @@ -85,7 +75,6 @@ When creating your Sentry OAuth application: ## Building ```bash -cd packages/cli bun run build ``` diff --git a/README.md b/README.md index 49daca64..25eab987 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# sentry-cli-next +# sentry A gh-like CLI for Sentry. @@ -63,9 +63,8 @@ sentry api /organizations/ --include # Show headers ```bash bun install -cd packages/cli -bun run --env-file=../../.env.local src/bin.ts --help # Run CLI in dev mode -bun run build # Build binary +bun run --env-file=.env.local src/bin.ts --help # Run CLI in dev mode +bun run build # Build binary ``` See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed development instructions. diff --git a/biome.jsonc b/biome.jsonc index 8dcab375..d498314e 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -6,7 +6,7 @@ }, "overrides": [ { - "includes": ["packages/cli/test/**/*.ts"], + "includes": ["test/**/*.ts"], "linter": { "rules": { "performance": { diff --git a/bun.lock b/bun.lock index 73d782f3..70f922d0 100644 --- a/bun.lock +++ b/bun.lock @@ -3,21 +3,9 @@ "configVersion": 1, "workspaces": { "": { - "name": "sry", - "devDependencies": { - "@biomejs/biome": "2.3.8", - "turbo": "^2.3.3", - "typescript": "^5", - "ultracite": "6.3.10", - }, - }, - "packages/cli": { "name": "sentry", - "version": "0.2.0", - "bin": { - "sentry": "./dist/bin.mjs", - }, "devDependencies": { + "@biomejs/biome": "2.3.8", "@stricli/auto-complete": "^1.2.4", "@stricli/core": "^1.2.4", "@types/bun": "latest", @@ -29,6 +17,7 @@ "ky": "^1.14.2", "qrcode-terminal": "^0.12.0", "typescript": "^5", + "ultracite": "6.3.10", "zod": "^3.24.0", }, }, @@ -118,15 +107,15 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@stricli/auto-complete": ["@stricli/auto-complete@1.2.4", "", { "dependencies": { "@stricli/core": "^1.2.4" }, "bin": { "auto-complete": "dist/bin/cli.js" } }, "sha512-MxGgeBbFyH+YtzhIjJeOr68NSx0r8mn4+hWRGgWn31YTG9u0Oa2y9oGHPY+PHeoTfvS7vhgllFvOrHcTVpwTrA=="], + "@stricli/auto-complete": ["@stricli/auto-complete@1.2.5", "", { "dependencies": { "@stricli/core": "^1.2.5" }, "bin": { "auto-complete": "dist/bin/cli.js" } }, "sha512-C6G88Hh4lUWBwiqsxbcA4I1ricSQwiLaOziTWW3NmBoX7WGTW7i7RvyooXMpZk1YMLf2olv5Odxmg127ik1DKQ=="], - "@stricli/core": ["@stricli/core@1.2.4", "", {}, "sha512-ujvJDQpC2FINWvlTjkFz+Qzw/vsB8p/LyZEW18idisqIyjXR6yb+sF3WTUPksl+5ZON5r4fHQnCqQWnJxeqSzg=="], + "@stricli/core": ["@stricli/core@1.2.5", "", {}, "sha512-+afyztQW7fwWkqmU2WQZbdc3LjnZThWYdtE0l+hykZ1Rvy7YGxZSvsVCS/wZ/2BNv117pQ9TU1GZZRIcPnB4tw=="], - "@trpc/server": ["@trpc/server@11.7.2", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-AgB26PXY69sckherIhCacKLY49rxE2XP5h38vr/KMZTbLCL1p8IuIoKPjALTcugC2kbyQ7Lbqo2JDVfRSmPmfQ=="], + "@trpc/server": ["@trpc/server@11.8.1", "", { "peerDependencies": { "typescript": ">=5.7.2" } }, "sha512-P4rzZRpEL7zDFgjxK65IdyH0e41FMFfTkQkuq0BA5tKcr7E6v9/v38DEklCpoDN6sPiB1Sigy/PUEzHENhswDA=="], "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], - "@types/node": ["@types/node@20.19.26", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg=="], + "@types/node": ["@types/node@20.19.30", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g=="], "@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="], @@ -136,20 +125,14 @@ "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + "citty": ["citty@0.2.0", "", {}, "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA=="], "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], - "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], - - "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], - "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], - "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], @@ -180,7 +163,7 @@ "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + "nypm": ["nypm@0.6.4", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw=="], "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], @@ -190,8 +173,6 @@ "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], - "qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], @@ -200,29 +181,13 @@ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "sentry": ["sentry@workspace:packages/cli"], - "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "trpc-cli": ["trpc-cli@0.12.1", "", { "dependencies": { "commander": "^14.0.0" }, "peerDependencies": { "@orpc/server": "^1.0.0", "@trpc/server": "^10.45.2 || ^11.0.1", "@valibot/to-json-schema": "^1.1.0", "effect": "^3.14.2 || ^4.0.0", "valibot": "^1.1.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@orpc/server", "@trpc/server", "@valibot/to-json-schema", "effect", "valibot", "zod"], "bin": { "trpc-cli": "dist/bin.js" } }, "sha512-/D/mIQf3tUrS7ZKJZ1gmSPJn2psAABJfkC5Eevm55SZ4s6KwANOUNlwhAGXN9HT4VSJVfoF2jettevE9vHPQlg=="], - - "turbo": ["turbo@2.6.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.3", "turbo-darwin-arm64": "2.6.3", "turbo-linux-64": "2.6.3", "turbo-linux-arm64": "2.6.3", "turbo-windows-64": "2.6.3", "turbo-windows-arm64": "2.6.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA=="], - - "turbo-darwin-64": ["turbo-darwin-64@2.6.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-BlJJDc1CQ7SK5Y5qnl7AzpkvKSnpkfPmnA+HeU/sgny3oHZckPV2776ebO2M33CYDSor7+8HQwaodY++IINhYg=="], - - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.6.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MwVt7rBKiOK7zdYerenfCRTypefw4kZCue35IJga9CH1+S50+KTiCkT6LBqo0hHeoH2iKuI0ldTF2a0aB72z3w=="], - - "turbo-linux-64": ["turbo-linux-64@2.6.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cqpcw+dXxbnPtNnzeeSyWprjmuFVpHJqKcs7Jym5oXlu/ZcovEASUIUZVN3OGEM6Y/OTyyw0z09tOHNt5yBAVg=="], - - "turbo-linux-arm64": ["turbo-linux-arm64@2.6.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-MterpZQmjXyr4uM7zOgFSFL3oRdNKeflY7nsjxJb2TklsYqiu3Z9pQ4zRVFFH8n0mLGna7MbQMZuKoWqqHb45w=="], - - "turbo-windows-64": ["turbo-windows-64@2.6.3", "", { "os": "win32", "cpu": "x64" }, "sha512-biDU70v9dLwnBdLf+daoDlNJVvqOOP8YEjqNipBHzgclbQlXbsi6Gqqelp5er81Qo3BiRgmTNx79oaZQTPb07Q=="], - - "turbo-windows-arm64": ["turbo-windows-arm64@2.6.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-dDHVKpSeukah3VsI/xMEKeTnV9V9cjlpFSUs4bmsUiLu3Yv2ENlgVEZv65wxbeE0bh0jjpmElDT+P1KaCxArQQ=="], + "trpc-cli": ["trpc-cli@0.12.2", "", { "dependencies": { "commander": "^14.0.0" }, "peerDependencies": { "@orpc/server": "^1.0.0", "@trpc/server": "^10.45.2 || ^11.0.1", "@valibot/to-json-schema": "^1.1.0", "effect": "^3.14.2 || ^4.0.0", "valibot": "^1.1.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@orpc/server", "@trpc/server", "@valibot/to-json-schema", "effect", "valibot", "zod"], "bin": { "trpc-cli": "dist/bin.js" } }, "sha512-kGNCiyOimGlfcZFImbWzFF2Nn3TMnenwUdyuckiN5SEaceJbIac7+Iau3WsVHjQpoNgugFruZMDOKf8GNQNtJw=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], @@ -232,10 +197,6 @@ "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "bun-types/@types/node": ["@types/node@25.0.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew=="], - - "ultracite/zod": ["zod@4.1.13", "", {}, "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig=="], - - "bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "ultracite/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], } } diff --git a/packages/cli/bunfig.toml b/bunfig.toml similarity index 100% rename from packages/cli/bunfig.toml rename to bunfig.toml diff --git a/package.json b/package.json index 9be4e343..45482e64 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,48 @@ { - "name": "sentry-cli-monorepo", + "name": "sentry", "version": "0.2.0", - "private": true, - "packageManager": "bun@1.3.3", - "description": "A gh-like CLI for Sentry", - "workspaces": [ - "packages/*" + "description": "Sentry CLI - A command-line interface for Sentry", + "type": "module", + "bin": { + "sentry": "./dist/bin.mjs" + }, + "files": [ + "dist/bin.mjs" ], "scripts": { - "dev": "turbo dev", - "build": "turbo build", - "lint": "turbo lint", - "lint:fix": "turbo lint:fix", - "typecheck": "turbo typecheck" + "dev": "bun run src/bin.ts", + "build": "bun run script/build.ts --single", + "build:all": "bun run script/build.ts", + "bundle": "bun run script/bundle.ts", + "typecheck": "tsc --noEmit", + "lint": "bunx ultracite check", + "lint:fix": "bunx ultracite fix", + "test": "bun test", + "test:e2e": "bun test test/e2e" }, "devDependencies": { "@biomejs/biome": "2.3.8", - "turbo": "^2.3.3", + "@stricli/auto-complete": "^1.2.4", + "@stricli/core": "^1.2.4", + "@types/bun": "latest", + "@types/node": "^20", + "@types/qrcode-terminal": "^0.12.2", + "chalk": "^5.6.2", + "esbuild": "^0.25.0", + "fast-glob": "^3.3.3", + "ky": "^1.14.2", + "qrcode-terminal": "^0.12.0", "typescript": "^5", - "ultracite": "6.3.10" - } + "ultracite": "6.3.10", + "zod": "^3.24.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/getsentry/cli.git" + }, + "license": "FSL-1.1-Apache-2.0", + "engines": { + "node": ">=18" + }, + "packageManager": "bun@1.3.3" } diff --git a/packages/cli/package.json b/packages/cli/package.json deleted file mode 100644 index dde92df8..00000000 --- a/packages/cli/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "sentry", - "version": "0.2.0", - "description": "Sentry CLI - A command-line interface for Sentry", - "type": "module", - "bin": { - "sentry": "./dist/bin.mjs" - }, - "files": [ - "dist/bin.mjs" - ], - "scripts": { - "dev": "bun run src/bin.ts", - "build": "bun run script/build.ts --single", - "build:all": "bun run script/build.ts", - "bundle": "bun run script/bundle.ts", - "typecheck": "tsc --noEmit", - "lint": "bunx ultracite check", - "lint:fix": "bunx ultracite fix", - "test": "bun test", - "test:e2e": "bun test test/e2e" - }, - "devDependencies": { - "@stricli/auto-complete": "^1.2.4", - "@stricli/core": "^1.2.4", - "@types/bun": "latest", - "@types/node": "^20", - "@types/qrcode-terminal": "^0.12.2", - "chalk": "^5.6.2", - "esbuild": "^0.25.0", - "fast-glob": "^3.3.3", - "ky": "^1.14.2", - "qrcode-terminal": "^0.12.0", - "typescript": "^5", - "zod": "^3.24.0" - }, - "repository": { - "type": "git", - "url": "https://github.com/getsentry/cli.git" - }, - "license": "FSL-1.1-Apache-2.0", - "engines": { - "node": ">=18" - } -} diff --git a/packages/cli/script/build.ts b/script/build.ts similarity index 100% rename from packages/cli/script/build.ts rename to script/build.ts diff --git a/packages/cli/script/bundle.ts b/script/bundle.ts similarity index 100% rename from packages/cli/script/bundle.ts rename to script/bundle.ts diff --git a/packages/cli/script/node-polyfills.ts b/script/node-polyfills.ts similarity index 100% rename from packages/cli/script/node-polyfills.ts rename to script/node-polyfills.ts diff --git a/packages/cli/src/app.ts b/src/app.ts similarity index 100% rename from packages/cli/src/app.ts rename to src/app.ts diff --git a/packages/cli/src/bin.ts b/src/bin.ts similarity index 100% rename from packages/cli/src/bin.ts rename to src/bin.ts diff --git a/packages/cli/src/commands/api.ts b/src/commands/api.ts similarity index 100% rename from packages/cli/src/commands/api.ts rename to src/commands/api.ts diff --git a/packages/cli/src/commands/auth/index.ts b/src/commands/auth/index.ts similarity index 100% rename from packages/cli/src/commands/auth/index.ts rename to src/commands/auth/index.ts diff --git a/packages/cli/src/commands/auth/login.ts b/src/commands/auth/login.ts similarity index 100% rename from packages/cli/src/commands/auth/login.ts rename to src/commands/auth/login.ts diff --git a/packages/cli/src/commands/auth/logout.ts b/src/commands/auth/logout.ts similarity index 100% rename from packages/cli/src/commands/auth/logout.ts rename to src/commands/auth/logout.ts diff --git a/packages/cli/src/commands/auth/status.ts b/src/commands/auth/status.ts similarity index 100% rename from packages/cli/src/commands/auth/status.ts rename to src/commands/auth/status.ts diff --git a/packages/cli/src/commands/event/get.ts b/src/commands/event/get.ts similarity index 100% rename from packages/cli/src/commands/event/get.ts rename to src/commands/event/get.ts diff --git a/packages/cli/src/commands/event/index.ts b/src/commands/event/index.ts similarity index 100% rename from packages/cli/src/commands/event/index.ts rename to src/commands/event/index.ts diff --git a/packages/cli/src/commands/issue/get.ts b/src/commands/issue/get.ts similarity index 100% rename from packages/cli/src/commands/issue/get.ts rename to src/commands/issue/get.ts diff --git a/packages/cli/src/commands/issue/index.ts b/src/commands/issue/index.ts similarity index 100% rename from packages/cli/src/commands/issue/index.ts rename to src/commands/issue/index.ts diff --git a/packages/cli/src/commands/issue/list.ts b/src/commands/issue/list.ts similarity index 100% rename from packages/cli/src/commands/issue/list.ts rename to src/commands/issue/list.ts diff --git a/packages/cli/src/commands/org/get.ts b/src/commands/org/get.ts similarity index 100% rename from packages/cli/src/commands/org/get.ts rename to src/commands/org/get.ts diff --git a/packages/cli/src/commands/org/index.ts b/src/commands/org/index.ts similarity index 100% rename from packages/cli/src/commands/org/index.ts rename to src/commands/org/index.ts diff --git a/packages/cli/src/commands/org/list.ts b/src/commands/org/list.ts similarity index 100% rename from packages/cli/src/commands/org/list.ts rename to src/commands/org/list.ts diff --git a/packages/cli/src/commands/project/get.ts b/src/commands/project/get.ts similarity index 100% rename from packages/cli/src/commands/project/get.ts rename to src/commands/project/get.ts diff --git a/packages/cli/src/commands/project/index.ts b/src/commands/project/index.ts similarity index 100% rename from packages/cli/src/commands/project/index.ts rename to src/commands/project/index.ts diff --git a/packages/cli/src/commands/project/list.ts b/src/commands/project/list.ts similarity index 100% rename from packages/cli/src/commands/project/list.ts rename to src/commands/project/list.ts diff --git a/packages/cli/src/context.ts b/src/context.ts similarity index 100% rename from packages/cli/src/context.ts rename to src/context.ts diff --git a/packages/cli/src/lib/api-client.ts b/src/lib/api-client.ts similarity index 100% rename from packages/cli/src/lib/api-client.ts rename to src/lib/api-client.ts diff --git a/packages/cli/src/lib/browser.ts b/src/lib/browser.ts similarity index 100% rename from packages/cli/src/lib/browser.ts rename to src/lib/browser.ts diff --git a/packages/cli/src/lib/config.ts b/src/lib/config.ts similarity index 100% rename from packages/cli/src/lib/config.ts rename to src/lib/config.ts diff --git a/packages/cli/src/lib/dsn/cache.ts b/src/lib/dsn/cache.ts similarity index 100% rename from packages/cli/src/lib/dsn/cache.ts rename to src/lib/dsn/cache.ts diff --git a/packages/cli/src/lib/dsn/detector.ts b/src/lib/dsn/detector.ts similarity index 100% rename from packages/cli/src/lib/dsn/detector.ts rename to src/lib/dsn/detector.ts diff --git a/packages/cli/src/lib/dsn/env-file.ts b/src/lib/dsn/env-file.ts similarity index 100% rename from packages/cli/src/lib/dsn/env-file.ts rename to src/lib/dsn/env-file.ts diff --git a/packages/cli/src/lib/dsn/env.ts b/src/lib/dsn/env.ts similarity index 100% rename from packages/cli/src/lib/dsn/env.ts rename to src/lib/dsn/env.ts diff --git a/packages/cli/src/lib/dsn/errors.ts b/src/lib/dsn/errors.ts similarity index 100% rename from packages/cli/src/lib/dsn/errors.ts rename to src/lib/dsn/errors.ts diff --git a/packages/cli/src/lib/dsn/index.ts b/src/lib/dsn/index.ts similarity index 100% rename from packages/cli/src/lib/dsn/index.ts rename to src/lib/dsn/index.ts diff --git a/packages/cli/src/lib/dsn/languages/go.ts b/src/lib/dsn/languages/go.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/go.ts rename to src/lib/dsn/languages/go.ts diff --git a/packages/cli/src/lib/dsn/languages/index.ts b/src/lib/dsn/languages/index.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/index.ts rename to src/lib/dsn/languages/index.ts diff --git a/packages/cli/src/lib/dsn/languages/java.ts b/src/lib/dsn/languages/java.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/java.ts rename to src/lib/dsn/languages/java.ts diff --git a/packages/cli/src/lib/dsn/languages/javascript.ts b/src/lib/dsn/languages/javascript.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/javascript.ts rename to src/lib/dsn/languages/javascript.ts diff --git a/packages/cli/src/lib/dsn/languages/php.ts b/src/lib/dsn/languages/php.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/php.ts rename to src/lib/dsn/languages/php.ts diff --git a/packages/cli/src/lib/dsn/languages/python.ts b/src/lib/dsn/languages/python.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/python.ts rename to src/lib/dsn/languages/python.ts diff --git a/packages/cli/src/lib/dsn/languages/ruby.ts b/src/lib/dsn/languages/ruby.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/ruby.ts rename to src/lib/dsn/languages/ruby.ts diff --git a/packages/cli/src/lib/dsn/languages/types.ts b/src/lib/dsn/languages/types.ts similarity index 100% rename from packages/cli/src/lib/dsn/languages/types.ts rename to src/lib/dsn/languages/types.ts diff --git a/packages/cli/src/lib/dsn/parser.ts b/src/lib/dsn/parser.ts similarity index 100% rename from packages/cli/src/lib/dsn/parser.ts rename to src/lib/dsn/parser.ts diff --git a/packages/cli/src/lib/dsn/resolver.ts b/src/lib/dsn/resolver.ts similarity index 100% rename from packages/cli/src/lib/dsn/resolver.ts rename to src/lib/dsn/resolver.ts diff --git a/packages/cli/src/lib/dsn/types.ts b/src/lib/dsn/types.ts similarity index 100% rename from packages/cli/src/lib/dsn/types.ts rename to src/lib/dsn/types.ts diff --git a/packages/cli/src/lib/errors.ts b/src/lib/errors.ts similarity index 100% rename from packages/cli/src/lib/errors.ts rename to src/lib/errors.ts diff --git a/packages/cli/src/lib/formatters/colors.ts b/src/lib/formatters/colors.ts similarity index 100% rename from packages/cli/src/lib/formatters/colors.ts rename to src/lib/formatters/colors.ts diff --git a/packages/cli/src/lib/formatters/human.ts b/src/lib/formatters/human.ts similarity index 100% rename from packages/cli/src/lib/formatters/human.ts rename to src/lib/formatters/human.ts diff --git a/packages/cli/src/lib/formatters/index.ts b/src/lib/formatters/index.ts similarity index 100% rename from packages/cli/src/lib/formatters/index.ts rename to src/lib/formatters/index.ts diff --git a/packages/cli/src/lib/formatters/json.ts b/src/lib/formatters/json.ts similarity index 100% rename from packages/cli/src/lib/formatters/json.ts rename to src/lib/formatters/json.ts diff --git a/packages/cli/src/lib/formatters/output.ts b/src/lib/formatters/output.ts similarity index 100% rename from packages/cli/src/lib/formatters/output.ts rename to src/lib/formatters/output.ts diff --git a/packages/cli/src/lib/oauth.ts b/src/lib/oauth.ts similarity index 99% rename from packages/cli/src/lib/oauth.ts rename to src/lib/oauth.ts index 9645cc6f..d969b5b1 100644 --- a/packages/cli/src/lib/oauth.ts +++ b/src/lib/oauth.ts @@ -27,7 +27,7 @@ const SENTRY_URL = process.env.SENTRY_URL ?? "https://sentry.io"; * Build-time: Injected via Bun.build({ define: { SENTRY_CLIENT_ID: "..." } }) * Runtime: Can be overridden via SENTRY_CLIENT_ID env var (for self-hosted) * - * @see packages/cli/script/build.ts + * @see script/build.ts */ declare const SENTRY_CLIENT_ID_BUILD: string | undefined; const SENTRY_CLIENT_ID = diff --git a/packages/cli/src/lib/qrcode.ts b/src/lib/qrcode.ts similarity index 100% rename from packages/cli/src/lib/qrcode.ts rename to src/lib/qrcode.ts diff --git a/packages/cli/src/lib/resolve-target.ts b/src/lib/resolve-target.ts similarity index 100% rename from packages/cli/src/lib/resolve-target.ts rename to src/lib/resolve-target.ts diff --git a/packages/cli/src/types/config.ts b/src/types/config.ts similarity index 100% rename from packages/cli/src/types/config.ts rename to src/types/config.ts diff --git a/packages/cli/src/types/index.ts b/src/types/index.ts similarity index 100% rename from packages/cli/src/types/index.ts rename to src/types/index.ts diff --git a/packages/cli/src/types/oauth.ts b/src/types/oauth.ts similarity index 100% rename from packages/cli/src/types/oauth.ts rename to src/types/oauth.ts diff --git a/packages/cli/src/types/sentry.ts b/src/types/sentry.ts similarity index 100% rename from packages/cli/src/types/sentry.ts rename to src/types/sentry.ts diff --git a/packages/cli/test/commands/api.test.ts b/test/commands/api.test.ts similarity index 100% rename from packages/cli/test/commands/api.test.ts rename to test/commands/api.test.ts diff --git a/packages/cli/test/e2e/api.test.ts b/test/e2e/api.test.ts similarity index 100% rename from packages/cli/test/e2e/api.test.ts rename to test/e2e/api.test.ts diff --git a/packages/cli/test/e2e/auth.test.ts b/test/e2e/auth.test.ts similarity index 100% rename from packages/cli/test/e2e/auth.test.ts rename to test/e2e/auth.test.ts diff --git a/packages/cli/test/e2e/event.test.ts b/test/e2e/event.test.ts similarity index 100% rename from packages/cli/test/e2e/event.test.ts rename to test/e2e/event.test.ts diff --git a/packages/cli/test/e2e/issue.test.ts b/test/e2e/issue.test.ts similarity index 100% rename from packages/cli/test/e2e/issue.test.ts rename to test/e2e/issue.test.ts diff --git a/packages/cli/test/e2e/project.test.ts b/test/e2e/project.test.ts similarity index 100% rename from packages/cli/test/e2e/project.test.ts rename to test/e2e/project.test.ts diff --git a/packages/cli/test/fixture.ts b/test/fixture.ts similarity index 100% rename from packages/cli/test/fixture.ts rename to test/fixture.ts diff --git a/packages/cli/test/lib/config.test.ts b/test/lib/config.test.ts similarity index 100% rename from packages/cli/test/lib/config.test.ts rename to test/lib/config.test.ts diff --git a/packages/cli/test/lib/dsn.test.ts b/test/lib/dsn.test.ts similarity index 100% rename from packages/cli/test/lib/dsn.test.ts rename to test/lib/dsn.test.ts diff --git a/packages/cli/test/lib/dsn/cache.test.ts b/test/lib/dsn/cache.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/cache.test.ts rename to test/lib/dsn/cache.test.ts diff --git a/packages/cli/test/lib/dsn/detector.test.ts b/test/lib/dsn/detector.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/detector.test.ts rename to test/lib/dsn/detector.test.ts diff --git a/packages/cli/test/lib/dsn/languages/go.test.ts b/test/lib/dsn/languages/go.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/go.test.ts rename to test/lib/dsn/languages/go.test.ts diff --git a/packages/cli/test/lib/dsn/languages/java.test.ts b/test/lib/dsn/languages/java.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/java.test.ts rename to test/lib/dsn/languages/java.test.ts diff --git a/packages/cli/test/lib/dsn/languages/javascript.test.ts b/test/lib/dsn/languages/javascript.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/javascript.test.ts rename to test/lib/dsn/languages/javascript.test.ts diff --git a/packages/cli/test/lib/dsn/languages/php.test.ts b/test/lib/dsn/languages/php.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/php.test.ts rename to test/lib/dsn/languages/php.test.ts diff --git a/packages/cli/test/lib/dsn/languages/python.test.ts b/test/lib/dsn/languages/python.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/python.test.ts rename to test/lib/dsn/languages/python.test.ts diff --git a/packages/cli/test/lib/dsn/languages/ruby.test.ts b/test/lib/dsn/languages/ruby.test.ts similarity index 100% rename from packages/cli/test/lib/dsn/languages/ruby.test.ts rename to test/lib/dsn/languages/ruby.test.ts diff --git a/packages/cli/test/preload.ts b/test/preload.ts similarity index 100% rename from packages/cli/test/preload.ts rename to test/preload.ts diff --git a/packages/cli/tsconfig.json b/tsconfig.json similarity index 100% rename from packages/cli/tsconfig.json rename to tsconfig.json diff --git a/turbo.json b/turbo.json deleted file mode 100644 index 40d21258..00000000 --- a/turbo.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "tasks": { - "build": { - "dependsOn": ["^build"], - "outputs": ["dist/**", "dist-bin/**"] - }, - "dev": { - "cache": false, - "persistent": true - }, - "lint": { - "dependsOn": ["^lint"] - }, - "lint:fix": { - "cache": false - }, - "typecheck": { - "dependsOn": ["^typecheck"] - } - } -} From dc89d487376e4e2e9afa5cf26370639024740ee8 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:24:03 +0000 Subject: [PATCH 08/23] perf: cache node_modules to skip install on cache hit --- .github/workflows/ci.yml | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9042403..69288b99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,10 +31,13 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 + - uses: actions/cache@v4 + id: cache with: - cache: true - cache-dependency-path: bun.lock - - run: bun install --frozen-lockfile + path: node_modules + key: node-modules-${{ hashFiles('bun.lock') }} + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile - run: bun run lint - run: bun run typecheck @@ -44,10 +47,13 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 + - uses: actions/cache@v4 + id: cache with: - cache: true - cache-dependency-path: bun.lock - - run: bun install --frozen-lockfile + path: node_modules + key: node-modules-${{ hashFiles('bun.lock') }} + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile - name: Test env: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} @@ -76,10 +82,13 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 + - uses: actions/cache@v4 + id: cache with: - cache: true - cache-dependency-path: bun.lock - - run: bun install --frozen-lockfile + path: node_modules + key: node-modules-${{ matrix.os }}-${{ hashFiles('bun.lock') }} + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile - name: Build env: SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} @@ -105,13 +114,16 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - with: - cache: true - cache-dependency-path: bun.lock - uses: actions/setup-node@v4 with: node-version: '22' - - run: bun install --frozen-lockfile + - uses: actions/cache@v4 + id: cache + with: + path: node_modules + key: node-modules-${{ hashFiles('bun.lock') }} + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile - name: Bundle env: SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} From e9daa944327e8778ea586570110ab2a69284b37e Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:25:39 +0000 Subject: [PATCH 09/23] chore: target Node.js 22+ --- package.json | 2 +- script/bundle.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 45482e64..cb1bdb46 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ }, "license": "FSL-1.1-Apache-2.0", "engines": { - "node": ">=18" + "node": ">=22" }, "packageManager": "bun@1.3.3" } diff --git a/script/bundle.ts b/script/bundle.ts index 2686d93a..fa1f30f5 100644 --- a/script/bundle.ts +++ b/script/bundle.ts @@ -32,7 +32,7 @@ const result = await build({ bundle: true, minify: true, platform: "node", - target: "node18", + target: "node22", format: "esm", outfile: "./dist/bin.mjs", inject: ["./script/node-polyfills.ts"], From 12805aab72d515db36bceffad6d51eedbafd7b48 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 19:30:41 +0000 Subject: [PATCH 10/23] Apply suggestion from @BYK --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cb1bdb46..70cbf875 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sentry", "version": "0.2.0", - "description": "Sentry CLI - A command-line interface for Sentry", + "description": "Sentry CLI - A command-line interface for using Sentry built by robots and humans for robots and humans", "type": "module", "bin": { "sentry": "./dist/bin.mjs" From 2dc3bffe7f4a16a20fe50546dd09bf8eea33ecd2 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:06:59 +0000 Subject: [PATCH 11/23] test: increase timeouts for E2E tests that call Sentry API These tests can be slow due to network latency. Increase timeout from default 5s to 15s to prevent flaky test failures. --- test/e2e/project.test.ts | 214 +++++++++++++++++++++++---------------- 1 file changed, 125 insertions(+), 89 deletions(-) diff --git a/test/e2e/project.test.ts b/test/e2e/project.test.ts index ca736190..9133ff62 100644 --- a/test/e2e/project.test.ts +++ b/test/e2e/project.test.ts @@ -56,30 +56,38 @@ describe("sentry org list", () => { expect(result.stderr + result.stdout).toMatch(/not authenticated|login/i); }); - test("lists organizations with valid auth", async () => { - await setAuthToken(TEST_TOKEN); + test( + "lists organizations with valid auth", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli(["org", "list"], { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - }); + const result = await runCli(["org", "list"], { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + }); - expect(result.exitCode).toBe(0); - // Should contain header and at least one org - expect(result.stdout).toContain("SLUG"); - }); + expect(result.exitCode).toBe(0); + // Should contain header and at least one org + expect(result.stdout).toContain("SLUG"); + }, + { timeout: 15_000 } + ); - test("supports --json output", async () => { - await setAuthToken(TEST_TOKEN); + test( + "supports --json output", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli(["org", "list", "--json"], { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - }); + const result = await runCli(["org", "list", "--json"], { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + }); - expect(result.exitCode).toBe(0); - const data = JSON.parse(result.stdout); - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBeGreaterThan(0); - }); + expect(result.exitCode).toBe(0); + const data = JSON.parse(result.stdout); + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBeGreaterThan(0); + }, + { timeout: 15_000 } + ); }); describe("sentry project list", () => { @@ -92,35 +100,43 @@ describe("sentry project list", () => { expect(result.stderr + result.stdout).toMatch(/not authenticated|login/i); }); - test("lists projects with valid auth and org filter", async () => { - await setAuthToken(TEST_TOKEN); + test( + "lists projects with valid auth and org filter", + async () => { + await setAuthToken(TEST_TOKEN); - // Use --org flag to filter by organization - const result = await runCli( - ["project", "list", "--org", TEST_ORG, "--limit", "5"], - { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - } - ); + // Use --org flag to filter by organization + const result = await runCli( + ["project", "list", "--org", TEST_ORG, "--limit", "5"], + { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + } + ); - expect(result.exitCode).toBe(0); - }); + expect(result.exitCode).toBe(0); + }, + { timeout: 15_000 } + ); - test("supports --json output", async () => { - await setAuthToken(TEST_TOKEN); + test( + "supports --json output", + async () => { + await setAuthToken(TEST_TOKEN); - // Use --org flag to filter by organization - const result = await runCli( - ["project", "list", "--org", TEST_ORG, "--json", "--limit", "5"], - { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - } - ); + // Use --org flag to filter by organization + const result = await runCli( + ["project", "list", "--org", TEST_ORG, "--json", "--limit", "5"], + { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + } + ); - expect(result.exitCode).toBe(0); - const data = JSON.parse(result.stdout); - expect(Array.isArray(data)).toBe(true); - }); + expect(result.exitCode).toBe(0); + const data = JSON.parse(result.stdout); + expect(Array.isArray(data)).toBe(true); + }, + { timeout: 15_000 } + ); }); describe("sentry org get", () => { @@ -133,40 +149,52 @@ describe("sentry org get", () => { expect(result.stderr + result.stdout).toMatch(/not authenticated|login/i); }); - test("gets organization details", async () => { - await setAuthToken(TEST_TOKEN); + test( + "gets organization details", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli(["org", "get", TEST_ORG], { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - }); + const result = await runCli(["org", "get", TEST_ORG], { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + }); - expect(result.exitCode).toBe(0); - expect(result.stdout).toContain(TEST_ORG); - expect(result.stdout).toContain("Slug:"); - }); + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain(TEST_ORG); + expect(result.stdout).toContain("Slug:"); + }, + { timeout: 15_000 } + ); - test("supports --json output", async () => { - await setAuthToken(TEST_TOKEN); + test( + "supports --json output", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli(["org", "get", TEST_ORG, "--json"], { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - }); + const result = await runCli(["org", "get", TEST_ORG, "--json"], { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + }); - expect(result.exitCode).toBe(0); - const data = JSON.parse(result.stdout); - expect(data.slug).toBe(TEST_ORG); - }); + expect(result.exitCode).toBe(0); + const data = JSON.parse(result.stdout); + expect(data.slug).toBe(TEST_ORG); + }, + { timeout: 15_000 } + ); - test("handles non-existent org", async () => { - await setAuthToken(TEST_TOKEN); + test( + "handles non-existent org", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli(["org", "get", "nonexistent-org-12345"], { - env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, - }); + const result = await runCli(["org", "get", "nonexistent-org-12345"], { + env: { SENTRY_CLI_CONFIG_DIR: testConfigDir }, + }); - expect(result.exitCode).toBe(1); - expect(result.stderr + result.stdout).toMatch(/not found|error|404/i); - }); + expect(result.exitCode).toBe(1); + expect(result.stderr + result.stdout).toMatch(/not found|error|404/i); + }, + { timeout: 15_000 } + ); }); describe("sentry project get", () => { @@ -204,31 +232,39 @@ describe("sentry project get", () => { ); }); - test("gets project details", async () => { - await setAuthToken(TEST_TOKEN); + test( + "gets project details", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli( - ["project", "get", TEST_PROJECT, "--org", TEST_ORG], - { env: { SENTRY_CLI_CONFIG_DIR: testConfigDir } } - ); + const result = await runCli( + ["project", "get", TEST_PROJECT, "--org", TEST_ORG], + { env: { SENTRY_CLI_CONFIG_DIR: testConfigDir } } + ); - expect(result.exitCode).toBe(0); - expect(result.stdout).toContain(TEST_PROJECT); - expect(result.stdout).toContain("Slug:"); - }); + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain(TEST_PROJECT); + expect(result.stdout).toContain("Slug:"); + }, + { timeout: 15_000 } + ); - test("supports --json output", async () => { - await setAuthToken(TEST_TOKEN); + test( + "supports --json output", + async () => { + await setAuthToken(TEST_TOKEN); - const result = await runCli( - ["project", "get", TEST_PROJECT, "--org", TEST_ORG, "--json"], - { env: { SENTRY_CLI_CONFIG_DIR: testConfigDir } } - ); + const result = await runCli( + ["project", "get", TEST_PROJECT, "--org", TEST_ORG, "--json"], + { env: { SENTRY_CLI_CONFIG_DIR: testConfigDir } } + ); - expect(result.exitCode).toBe(0); - const data = JSON.parse(result.stdout); - expect(data.slug).toBe(TEST_PROJECT); - }); + expect(result.exitCode).toBe(0); + const data = JSON.parse(result.stdout); + expect(data.slug).toBe(TEST_PROJECT); + }, + { timeout: 15_000 } + ); test( "handles non-existent project", From f7ccade5fac0d0d36bc864471061518c00fae292 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:19:20 +0000 Subject: [PATCH 12/23] fix(ci): use cross-compilation for unavailable runners - darwin-x64: build on macos-latest (ARM) with cross-compilation - linux-arm64: build on ubuntu-latest (x64) with cross-compilation macOS-13 runners are retired, and ARM runners aren't available for private repos. Bun supports cross-compilation natively. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69288b99..2f3f2f21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,9 +72,9 @@ jobs: - target: darwin-arm64 os: macos-latest - target: darwin-x64 - os: macos-13 + os: macos-latest - target: linux-arm64 - os: ubuntu-24.04-arm + os: ubuntu-latest - target: linux-x64 os: ubuntu-latest - target: windows-x64 From 4847932ce61d5fa239cbc99737b32619b02b7efb Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:21:48 +0000 Subject: [PATCH 13/23] fix(ci): use vars.SENTRY_CLIENT_ID instead of secrets --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f3f2f21..d0cf2152 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,7 +91,7 @@ jobs: run: bun install --frozen-lockfile - name: Build env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} run: bun run build - name: Smoke test shell: bash @@ -126,7 +126,7 @@ jobs: run: bun install --frozen-lockfile - name: Bundle env: - SENTRY_CLIENT_ID: ${{ secrets.SENTRY_CLIENT_ID }} + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} run: bun run bundle - name: Smoke test (Node.js) run: node dist/bin.mjs --help From 0cc6024e2e2898cb52fea48fb5b156facdec8d28 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:25:32 +0000 Subject: [PATCH 14/23] fix(ci): support cross-compilation via --target flag - Add --target flag to build.ts for explicit target specification - Update CI to use --target instead of --single for matrix builds - Enables cross-compilation (e.g., build darwin-x64 on darwin-arm64) --- .github/workflows/ci.yml | 2 +- script/build.ts | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0cf2152..7b9b2a41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: - name: Build env: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} - run: bun run build + run: bun run build --target ${{ matrix.target }} - name: Smoke test shell: bash run: | diff --git a/script/build.ts b/script/build.ts index 253e56ca..2a430afc 100644 --- a/script/build.ts +++ b/script/build.ts @@ -6,8 +6,9 @@ * Binaries are uploaded to GitHub Releases. * * Usage: - * bun run script/build.ts # Build for all platforms - * bun run script/build.ts --single # Build for current platform only + * bun run script/build.ts # Build for all platforms + * bun run script/build.ts --single # Build for current platform only + * bun run script/build.ts --target darwin-x64 # Build for specific target (cross-compile) * * Output structure: * dist/ @@ -92,10 +93,25 @@ async function buildTarget(target: BuildTarget): Promise { return true; } +/** Parse target string (e.g., "darwin-x64" or "linux-arm64") into BuildTarget */ +function parseTarget(targetStr: string): BuildTarget | null { + // Handle "windows" alias for "win32" + const normalized = targetStr.replace("windows-", "win32-"); + const [os, arch] = normalized.split("-") as [ + BuildTarget["os"], + BuildTarget["arch"], + ]; + + const target = ALL_TARGETS.find((t) => t.os === os && t.arch === arch); + return target ?? null; +} + /** Main build function */ async function build(): Promise { const args = process.argv.slice(2); const singleBuild = args.includes("--single"); + const targetIndex = args.indexOf("--target"); + const targetArg = targetIndex !== -1 ? args[targetIndex + 1] : null; console.log(`\nSentry CLI Build v${VERSION}`); console.log("=".repeat(40)); @@ -112,7 +128,19 @@ async function build(): Promise { // Determine targets let targets: BuildTarget[]; - if (singleBuild) { + if (targetArg) { + // Explicit target specified (for cross-compilation) + const target = parseTarget(targetArg); + if (!target) { + console.error(`Invalid target: ${targetArg}`); + console.error( + `Valid targets: ${ALL_TARGETS.map((t) => `${t.os === "win32" ? "windows" : t.os}-${t.arch}`).join(", ")}` + ); + process.exit(1); + } + targets = [target]; + console.log(`\nBuilding for target: ${getPackageName(target)}`); + } else if (singleBuild) { const currentTarget = ALL_TARGETS.find( (t) => t.os === process.platform && t.arch === process.arch ); From 82cc7602cb697a7c236ab0631f1669c431b2c0c7 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:28:49 +0000 Subject: [PATCH 15/23] fix(ci): skip smoke test for cross-compiled binaries Cross-compiled binaries (darwin-x64 on arm64, linux-arm64 on x64) cannot be executed on the build runner. Add can-test matrix flag to skip smoke tests for these targets. --- .github/workflows/ci.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b9b2a41..10f9c91b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,16 +69,23 @@ jobs: fail-fast: false matrix: include: + # Native builds (can run smoke test) - target: darwin-arm64 os: macos-latest - - target: darwin-x64 - os: macos-latest - - target: linux-arm64 - os: ubuntu-latest + can-test: true - target: linux-x64 os: ubuntu-latest + can-test: true - target: windows-x64 os: windows-latest + can-test: true + # Cross-compiled builds (cannot run smoke test) + - target: darwin-x64 + os: macos-latest + can-test: false + - target: linux-arm64 + os: ubuntu-latest + can-test: false steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 @@ -94,6 +101,7 @@ jobs: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} run: bun run build --target ${{ matrix.target }} - name: Smoke test + if: matrix.can-test shell: bash run: | if [[ "${{ matrix.target }}" == "windows-x64" ]]; then From 6f9677878c248a6f1f7d6f5d3afd6de26659f4bf Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:40:10 +0000 Subject: [PATCH 16/23] refactor(ci): consolidate test workflows Remove separate test.yml and merge coverage reporting into ci.yml. Single test job now handles both CI gating and coverage uploads. --- .github/workflows/ci.yml | 11 +++++++- .github/workflows/test.yml | 52 -------------------------------------- 2 files changed, 10 insertions(+), 53 deletions(-) delete mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10f9c91b..1a756226 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,10 @@ jobs: test: name: Test runs-on: ubuntu-latest + permissions: + contents: read + actions: read + pull-requests: write steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 @@ -59,7 +63,12 @@ jobs: SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} - run: bun test + run: bun test --coverage --coverage-reporter=lcov + - name: Upload Coverage + uses: getsentry/codecov-action@main + with: + token: ${{ secrets.GITHUB_TOKEN }} + post-pr-comment: true build-binary: name: Build Binary (${{ matrix.target }}) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 2704216a..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Test - -on: - push: - branches: [main] - paths: - - 'src/**' - - 'test/**' - - 'package.json' - - 'bun.lock' - - '.github/workflows/test.yml' - pull_request: - branches: [main] - paths: - - 'src/**' - - 'test/**' - - 'package.json' - - 'bun.lock' - - '.github/workflows/test.yml' - workflow_dispatch: - -permissions: - contents: read - actions: read - pull-requests: write - -jobs: - test: - name: Run Tests - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - run: bun install - - - name: Test - env: - SENTRY_TEST_AUTH_TOKEN: ${{ secrets.SENTRY_TEST_AUTH_TOKEN }} - SENTRY_TEST_ORG: ${{ secrets.SENTRY_TEST_ORG }} - SENTRY_TEST_PROJECT: ${{ secrets.SENTRY_TEST_PROJECT }} - run: bun test --reporter=junit --reporter-outfile=./report.junit.xml --coverage --coverage-reporter=lcov - - - name: Upload Coverage - uses: getsentry/codecov-action@main - with: - token: ${{ secrets.GITHUB_TOKEN }} - post-pr-comment: true From fad134f333846d8de8f2f89c85616257dbdada1a Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:41:18 +0000 Subject: [PATCH 17/23] fix(craft): remove invalid cwd references to packages/cli The monorepo was flattened - package.json is now at root. --- .craft.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.craft.yml b/.craft.yml index c5c4db74..281f422b 100644 --- a/.craft.yml +++ b/.craft.yml @@ -1,17 +1,12 @@ minVersion: '2.14.0' changelog: policy: auto -preReleaseCommand: >- - node -p " - const {execSync} = require('child_process'); - execSync('npm --no-git-tag-version version ' + process.env.CRAFT_NEW_VERSION, {cwd: 'packages/cli'}).toString(); - " +preReleaseCommand: npm --no-git-tag-version version ${CRAFT_NEW_VERSION} postReleaseCommand: >- - node -p " - const {execSync} = require('child_process'); - execSync('npm --no-git-tag-version version preminor --preid=dev', {cwd: 'packages/cli'}); - execSync('git diff --quiet || git commit -anm \"meta: Bump new development version\\n\\n#skip-changelog\" && git pull --rebase && git push').toString(); - " + npm --no-git-tag-version version preminor --preid=dev && + git diff --quiet || (git commit -anm "meta: Bump new development version + + #skip-changelog" && git pull --rebase && git push) requireNames: - /^sentry-.+$/ - /^sentry-.*\.tgz$/ From 0388a5a4045490f1fc1fe87b1c8174a2c1997e5b Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:42:22 +0000 Subject: [PATCH 18/23] fix(test): correct .env.local path after monorepo flatten --- test/preload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/preload.ts b/test/preload.ts index 52ae099e..81648726 100644 --- a/test/preload.ts +++ b/test/preload.ts @@ -11,7 +11,7 @@ import { join, resolve } from "node:path"; // Load .env.local for test credentials (SENTRY_TEST_*) // This mimics what would happen in CI where secrets are injected as env vars -const envLocalPath = resolve(import.meta.dir, "../../../.env.local"); +const envLocalPath = resolve(import.meta.dir, "../.env.local"); if (existsSync(envLocalPath)) { const content = readFileSync(envLocalPath, "utf-8"); for (const line of content.split("\n")) { From 5679e7a57376b1986a131374db6c9839f952deab Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:45:46 +0000 Subject: [PATCH 19/23] fix(bundle): replace fast-glob with tinyglobby for ESM compatibility fast-glob uses CommonJS dynamic require() which fails in ESM bundles. tinyglobby is a pure ESM alternative that bundles correctly. Also fixes the bundle to inline all npm packages (external: ['node:*']) so the CLI works standalone without dependencies installed. --- bun.lock | 38 ++++---------------------------------- package.json | 2 +- script/bundle.ts | 4 ++-- script/node-polyfills.ts | 11 ++++++----- 4 files changed, 13 insertions(+), 42 deletions(-) diff --git a/bun.lock b/bun.lock index 70f922d0..c861bd74 100644 --- a/bun.lock +++ b/bun.lock @@ -13,9 +13,9 @@ "@types/qrcode-terminal": "^0.12.2", "chalk": "^5.6.2", "esbuild": "^0.25.0", - "fast-glob": "^3.3.3", "ky": "^1.14.2", "qrcode-terminal": "^0.12.0", + "tinyglobby": "^0.2.15", "typescript": "^5", "ultracite": "6.3.10", "zod": "^3.24.0", @@ -101,12 +101,6 @@ "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], - "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], - - "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], - - "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@stricli/auto-complete": ["@stricli/auto-complete@1.2.5", "", { "dependencies": { "@stricli/core": "^1.2.5" }, "bin": { "auto-complete": "dist/bin/cli.js" } }, "sha512-C6G88Hh4lUWBwiqsxbcA4I1ricSQwiLaOziTWW3NmBoX7WGTW7i7RvyooXMpZk1YMLf2olv5Odxmg127ik1DKQ=="], "@stricli/core": ["@stricli/core@1.2.5", "", {}, "sha512-+afyztQW7fwWkqmU2WQZbdc3LjnZThWYdtE0l+hykZ1Rvy7YGxZSvsVCS/wZ/2BNv117pQ9TU1GZZRIcPnB4tw=="], @@ -119,8 +113,6 @@ "@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="], - "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], @@ -133,32 +125,16 @@ "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], - "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - - "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], - - "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], "ky": ["ky@1.14.2", "", {}, "sha512-q3RBbsO5A5zrPhB6CaCS8ZUv+NWCXv6JJT4Em0i264G9W0fdPB8YRfnnEi7Dm7X7omAkBIPojzYJ2D1oHTHqug=="], "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - - "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], - "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], @@ -171,21 +147,15 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="], - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], - - "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], - "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "trpc-cli": ["trpc-cli@0.12.2", "", { "dependencies": { "commander": "^14.0.0" }, "peerDependencies": { "@orpc/server": "^1.0.0", "@trpc/server": "^10.45.2 || ^11.0.1", "@valibot/to-json-schema": "^1.1.0", "effect": "^3.14.2 || ^4.0.0", "valibot": "^1.1.0", "zod": "^3.24.0 || ^4.0.0" }, "optionalPeers": ["@orpc/server", "@trpc/server", "@valibot/to-json-schema", "effect", "valibot", "zod"], "bin": { "trpc-cli": "dist/bin.js" } }, "sha512-kGNCiyOimGlfcZFImbWzFF2Nn3TMnenwUdyuckiN5SEaceJbIac7+Iau3WsVHjQpoNgugFruZMDOKf8GNQNtJw=="], diff --git a/package.json b/package.json index 70cbf875..d73c3708 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "@types/qrcode-terminal": "^0.12.2", "chalk": "^5.6.2", "esbuild": "^0.25.0", - "fast-glob": "^3.3.3", "ky": "^1.14.2", "qrcode-terminal": "^0.12.0", + "tinyglobby": "^0.2.15", "typescript": "^5", "ultracite": "6.3.10", "zod": "^3.24.0" diff --git a/script/bundle.ts b/script/bundle.ts index fa1f30f5..329efe5b 100644 --- a/script/bundle.ts +++ b/script/bundle.ts @@ -40,8 +40,8 @@ const result = await build({ SENTRY_CLI_VERSION: JSON.stringify(VERSION), SENTRY_CLIENT_ID_BUILD: JSON.stringify(SENTRY_CLIENT_ID), }, - // Keep Node.js built-ins external - they're available in the runtime - packages: "external", + // Only externalize Node.js built-ins - bundle all npm packages + external: ["node:*"], metafile: true, }); diff --git a/script/node-polyfills.ts b/script/node-polyfills.ts index 63dc8c43..427d5818 100644 --- a/script/node-polyfills.ts +++ b/script/node-polyfills.ts @@ -8,8 +8,6 @@ import { execSync, spawn as nodeSpawn } from "node:child_process"; import { access, readFile, writeFile } from "node:fs/promises"; -import fg from "fast-glob"; - declare global { var Bun: typeof BunPolyfill; } @@ -75,10 +73,13 @@ const BunPolyfill = { constructor(pattern: string) { this.pattern = pattern; } - scan(opts?: { cwd?: string }): AsyncIterable { - return fg.stream(this.pattern, { + async *scan(opts?: { cwd?: string }): AsyncIterable { + const results = await glob(this.pattern, { cwd: opts?.cwd || process.cwd(), - }) as AsyncIterable; + }); + for (const result of results) { + yield result; + } } }, }; From 296c455ff8d771ce31c116cb856edab059c7fe54 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 20:48:40 +0000 Subject: [PATCH 20/23] fix: add missing tinyglobby import --- script/node-polyfills.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/node-polyfills.ts b/script/node-polyfills.ts index 427d5818..a0b0f2ed 100644 --- a/script/node-polyfills.ts +++ b/script/node-polyfills.ts @@ -8,6 +8,8 @@ import { execSync, spawn as nodeSpawn } from "node:child_process"; import { access, readFile, writeFile } from "node:fs/promises"; +import { glob } from "tinyglobby"; + declare global { var Bun: typeof BunPolyfill; } From ee01df300e6308d1682e8862807ff2ebf7433c25 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 21:15:10 +0000 Subject: [PATCH 21/23] fix(polyfill): correct Bun.spawn type signature and stdio mapping --- script/node-polyfills.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/script/node-polyfills.ts b/script/node-polyfills.ts index a0b0f2ed..b014f8dc 100644 --- a/script/node-polyfills.ts +++ b/script/node-polyfills.ts @@ -53,11 +53,21 @@ const BunPolyfill = { } }, - spawn(cmd: string[], opts?: { stdio?: string[] }) { + spawn( + cmd: string[], + opts?: { stdout?: "pipe" | "ignore"; stderr?: "pipe" | "ignore" } + ) { const [command, ...args] = cmd; + // Map Bun's stdout/stderr options to Node's stdio array format + // Currently only supports "ignore" - "pipe" would require returning streams + const stdio: ("pipe" | "ignore")[] = [ + "ignore", // stdin + opts?.stdout ?? "ignore", + opts?.stderr ?? "ignore", + ]; const proc = nodeSpawn(command, args, { detached: true, - stdio: (opts?.stdio as "ignore") || "ignore", + stdio, }); return { unref() { From a36742338c8cebba83dab895f002967f9d33977e Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 21:17:05 +0000 Subject: [PATCH 22/23] fix(test): use delete to clear env vars instead of undefined Assigning undefined to process.env converts it to string 'undefined' rather than removing the variable. --- test/preload.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/preload.ts b/test/preload.ts index 81648726..b820cb70 100644 --- a/test/preload.ts +++ b/test/preload.ts @@ -52,10 +52,10 @@ process.env.SENTRY_CLI_CONFIG_DIR = testDir; // Clear Sentry environment variables to ensure clean state // (but preserve SENTRY_TEST_* vars for E2E tests) -process.env.SENTRY_DSN = undefined; -process.env.SENTRY_AUTH_TOKEN = undefined; -process.env.SENTRY_CLIENT_ID = undefined; -process.env.SENTRY_URL = undefined; +delete process.env.SENTRY_DSN; +delete process.env.SENTRY_AUTH_TOKEN; +delete process.env.SENTRY_CLIENT_ID; +delete process.env.SENTRY_URL; // Cleanup after all tests process.on("exit", () => { From 714cdc2f8a465168d1322b5de211971abf6ea37f Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Wed, 21 Jan 2026 21:27:54 +0000 Subject: [PATCH 23/23] fix(test): use delete for all env var cleanup Setting process.env.X = undefined creates string 'undefined', not unset. --- test/e2e/event.test.ts | 2 +- test/lib/dsn/detector.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/event.test.ts b/test/e2e/event.test.ts index 8b5b5d6b..df159122 100644 --- a/test/e2e/event.test.ts +++ b/test/e2e/event.test.ts @@ -42,7 +42,7 @@ afterEach(() => { if (originalConfigDir) { process.env.SENTRY_CLI_CONFIG_DIR = originalConfigDir; } else { - process.env.SENTRY_CLI_CONFIG_DIR = undefined; + delete process.env.SENTRY_CLI_CONFIG_DIR; } }); diff --git a/test/lib/dsn/detector.test.ts b/test/lib/dsn/detector.test.ts index 0be67d8d..ed8809ea 100644 --- a/test/lib/dsn/detector.test.ts +++ b/test/lib/dsn/detector.test.ts @@ -46,11 +46,11 @@ describe("DSN Detector (New Module)", () => { // Clear any cached DSN for the test directory await clearDsnCache(testDir); // Clear SENTRY_DSN env var - process.env.SENTRY_DSN = undefined; + delete process.env.SENTRY_DSN; }); afterEach(() => { - process.env.SENTRY_DSN = undefined; + delete process.env.SENTRY_DSN; cleanupDir(testDir); cleanupDir(TEST_CONFIG_DIR); });