From 6a76b88afc91edf4a28c284fee52629244b02480 Mon Sep 17 00:00:00 2001 From: Andrei <168741329+andreiborza@users.noreply.github.com> Date: Thu, 27 Feb 2025 11:12:21 +0100 Subject: [PATCH] feat: Use hybrid docker/composite action approach (#265) * feat: Use hybrid approach depending on runner * Fix tag * Update dist * Add fetch depth to test * Add dependcy on docker-build job for test action * Improve branch extraction naming, add npm scripts to bump docker tags * Pass inputs along * Run tests on workflow_run completed * Update workflow run trigger * Fix fetch-depth * Update comment * Update workflow naming * Update workflow names * Merge test.yml into build.yml to run tests after building * Always install node/npm on non Linux runners, update development docs * Fail the job if docker tag matches MAJOR.MINOR.PATCH naming * Some cleanup * Test with major.minor.patch tag * Rework error message * Update development doc * Add logic to commit `master` docker tag on master runs * Allow linting in parallel * Add pre-commit to the repo * Add Makefile to install pre-commit and yarrn deps * Skip pre-commit in action when committing the master tag back * Add note on `yarn set-docker-tag-from-branch` to development doc * Add formatting and linting to pre-commit * Mark e2e tests in build.yml better * Don't pass filenames to local hooks, fix dockerfile casing * Add changelog --- .dockerignore | 10 ++ .github/workflows/build.yml | 206 ++++++++++++++++++++++++++ .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 121 --------------- .github/workflows/verify-dist.yml | 1 + .pre-commit-config.yaml | 26 ++++ CHANGELOG.md | 19 ++- Dockerfile | 32 ++++ Makefile | 7 + action.yml | 46 ++++-- dist/index.js | 2 +- docs/development.md | 68 ++++++--- entrypoint.sh | 2 + package.json | 12 +- scripts/craft-pre-release.sh | 3 + scripts/set-docker-tag-from-branch.sh | 10 ++ scripts/set-docker-tag.sh | 13 ++ 17 files changed, 414 insertions(+), 166 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .pre-commit-config.yaml create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 entrypoint.sh mode change 100644 => 100755 scripts/craft-pre-release.sh create mode 100755 scripts/set-docker-tag-from-branch.sh create mode 100755 scripts/set-docker-tag.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ed2dfea --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +# Docs: https://docs.docker.com/engine/reference/builder/#dockerignore-file +# These files will be ignore by Docker for COPY and ADD commands when creating a build context +# In other words, if a file should not be inside of the Docker container it should be +# added to the list, otherwise, it will invalidate cache layers and have to rebuild +# all layers after a COPY command +.git +.github +Dockerfile +.dockerignore +*.md \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..fea477a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,206 @@ +name: Build and Test + +on: + pull_request: + paths-ignore: + - '**.md' + push: + branches: + - master + - release/** + 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: + docker-build: + name: Build & publish Docker images + runs-on: ubuntu-latest + permissions: + packages: write + strategy: + matrix: + target: + - name: builder + image: action-release-builder-image + - name: app + image: action-release-image + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Evaluate docker tag + run: | + if [[ "${{ github.ref }}" == "refs/heads/master" ]]; then + echo "DOCKER_TAG=master" >> $GITHUB_ENV + yarn set-docker-tag master + + if ! git diff --quiet action.yml; then + echo "GIT_COMMITTER_NAME=getsentry-bot" >> $GITHUB_ENV; + echo "GIT_AUTHOR_NAME=getsentry-bot" >> $GITHUB_ENV; + echo "EMAIL=bot@sentry.io" >> $GITHUB_ENV; + + git add action.yml + SKIP=lint,format,set-docker-tag-from-branch git commit -m "chore: Set docker tag for master [skip-ci]" + git push + fi + 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_ENV + + 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: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@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 + # + # 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 + uses: docker/build-push-action@v6 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ghcr.io/${{ github.repository_owner }}/${{ matrix.target.image }}:${{ env.DOCKER_TAG }} + cache-from: ghcr.io/${{ github.repository_owner }}/${{ matrix.target.image }}:master + target: ${{ matrix.target.name }} + build-args: BUILDKIT_INLINE_CACHE=1 + + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install + run: yarn install + + - name: Check format + run: yarn format-check + + - name: Lint + run: yarn lint + + - name: Build + run: yarn build + + ############# + # E2E Tests + ############# + + test-create-staging-release-per-push: + needs: docker-build + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Test current action + steps: + - uses: actions/checkout@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 + container: + image: node:18.17 + + steps: + - uses: actions/checkout@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, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Mock a release + steps: + - uses: actions/checkout@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, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + name: Mock a release in a different working directory + steps: + - name: Checkout directory we'll be running from + uses: actions/checkout@v4 + with: + fetch-depth: 0 + path: main/ + + - name: Checkout directory we'll be testing + uses: actions/checkout@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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2924565..0868f2f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Prepare Release +name: "Action: Prepare Release" on: workflow_dispatch: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 57d81c4..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,121 +0,0 @@ -name: Integration Tests - -on: - pull_request: - paths-ignore: - - "**.md" - push: - branches: - - master - - release/** - 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: - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install - run: yarn install - - - name: Check format - run: yarn format-check - - - name: Lint - run: yarn lint - - - name: Build - run: yarn build - - # You're welcome to make changes on this job as part of your PR in order to test out your changes - # We can always undo the changes once we're satisfied with the results - # - # Secrets on this repo do not get shared with PRs opened on a fork, thus, - # add SENTRY_AUTH_TOKEN as a secret to your fork if you want to use this job. - create-staging-release-per-push: - strategy: - matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - runs-on: ${{ matrix.os }} - name: Test current action - steps: - - uses: actions/checkout@v4 - - - name: Create a staging release - uses: ./ - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_LOG_LEVEL: debug - with: - ignore_missing: true - - runs-on-container: - runs-on: ubuntu-latest - container: - image: node:18.17 - - steps: - - uses: actions/checkout@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 - - mock-release: - strategy: - matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - runs-on: ${{ matrix.os }} - name: Mock a release - steps: - - uses: actions/checkout@v4 - - - name: Mock creating a Sentry release - uses: ./ - env: - MOCK: true - with: - environment: production - - mock-release-working-directory: - strategy: - matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - runs-on: ${{ matrix.os }} - name: Mock a release in a different working directory - steps: - - name: Checkout directory we'll be running from - uses: actions/checkout@v4 - with: - path: main/ - - - name: Checkout directory we'll be testing - uses: actions/checkout@v4 - with: - path: test/ - - - name: Mock creating a Sentry release in a different directory - uses: ./main - env: - MOCK: true - with: - environment: production - working_directory: ./test diff --git a/.github/workflows/verify-dist.yml b/.github/workflows/verify-dist.yml index e05c1ba..0d87b5d 100644 --- a/.github/workflows/verify-dist.yml +++ b/.github/workflows/verify-dist.yml @@ -8,6 +8,7 @@ on: push: branches: - master + - release/** paths-ignore: - "**.md" pull_request: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4228dc0 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - repo: local + hooks: + - id: format + name: Format + entry: yarn format + language: system + pass_filenames: false + - id: lint + name: Lint + 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/CHANGELOG.md b/CHANGELOG.md index 3d2e5d6..86728fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## Unreleased + +- feat: Use hybrid docker/composite action approach (#265) by @andreiborza + +After receiving user feedback both on runtime and compatibility issues for `1.10.0` +the action has been reworked to use a Docker based approach on Linux runners, mimicking +`< 1.9.0` versions, while Mac OS and Windows runners will follow the `1.10.0` approach +of installing `@sentry/cli` in the run step. + ## 1.10.5 ### Various fixes & improvements @@ -8,11 +17,11 @@ ## 2.0.0 -> [!NOTE] -> This release contains no changes over `v1.10.4` and is just meant to unblock users that have upgraded to `v2` before. -> +> [!NOTE] +> This release contains no changes over `v1.10.4` and is just meant to unblock users that have upgraded to `v2` before. +> > We **recommend** pinning to `v1`. - + Last week we pushed a `v2` branch that triggered dependabot which treated it as a release. This was not meant to be a release, but many users have upgraded to `v2`. @@ -43,7 +52,7 @@ This release contains changes concerning maintainers of the repo and has no user ## 1.10.0 -- **feat(action): Support macos and windows runners** +- **feat(action): Support macos and windows runners** We now publish a composite action that runs on all runners. Actions can now be properly versioned, allowing pinning versions from here on out. ## 1.9.0 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7d52626 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# The multi stage set up *saves* up image size by avoiding the dev dependencies +# required to produce dist/ +FROM node:18-alpine AS builder +WORKDIR /app +# This layer will invalidate upon new dependencies +COPY package.json yarn.lock ./ +RUN export YARN_CACHE_FOLDER="$(mktemp -d)" \ + && yarn install --frozen-lockfile --quiet \ + && rm -r "$YARN_CACHE_FOLDER" +# If there's some code changes that causes this layer to +# invalidate but it shouldn't, use .dockerignore to exclude it +COPY . . +RUN yarn build + +FROM node:18-alpine AS app +COPY package.json yarn.lock /action-release/ +# On the builder image, we install both types of dependencies rather than +# just the production ones. This generates /action-release/node_modules +RUN export YARN_CACHE_FOLDER="$(mktemp -d)" \ + && cd /action-release \ + && yarn install --frozen-lockfile --production --quiet \ + && rm -r "$YARN_CACHE_FOLDER" + +# Copy the artifacts from `yarn build` +COPY --from=builder /app/dist /action-release/dist/ +RUN chmod +x /action-release/dist/index.js + +RUN printf '[safe]\n directory = *\n' > /etc/gitconfig + +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cec4431 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +install: setup-git + yarn install + +setup-git: +ifneq (, $(shell which pre-commit)) + pre-commit install +endif diff --git a/action.yml b/action.yml index 26331d4..7c1a34d 100644 --- a/action.yml +++ b/action.yml @@ -58,20 +58,46 @@ inputs: runs: using: 'composite' steps: + # For actions running on a linux runner, we use a docker + # approach as it's faster and encapsulates everything needed + # to run the action. + - name: Run docker image + if: runner.os != 'macOS' && runner.os != 'Windows' + env: + # Composite actions don't pass the outer action's inputs + # down into these steps, so we have to replicate all inputs to be accessible + # via @actions/core here and in the `Run Release Action` step further down. + INPUT_ENVIRONMENT: ${{ inputs.environment }} + INPUT_INJECT: ${{ inputs.inject }} + INPUT_SOURCEMAPS: ${{ inputs.sourcemaps }} + INPUT_DIST: ${{ inputs.dist }} + INPUT_FINALIZE: ${{ inputs.finalize }} + INPUT_IGNORE_MISSING: ${{ inputs.ignore_missing }} + INPUT_IGNORE_EMPTY: ${{ inputs.ignore_empty }} + INPUT_STARTED_AT: ${{ inputs.started_at }} + INPUT_VERSION: ${{ inputs.version }} + INPUT_VERSION_PREFIX: ${{ inputs.version_prefix }} + INPUT_SET_COMMITS: ${{ inputs.set_commits }} + INPUT_PROJECTS: ${{ inputs.projects }} + INPUT_URL_PREFIX: ${{ inputs.url_prefix }} + INPUT_STRIP_COMMON_PREFIX: ${{ inputs.strip_common_prefix }} + INPUT_WORKING_DIRECTORY: ${{ inputs.working_directory }} + INPUT_DISABLE_TELEMETRY: ${{ inputs.disable_telemetry }} + INPUT_DISABLE_SAFE_DIRECTORY: ${{ inputs.disable_safe_directory }} + uses: docker://ghcr.io/getsentry/action-release-image:ab-hybrid-action + + # For actions running on macos or windows runners, we use a composite + # action approach which allows us to install the arch specific sentry-cli + # binary that's needed for the runner. + # This is slower than the docker approach but runs on macos and windows. - name: Mark GitHub workspace a safe directory in git - if: ${{ inputs.disable_safe_directory != 'true' }} + if: ${{ (runner.os == 'macOS' || runner.os == 'Windows') && inputs.disable_safe_directory != 'true' }} shell: bash run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" - - name: Get node version - shell: bash - run: | - echo "NODE_VERSION=$(node -v 2>/dev/null || echo '')" >> $GITHUB_ENV - - name: Setup node - # Only install node if there isn't one already - if: env.NODE_VERSION == '' + if: runner.os == 'macOS' || runner.os == 'Windows' uses: actions/setup-node@v4 with: # setup-node doesn't allow absolute paths, so we can't @@ -80,11 +106,13 @@ runs: node-version: 18.17.0 - name: Install Sentry CLI v2 + if: runner.os == 'macOS' || runner.os == 'Windows' shell: bash - run: npm install --save-dev --no-package-lock @sentry/cli@^2.4 + run: npm install --no-package-lock @sentry/cli@^2.4 working-directory: ${{ github.action_path }} - name: Run Release Action + if: runner.os == 'macOS' || runner.os == 'Windows' env: # Composite actions don't pass the outer action's inputs # down into these steps, so we have to replicate all inputs to be accessible diff --git a/dist/index.js b/dist/index.js index daf1425..0260004 100644 --- a/dist/index.js +++ b/dist/index.js @@ -123585,7 +123585,7 @@ module.exports = JSON.parse('{"eN":{"H":"https://github.com/elastic/require-in-t /***/ ((module) => { "use strict"; -module.exports = JSON.parse('{"name":"action-release","version":"1.10.5","private":true,"description":"GitHub Action for creating a release on Sentry","main":"dist/index.js","scripts":{"start":"node dist/index.js","build":"ncc build src/main.ts -e @sentry/cli","format":"prettier --write **/*.ts **/*.md","format-check":"prettier --check **/*.ts **/*.md","lint":"eslint src/**/*.ts","test":"jest","all":"yarn run format && yarn run lint && yarn run build && yarn test"},"repository":{"type":"git","url":"git+https://github.com/getsentry/action-release.git"},"keywords":["actions","sentry","release"],"author":"Sentry","license":"MIT","dependencies":{"@actions/core":"^1.11.1","@sentry/node":"^8.54.0"},"devDependencies":{"@sentry/cli":"^2.41.1","@types/jest":"^29.5.6","@types/node":"^20.8.9","@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.1.0","prettier":"^3.0.3","ts-jest":"^29.1.1","typescript":"^5.2.2"},"volta":{"node":"18.17.0","yarn":"1.22.4"}}'); +module.exports = JSON.parse('{"name":"action-release","version":"1.10.5","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":"^1.11.1","@sentry/node":"^8.54.0","@sentry/cli":"^2.41.1"},"devDependencies":{"@types/jest":"^29.5.6","@types/node":"^20.8.9","@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.1.0","prettier":"^3.0.3","ts-jest":"^29.1.1","typescript":"^5.2.2"},"volta":{"node":"18.17.0","yarn":"1.22.4"}}'); /***/ }) diff --git a/docs/development.md b/docs/development.md index d45cc45..d854610 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,49 +1,69 @@ +# Pre-requirements + +This setup assumes you have [Yarn][Yarn], [Volta][volta] and [pre-commit][pre-commit] installed. + +After cloning the repo, run + +```bash +# Install or update application dependencies +make +``` + # Development of `getsentry/action-release` This document aims to provide guidelines for maintainers and contains information on how to develop and test this action. For info on how to release changes, follow [publishing-a-release](publishing-a-release.md). +The action is a composite GitHub Action. + +On Linux runners, the action executes the underlying JavaScript script +via a Docker image we publish. + +For Mac OS and Windows runners, the action cannot run the Docker image and instead installs +the `@sentry/cli` dependency corresponding to the architecture of the runner and then executes the underlying JavaScript +distribution. + +This split in architecture is done to optimize the run-time of the action but at the same time support non-Linux runners. + +This action runs fastest on Linux runners. + ## Development The action is using `@sentry/cli` under the hood and is written in TypeScript. See `src/main.ts` to get started. Options to the action are exposed via `action.yml`, changes that impact options need to be documented in the `README.md`. +> [!NOTE] +> Actions have to be exposed in 3 places in `action.yml` +> +> 1. Under the `inputs` field - These are the actual inputs exposed to users +> 2. Under the `env` field inside the `Run docker image` step. All inputs have to be mapped from inputs to `INPUT_X` env variables. +> 3. Under the `env` field inside the `Run Release Action + Telemetry for internal development is collected using `@sentry/node`, see `src/telemetry.ts` for utilities. -## Testing +## Development steps -You can run unit tests with `yarn test`. - -### E2E testing on GitHub's CI - -> [!NOTE] +> [!NOTE] > Contributors will need to create an internal integration in their Sentry org and need to be an admin. > See [#Prerequisites](../README.md#prerequisites). 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. -### Test your own repo against an action-release 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/` -> [!NOTE] -> This assumes that you have gone through the [#Usage](../README.md#usage) section and have managed to get your GitHub repository to have worked with this action. +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. -**Step 1** +## Testing -- Create a branch, make changes -- If possible, add unit and E2E tests (inside `.github/workflows/test.yml`) -- Run `yarn install` to install deps -- Run `yarn build` to build the action -- Commit the changes and the build inside `dist/` - -**Step 2** -Create a new Sentry project under your existing Sentry org (only this one time). - -**Step 3** -Create an environment variable in GitHub for the branch you release from (e.g. `master`) and define the same variable as a repository variable which all other branches will use (i.e. your PR's branch) - -**Step 4** -Push to GitHub and the CI will do E2E runs! +You can run unit tests with `yarn test`. ### Troubleshooting diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..1451700 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,2 @@ +#!/bin/sh -l +node /action-release/dist/index.js \ No newline at end of file diff --git a/package.json b/package.json index 1ef25cb..704c2e1 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,15 @@ "description": "GitHub Action for creating a release on Sentry", "main": "dist/index.js", "scripts": { - "start": "node dist/index.js", + "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", - "test": "jest", - "all": "yarn run format && yarn run lint && yarn run build && yarn test" + "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", @@ -26,10 +28,10 @@ "license": "MIT", "dependencies": { "@actions/core": "^1.11.1", - "@sentry/node": "^8.54.0" + "@sentry/node": "^8.54.0", + "@sentry/cli": "^2.41.1" }, "devDependencies": { - "@sentry/cli": "^2.41.1", "@types/jest": "^29.5.6", "@types/node": "^20.8.9", "@typescript-eslint/parser": "^6.9.0", diff --git a/scripts/craft-pre-release.sh b/scripts/craft-pre-release.sh old mode 100644 new mode 100755 index d5ee22b..292ace5 --- a/scripts/craft-pre-release.sh +++ b/scripts/craft-pre-release.sh @@ -16,3 +16,6 @@ npm version "${NEW_VERSION}" # The build output contains the package.json so we need to # rebuild to ensure it's reflected after bumping the version yarn install && yarn build + +# Update the docker tag in action.yml +yarn set-docker-tag "${NEW_VERSION}" diff --git a/scripts/set-docker-tag-from-branch.sh b/scripts/set-docker-tag-from-branch.sh new file mode 100755 index 0000000..f626b04 --- /dev/null +++ b/scripts/set-docker-tag-from-branch.sh @@ -0,0 +1,10 @@ +#!/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 diff --git a/scripts/set-docker-tag.sh b/scripts/set-docker-tag.sh new file mode 100755 index 0000000..86ebe7a --- /dev/null +++ b/scripts/set-docker-tag.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eux + +DOCKER_REGISTRY_IMAGE="docker://ghcr.io/getsentry/action-release-image" +TAG="${1}" + +# Move to the project root +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $SCRIPT_DIR/.. + +# We don't want the backup but this is the only way to make this +# work on macos as well +sed -i.bak -e "s|\($DOCKER_REGISTRY_IMAGE:\)[^']*|\1$TAG|" action.yml && rm -f action.yml.bak