diff --git a/.agents/skills/fix-security-vulnerability/SKILL.md b/.agents/skills/fix-security-vulnerability/SKILL.md index d8ff8008..931203da 100644 --- a/.agents/skills/fix-security-vulnerability/SKILL.md +++ b/.agents/skills/fix-security-vulnerability/SKILL.md @@ -56,14 +56,14 @@ make # installs yarn deps AND runs 'pre-commit install' pre-commit install ``` -The pre-commit config (`.pre-commit-config.yaml`) runs formatters, linters, and a `set-docker-tag-from-branch` hook that rewrites `action.yml` so the Docker tag matches the current branch name. **This is not optional.** CI's `prepare-docker` job rejects any PR whose `action.yml` Docker tag still matches a semver like `3.6.0`. The pre-commit hook is what keeps the tag in sync on feature branches; CI does **not** install or run pre-commit itself. +The pre-commit config (`.pre-commit-config.yaml`) runs formatters and linters. CI does **not** install or run pre-commit itself. ### Hook-modified files: re-stage, re-commit (never `--amend`) -On the first `git commit`, the `set-docker-tag-from-branch` hook will usually modify `action.yml`. The commit fails, and the hook's changes are left unstaged. Recover by: +If a hook modifies files, the commit fails and the hook's changes are left unstaged. Recover by: ```bash -git add action.yml +git add git commit -m "" # a NEW commit; do not use --amend ``` @@ -123,10 +123,9 @@ Co-Authored-By: EOF )" -# 4. If the 'set-docker-tag-from-branch' hook rewrote action.yml (it usually -# does on the first commit of a branch), the commit above fails. Re-stage -# and re-commit — DO NOT use --amend. -git add action.yml +# 4. If a pre-commit hook modified files, the commit above fails. Re-stage +# and re-commit. DO NOT use --amend. +git add git commit -m "" ``` diff --git a/.agents/skills/verify-dist/SKILL.md b/.agents/skills/verify-dist/SKILL.md index e26d8708..8bed1b81 100644 --- a/.agents/skills/verify-dist/SKILL.md +++ b/.agents/skills/verify-dist/SKILL.md @@ -61,15 +61,13 @@ Regenerates dist/index.js. Whoever runs the follow-up commit needs the repo's pre-commit hooks installed. Verify with `ls .git/hooks/pre-commit`; if missing, run `make` (installs yarn deps + `pre-commit install`) or `pre-commit install`. -The `set-docker-tag-from-branch` hook will rewrite `action.yml` on the first commit of a branch and fail the commit. Recover by staging `action.yml` and committing again (**never `--amend`** — the hook-failed commit never landed): +If a hook modifies files, the commit fails. Recover by staging the modified files and committing again (**never `--amend`**, because the hook-failed commit never landed): ```bash -git add action.yml +git add git commit -m "" ``` -CI does **not** run pre-commit. CI's `prepare-docker` job rejects PRs where `action.yml`'s Docker tag still matches a semver like `3.6.0`, so keeping the tag in sync via the local hook is what prevents the CI failure. - ## Notes - The CI check runs `git diff --ignore-space-at-eol dist/` — whitespace-only diffs pass, anything else fails. Match that locally. diff --git a/.github/actions/use-local-image/action.yml b/.github/actions/use-local-image/action.yml new file mode 100644 index 00000000..0836bb7f --- /dev/null +++ b/.github/actions/use-local-image/action.yml @@ -0,0 +1,57 @@ +name: 'Use local action image' +description: |- + Loads the action image built in this workflow run into a local registry + and points the checked-out action.yml to it. The e2e tests use this, so + they can run before any image goes to ghcr.io (and on fork PRs, which get + a read-only token). + +inputs: + path: + description: Directory of the checked-out action that the tests run. + default: '.' + required: false + +runs: + using: 'composite' + steps: + - name: Download image + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: action-release-image-${{ runner.arch == 'ARM64' && 'arm64' || 'amd64' }} + # Relative path, because `runner.temp` is a host path in container jobs. + path: .action-release-image + + # Container jobs have the host docker socket mounted but usually no docker CLI. + - name: Install docker CLI + shell: bash + run: | + if command -v docker &> /dev/null; then + exit 0 + fi + curl -fsSL "https://download.docker.com/linux/static/stable/$(uname -m)/docker-29.9.1.tgz" \ + | tar -xz -C /usr/local/bin --strip-components=1 docker/docker + + # The runner always pulls `docker://` images, so a local copy is not enough. + # The daemon trusts registries on localhost without TLS. + - name: Push image to local registry + shell: bash + run: | + docker run -d --rm -p 5000:5000 --name action-release-registry \ + registry:3.1.2@sha256:d4032d4cc323c1731c707931ecada07a53076eac38e3b61ae57533f170f2c6c3 + docker load -i .action-release-image/image.tar + rm -rf .action-release-image + # Retry until the registry is ready. A curl check does not work in + # container jobs, because there localhost is the job container. + for i in $(seq 1 10); do + docker push localhost:5000/action-release-image:pr && exit 0 + sleep 2 + done + exit 1 + + - name: Point action.yml to local image + shell: bash + working-directory: ${{ inputs.path }} + run: | + sed -i -e 's|docker://ghcr.io/getsentry/action-release-image:.*|docker://localhost:5000/action-release-image:pr|' action.yml + # Make sure the replacement worked + grep -q 'docker://localhost:5000/action-release-image:pr' action.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 70ee8de3..05e08273 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,18 +11,10 @@ on: paths-ignore: - '**.md' -env: - # Variables defined in the repository - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - # For master, we have an environment variable that selects the action-release project - # instead of action-release-prs - # For other branches: https://sentry-ecosystem.sentry.io/releases/?project=4505075304693760 - # For master branch: https://sentry-ecosystem.sentry.io/releases/?project=6576594 - SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} - jobs: prepare-docker: name: Prepare docker tag + if: github.event_name == 'push' runs-on: ubuntu-latest permissions: contents: write @@ -41,14 +33,6 @@ jobs: else TAG=$(yq '... | select(has("uses") and .uses | test("docker://ghcr.io/getsentry/action-release-image:.*")) | .uses' action.yml | awk -F':' '{print $3}') echo "docker_tag=$TAG" >> $GITHUB_OUTPUT - - if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then - if [[ "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: docker_tag $TAG matching format MAJOR.MINOR.PATCH is not allowed inside pull requests." - echo "Please rename the docker tag in action.yml and try again." - exit 1 - fi - fi fi - name: Get auth token @@ -66,12 +50,14 @@ jobs: github-token: ${{ steps.token.outputs.token }} message: 'chore: Set docker tag for master [skip ci]' - docker-build-platform: - name: Build & publish Docker images - needs: prepare-docker + # Builds the images without a push, so this job needs no write access. PRs + # (including fork PRs) and pushes use the same build. The e2e tests load the + # app image into a local registry, see `use-local-image`. + docker-build: + name: Build Docker images runs-on: ${{ matrix.platform.runner }} permissions: - packages: write + contents: read strategy: matrix: target: @@ -83,26 +69,17 @@ jobs: platform: - name: linux/amd64 arch: amd64 - runner: ubuntu-latest + runner: ubuntu-26.04 - name: linux/arm64 arch: arm64 - runner: ubuntu-24.04-arm + runner: ubuntu-26.04-arm steps: - name: Checkout repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - # BUILDKIT_INLINE_CACHE creates the image in such a way that you can # then use --cache-from (think of a remote cache) # This feature is allowed thanks to using the buildx plugin @@ -110,19 +87,37 @@ jobs: # There's a COPY command in the builder stage that can easily invalidate the cache # If you notice, please add more exceptions to .dockerignore since we loose the value # of using --cache-from on the app stage - - name: Build and push + - name: Build uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 with: platforms: ${{ matrix.platform.name }} - push: true - tags: ghcr.io/${{ github.repository_owner }}/${{ matrix.target.image }}:${{ needs.prepare-docker.outputs.docker_tag }}-${{ matrix.platform.arch }} - cache-from: ghcr.io/${{ github.repository_owner }}/${{ matrix.target.image }}:master + # Local name inside the tar only, also on master and release runs. It is never + # pushed to ghcr.io. `docker-publish` pushes the image under its ghcr.io name. + tags: localhost:5000/${{ matrix.target.image }}:pr + # OCI archive, so it keeps the provenance attestation and `docker-publish` + # can push the exact bytes that the e2e tests used. + outputs: type=oci,dest=${{ runner.temp }}/image.tar + # Inline cache only holds the final stage, so the app build also + # reads the builder image to reuse the builder stage. + cache-from: | + ghcr.io/${{ github.repository_owner }}/action-release-builder-image:master + ghcr.io/${{ github.repository_owner }}/action-release-image:master target: ${{ matrix.target.name }} build-args: BUILDKIT_INLINE_CACHE=1 - docker-build: - name: Merge multi-arch Docker images - needs: [prepare-docker, docker-build-platform] + - name: Upload image + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: ${{ matrix.target.image }}-${{ matrix.platform.arch }} + path: ${{ runner.temp }}/image.tar + retention-days: 1 + + # The only job that can write to ghcr.io. It runs only on push (reviewed code), + # after the e2e tests pass, and publishes the exact images they tested. + docker-publish: + name: Publish Docker images + needs: [prepare-docker, e2e] + if: github.event_name == 'push' runs-on: ubuntu-latest permissions: packages: write @@ -132,6 +127,12 @@ jobs: - action-release-builder-image - action-release-image steps: + - name: Download images + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: ${{ matrix.image }}-* + path: ${{ runner.temp }}/images + - name: Login to GitHub Container Registry uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: @@ -139,6 +140,18 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + # skopeo reads the credentials of `docker login`. `--preserve-digests` fails + # the push if the image would change, so ghcr.io gets the tested bytes. + - name: Push arch images + env: + IMAGE: ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}:${{ needs.prepare-docker.outputs.docker_tag }} + run: | + for ARCH in amd64 arm64; do + skopeo copy --all --preserve-digests \ + "oci-archive:$RUNNER_TEMP/images/${{ matrix.image }}-$ARCH/image.tar" \ + "docker://$IMAGE-$ARCH" + done + - name: Create and verify multi-arch manifest env: IMAGE: ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}:${{ needs.prepare-docker.outputs.docker_tag }} @@ -169,176 +182,11 @@ jobs: - name: Build run: yarn build - ############# - # E2E Tests - ############# - - test-create-staging-release-per-push: - needs: docker-build - strategy: - matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - runs-on: ${{ matrix.os }} - permissions: - contents: read - name: Test current action - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Create a staging release - uses: ./ - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_LOG_LEVEL: debug - with: - ignore_missing: true - - test-runs-on-container: - needs: docker-build - runs-on: ubuntu-latest - permissions: - contents: read - container: - image: node:20.19.2 - - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Create a staging release - uses: ./ - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_LOG_LEVEL: debug - with: - ignore_missing: true - - test-mock-release: - needs: docker-build - strategy: - matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - runs-on: ${{ matrix.os }} - name: Mock a release - permissions: - contents: read - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Mock creating a Sentry release - uses: ./ - env: - MOCK: true - with: - environment: production - - test-mock-release-working-directory: - needs: docker-build - strategy: - matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - runs-on: ${{ matrix.os }} - name: Mock a release in a different working directory - permissions: - contents: read - steps: - - name: Checkout directory we'll be running from - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - path: main/ - - - name: Checkout directory we'll be testing - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - path: test/ - - - name: Mock creating a Sentry release in a different directory - uses: ./main - env: - MOCK: true - with: - environment: production - working_directory: ./test - - test-node-version-preserved: - needs: docker-build - strategy: - matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - node-version: ['20.x', '22.x', '24.x'] - runs-on: ${{ matrix.os }} - name: Test Node version preserved on ${{ matrix.os }} with Node ${{ matrix.node-version }} - permissions: - contents: read - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Print Node Version (Before) - id: node_before - shell: bash - run: | - VERSION=$(node --version) - echo "Node version before: $VERSION" - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Mock creating a Sentry release - uses: ./ - env: - MOCK: true - with: - environment: production - - - name: Print Node Version (After) - shell: bash - run: | - VERSION_AFTER=$(node --version) - echo "Node version after: $VERSION_AFTER" - echo "Expected: ${{ steps.node_before.outputs.VERSION }}" - if [ "$VERSION_AFTER" != "${{ steps.node_before.outputs.VERSION }}" ]; then - echo "ERROR: Node version changed from ${{ steps.node_before.outputs.VERSION }} to $VERSION_AFTER" - exit 1 - fi - - echo "SUCCESS: Node version preserved" - - test-manual-commit-range: + # All E2E tests are in e2e.yml. Add new tests there, so they also gate docker-publish. + e2e: + name: E2E needs: docker-build - - strategy: - matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-latest] - runs-on: ${{ matrix.os }} - name: Test manual commit range + uses: ./.github/workflows/e2e.yml + secrets: inherit permissions: contents: read - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Create a release with manual commit range - uses: ./ - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_LOG_LEVEL: debug - MOCK: true - with: - environment: production - set_commits: manual - repo: getsentry/action-release - commit: ${{ github.sha }} - previous_commit: ${{ github.sha }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..5743594d --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,214 @@ +name: E2E Tests + +# Called from build.yml after the images are built. The `e2e` job there passes +# only if all jobs here pass, and docker-publish waits for it. +on: + workflow_call: + +# Linux jobs use Ubuntu 26.04 runners (Docker 29). `use-local-image` loads an OCI +# archive, and the Docker 28 on Ubuntu 24.04 runners cannot load it. + +env: + # Variables defined in the repository + # Fork PRs do not get repository variables, so fall back to the values for PRs. + SENTRY_ORG: ${{ vars.SENTRY_ORG || 'sentry-ecosystem' }} + # For master, we have an environment variable that selects the action-release project + # instead of action-release-prs + # For other branches: https://sentry-ecosystem.sentry.io/releases/?project=4505075304693760 + # For master branch: https://sentry-ecosystem.sentry.io/releases/?project=6576594 + SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT || 'action-release-prs' }} + +jobs: + test-create-staging-release-per-push: + # Needs SENTRY_AUTH_TOKEN, which fork PRs do not get. + if: ${{ !github.event.pull_request.head.repo.fork }} + strategy: + matrix: + os: [ubuntu-26.04, ubuntu-26.04-arm, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + permissions: + contents: read + name: Test current action + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./.github/actions/use-local-image + + - name: Create a staging release + uses: ./ + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_LOG_LEVEL: debug + with: + ignore_missing: true + + test-runs-on-container: + # Needs SENTRY_AUTH_TOKEN, which fork PRs do not get. + if: ${{ !github.event.pull_request.head.repo.fork }} + # Pinned like the Linux jobs above, see the comment at the top of this file. + runs-on: ubuntu-26.04 + permissions: + contents: read + container: + image: node:20.19.2 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./.github/actions/use-local-image + + - name: Create a staging release + uses: ./ + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_LOG_LEVEL: debug + with: + ignore_missing: true + + test-mock-release: + strategy: + matrix: + os: [ubuntu-26.04, ubuntu-26.04-arm, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Mock a release + permissions: + contents: read + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./.github/actions/use-local-image + + - name: Mock creating a Sentry release + uses: ./ + env: + MOCK: true + with: + environment: production + + test-mock-release-working-directory: + strategy: + matrix: + os: [ubuntu-26.04, ubuntu-26.04-arm, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Mock a release in a different working directory + permissions: + contents: read + steps: + - name: Checkout directory we'll be running from + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + path: main/ + + - name: Checkout directory we'll be testing + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + path: test/ + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./main/.github/actions/use-local-image + with: + path: main + + - name: Mock creating a Sentry release in a different directory + uses: ./main + env: + MOCK: true + with: + environment: production + working_directory: ./test + + test-node-version-preserved: + strategy: + matrix: + os: [ubuntu-26.04, ubuntu-26.04-arm, windows-latest, macos-latest] + node-version: ['20.x', '22.x', '24.x'] + runs-on: ${{ matrix.os }} + name: Test Node version preserved on ${{ matrix.os }} with Node ${{ matrix.node-version }} + permissions: + contents: read + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./.github/actions/use-local-image + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Print Node Version (Before) + id: node_before + shell: bash + run: | + VERSION=$(node --version) + echo "Node version before: $VERSION" + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + + - name: Mock creating a Sentry release + uses: ./ + env: + MOCK: true + with: + environment: production + + - name: Print Node Version (After) + shell: bash + run: | + VERSION_AFTER=$(node --version) + echo "Node version after: $VERSION_AFTER" + echo "Expected: ${{ steps.node_before.outputs.VERSION }}" + if [ "$VERSION_AFTER" != "${{ steps.node_before.outputs.VERSION }}" ]; then + echo "ERROR: Node version changed from ${{ steps.node_before.outputs.VERSION }} to $VERSION_AFTER" + exit 1 + fi + + echo "SUCCESS: Node version preserved" + + test-manual-commit-range: + + strategy: + matrix: + os: [ubuntu-26.04, ubuntu-26.04-arm, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Test manual commit range + permissions: + contents: read + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Use local action image + if: runner.os == 'Linux' + uses: ./.github/actions/use-local-image + + - name: Create a release with manual commit range + uses: ./ + env: + SENTRY_LOG_LEVEL: debug + MOCK: true + with: + environment: production + set_commits: manual + repo: getsentry/action-release + commit: ${{ github.sha }} + previous_commit: ${{ github.sha }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e51a717f..4e1d5373 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,8 +21,3 @@ repos: entry: yarn lint language: system pass_filenames: false - - id: set-docker-tag-from-branch - name: Set docker tag in action.yml from current git branch - entry: yarn set-docker-tag-from-branch - language: system - pass_filenames: false diff --git a/dist/index.js b/dist/index.js index 75edd0d8..6186ba24 100644 --- a/dist/index.js +++ b/dist/index.js @@ -100637,7 +100637,7 @@ const BROWSER_PAGELOAD_SPAN_OP="pageload",BROWSER_NAVIGATION_SPAN_OP="navigation /***/ ((module) => { "use strict"; -module.exports = JSON.parse('{"name":"action-release","version":"3.7.2","private":true,"description":"GitHub Action for creating a release on Sentry","main":"dist/index.js","scripts":{"all":"yarn run format && yarn run lint && yarn run build && yarn test","build":"ncc build src/main.ts -e @sentry/cli","format":"prettier --write **/*.ts **/*.md","format-check":"prettier --check **/*.ts **/*.md","lint":"eslint src/**/*.ts","set-docker-tag":"./scripts/set-docker-tag.sh","set-docker-tag-from-branch":"./scripts/set-docker-tag-from-branch.sh","start":"node dist/index.js","test":"jest"},"repository":{"type":"git","url":"git+https://github.com/getsentry/action-release.git"},"keywords":["actions","sentry","release"],"author":"Sentry","license":"MIT","dependencies":{"@actions/core":"^2.0.3","@sentry/cli":"^2.58.6","@sentry/node":"^10.71.0"},"devDependencies":{"@types/jest":"^29.5.6","@types/node":"^24.0.0","@typescript-eslint/parser":"^6.9.0","@vercel/ncc":"^0.38.1","eslint":"^8.52.0","eslint-plugin-github":"^4.10.1","eslint-plugin-jest":"^27.4.3","jest":"^29.7.0","jest-circus":"^29.7.0","js-yaml":"^4.3.2","prettier":"^3.0.3","ts-jest":"^29.1.1","typescript":"^5.2.2"},"resolutions":{"**/@istanbuljs/load-nyc-config/js-yaml":"3.15.2"},"volta":{"node":"24.22.1","yarn":"1.22.4"}}'); +module.exports = JSON.parse('{"name":"action-release","version":"3.7.2","private":true,"description":"GitHub Action for creating a release on Sentry","main":"dist/index.js","scripts":{"all":"yarn run format && yarn run lint && yarn run build && yarn test","build":"ncc build src/main.ts -e @sentry/cli","format":"prettier --write **/*.ts **/*.md","format-check":"prettier --check **/*.ts **/*.md","lint":"eslint src/**/*.ts","set-docker-tag":"./scripts/set-docker-tag.sh","start":"node dist/index.js","test":"jest"},"repository":{"type":"git","url":"git+https://github.com/getsentry/action-release.git"},"keywords":["actions","sentry","release"],"author":"Sentry","license":"MIT","dependencies":{"@actions/core":"^2.0.3","@sentry/cli":"^2.58.6","@sentry/node":"^10.71.0"},"devDependencies":{"@types/jest":"^29.5.6","@types/node":"^24.0.0","@typescript-eslint/parser":"^6.9.0","@vercel/ncc":"^0.38.1","eslint":"^8.52.0","eslint-plugin-github":"^4.10.1","eslint-plugin-jest":"^27.4.3","jest":"^29.7.0","jest-circus":"^29.7.0","js-yaml":"^4.3.2","prettier":"^3.0.3","ts-jest":"^29.1.1","typescript":"^5.2.2"},"resolutions":{"**/@istanbuljs/load-nyc-config/js-yaml":"3.15.2"},"volta":{"node":"24.22.1","yarn":"1.22.4"}}'); /***/ }) diff --git a/docs/development.md b/docs/development.md index d8546100..a88dc967 100644 --- a/docs/development.md +++ b/docs/development.md @@ -51,15 +51,21 @@ Telemetry for internal development is collected using `@sentry/node`, see `src/t Members of this repo will not have to set anything up since [the integration](https://sentry-ecosystem.sentry.io/settings/developer-settings/end-to-end-action-release-integration-416eb2/) is already set-up. Just open the PR and you will see [a release created](https://sentry-ecosystem.sentry.io/releases/?project=4505075304693760) for your PR. 1. Create a branch -2. Run `yarn set-docker-tag-from-branch` to set a docker tag based on your github branch name. This is important so that the action gets its own Docker image, allowing you to test the action in a different repo. -3. Make changes -4. If possible, add unit and E2E tests (inside `.github/workflows/build.yml`) -5. Run `yarn install` to install deps -6. Run `yarn build` to build the action -7. Commit the changes and the build inside `dist/` - -If you forget to run `yarn set-docker-tag-from-branch` the repo's pre-commit hooks will do it for you and fail the commit. -Just add the changes to staging and commit again. +2. Make changes +3. If possible, add unit and E2E tests (E2E tests go in `.github/workflows/e2e.yml`) +4. Run `yarn install` to install deps +5. Run `yarn build` to build the action +6. Commit the changes and the build inside `dist/` + +Do not change the Docker image tag in `action.yml`. PR builds do not publish an image to ghcr.io. +The E2E tests load the image of the PR into a local registry (see `.github/actions/use-local-image`). + +### Testing in a different repo + +- After the PR is merged, use `getsentry/action-release@master`. CI publishes the `master` image after the E2E tests pass. +- Before the PR is merged, use `getsentry/action-release@` on a macOS or Windows runner. + These runners do not use the Docker image. They run `dist/` from your branch. + Linux runners use the Docker image, and CI does not publish an image for PR branches. ## Testing diff --git a/package.json b/package.json index bd9812a4..df86dea8 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "format-check": "prettier --check **/*.ts **/*.md", "lint": "eslint src/**/*.ts", "set-docker-tag": "./scripts/set-docker-tag.sh", - "set-docker-tag-from-branch": "./scripts/set-docker-tag-from-branch.sh", "start": "node dist/index.js", "test": "jest" }, diff --git a/scripts/set-docker-tag-from-branch.sh b/scripts/set-docker-tag-from-branch.sh deleted file mode 100755 index f626b04d..00000000 --- a/scripts/set-docker-tag-from-branch.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -eux - -# Extract the branch name from git and replace all non-alphanumerical characters with `-` -BRANCH=$(git rev-parse --abbrev-ref HEAD | sed 's/[^a-zA-Z0-9-]/-/g') - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $SCRIPT_DIR - -./set-docker-tag.sh $BRANCH