From 5750c85fc8bccfe6dcff8b37a30617034c940679 Mon Sep 17 00:00:00 2001 From: Rune Johansen Date: Mon, 6 Jul 2026 09:46:58 +0200 Subject: [PATCH 1/3] chore: Add release-please configuration and workflow files --- .github/release-please-config.json | 32 +++++++ .github/workflows/release-please.yml | 128 +++++++++++++++++++++++++++ .release-please-manifest.json | 1 + 3 files changed, 161 insertions(+) create mode 100644 .github/release-please-config.json create mode 100644 .github/workflows/release-please.yml create mode 100644 .release-please-manifest.json diff --git a/.github/release-please-config.json b/.github/release-please-config.json new file mode 100644 index 000000000..bb1955454 --- /dev/null +++ b/.github/release-please-config.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "draft": true, + "force-tag-creation": true, + "release-type": "node", + "always-update": true, + "include-component-in-tag": false, + "include-v-in-release-name": true, + "include-v-in-tag": true, + "commit-search-depth": 1000, + "initial-version": "2.9.0", + "include-commit-authors": true, + "packages": { + ".": { + "changelog-sections": [ + { "type": "feat", "section": ":sparkles: Features" }, + { "type": "feature", "section": ":sparkles: Features" }, + { "type": "fix", "section": ":bug: Bug Fixes" }, + { "type": "patch", "section": ":bug: Bug Fixes" }, + { "type": "perf", "section": ":zap: Performance Improvements" }, + { "type": "refactor", "section": ":wrench: Code Refactoring" }, + { "type": "docs", "section": ":books: Documentation" }, + { "type": "style", "section": ":art: Styles" }, + { "type": "test", "section": ":test_tube: Tests" }, + { "type": "build", "section": ":building_construction: Build System and dependencies" }, + { "type": "ci", "section": ":building_construction: Build System and dependencies" }, + { "type": "chore", "section": ":broom: Chores", "hidden": false }, + { "type": "revert", "section": ":rewind: Reverts" } + ] + } + } +} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 000000000..5c6798f96 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,128 @@ +name: release-please + +on: + push: + branches: + - main + +jobs: + release-please: + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + + steps: + - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 + id: release + with: + config-file: .github/release-please-config.json + + upload-asset: + needs: release-please + if: ${{ needs.release-please.outputs.release_created }} + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + attestations: write + + env: + TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: 24.x + cache: 'npm' + + - run: npm ci + + - run: npm run build-artifact + + - name: Create zip file + run: pushd packages/pxweb2/dist && zip -r $OLDPWD/pxweb-${{ env.TAG_NAME }}.zip ./ + + - name: Upload release asset + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release upload ${{ env.TAG_NAME }} pxweb-${{ env.TAG_NAME }}.zip + + docker-publish: + needs: release-please + if: ${{ needs.release-please.outputs.release_created }} + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + + - name: Log into registry ${{ env.REGISTRY }} + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}},value=${{ env.TAG_NAME }} + type=semver,pattern={{major}}.{{minor}},value=${{ env.TAG_NAME }} + type=semver,pattern={{major}},value=${{ env.TAG_NAME }} + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + publish-release: + needs: [release-please, upload-asset, docker-publish] + if: ${{ needs.release-please.outputs.release_created }} + runs-on: ubuntu-latest + permissions: + contents: write + + env: + TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release edit ${{ env.TAG_NAME }} --draft=false diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 000000000..ffcd4415b --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1 @@ +{ } From fc158f89bdcc209ec4f605af5a98bcfad49ceb86 Mon Sep 17 00:00:00 2001 From: Rune Johansen Date: Tue, 7 Jul 2026 12:08:12 +0200 Subject: [PATCH 2/3] chore: remove obsolete release workflows --- .github/release.yml | 11 ------ .github/workflows/create-release.yml | 35 ------------------ .github/workflows/docker-publish.yml | 54 ---------------------------- 3 files changed, 100 deletions(-) delete mode 100644 .github/release.yml delete mode 100644 .github/workflows/create-release.yml delete mode 100644 .github/workflows/docker-publish.yml diff --git a/.github/release.yml b/.github/release.yml deleted file mode 100644 index 1d8bb9d81..000000000 --- a/.github/release.yml +++ /dev/null @@ -1,11 +0,0 @@ -changelog: - categories: - - title: 🏕 Features - labels: - - "*" - exclude: - labels: - - dependencies - - title: 👒 Dependencies - labels: - - dependencies diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml deleted file mode 100644 index d34907085..000000000 --- a/.github/workflows/create-release.yml +++ /dev/null @@ -1,35 +0,0 @@ -# This workflow runs upon creation of a release in this project. -# This workflow will build the project for production, create a downloadable artifact and uploads this to the tagged release. - -name: Create artifact and add to release - -on: - release: - types: - - published - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: write - - env: - TAG_NAME: ${{ github.event.release.tag_name }} - - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Use Node.js LTS - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 'lts/*' - cache: 'npm' - - run: npm ci - - run: npm run build-artifact - - name: Create zip file - run: pushd packages/pxweb2/dist && zip -r $OLDPWD/pxweb-${{ env.TAG_NAME }}.zip ./ - - name: Upload release asset - env: - GH_TOKEN: ${{ github.token }} - run: | - gh release upload ${{ env.TAG_NAME }} pxweb-${{ env.TAG_NAME }}.zip diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index 091eb342e..000000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Docker build and publish - -on: - release: - types: - - published - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - - steps: - - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Log into registry ${{ env.REGISTRY }} - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - - - name: Build and push Docker image - id: build-and-push - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} From 5b574bd6f449feee4b1ab0252b3f3744037cd17d Mon Sep 17 00:00:00 2001 From: Rune Johansen Date: Fri, 10 Jul 2026 10:33:44 +0200 Subject: [PATCH 3/3] chore: add support for pre-releases --- ...ase-config.json => prerelease-config.json} | 12 ++- .../prerelease-manifest.json | 0 .github/release-config.json | 43 +++++++++++ .github/release-manifest.json | 1 + .github/workflows/release-please.yml | 62 +++++++++++---- MAINTAINERS.md | 75 ++++++++++++++++++- 6 files changed, 173 insertions(+), 20 deletions(-) rename .github/{release-please-config.json => prerelease-config.json} (90%) rename .release-please-manifest.json => .github/prerelease-manifest.json (100%) create mode 100644 .github/release-config.json create mode 100644 .github/release-manifest.json diff --git a/.github/release-please-config.json b/.github/prerelease-config.json similarity index 90% rename from .github/release-please-config.json rename to .github/prerelease-config.json index bb1955454..092279b68 100644 --- a/.github/release-please-config.json +++ b/.github/prerelease-config.json @@ -1,15 +1,19 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "always-update": true, + "changelog-type": "default", + "commit-search-depth": 50, "draft": true, "force-tag-creation": true, - "release-type": "node", - "always-update": true, + "include-commit-authors": true, "include-component-in-tag": false, "include-v-in-release-name": true, "include-v-in-tag": true, - "commit-search-depth": 1000, "initial-version": "2.9.0", - "include-commit-authors": true, + "prerelease": true, + "prerelease-type": "rc.1", + "release-type": "node", + "versioning": "prerelease", "packages": { ".": { "changelog-sections": [ diff --git a/.release-please-manifest.json b/.github/prerelease-manifest.json similarity index 100% rename from .release-please-manifest.json rename to .github/prerelease-manifest.json diff --git a/.github/release-config.json b/.github/release-config.json new file mode 100644 index 000000000..2811a1c5a --- /dev/null +++ b/.github/release-config.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "always-update": true, + "changelog-type": "default", + "commit-search-depth": 50, + "draft": true, + "force-tag-creation": true, + "include-commit-authors": true, + "include-component-in-tag": false, + "include-v-in-release-name": true, + "include-v-in-tag": true, + "initial-version": "2.9.0", + "prerelease": false, + "prerelease-type": "rc.1", + "release-type": "node", + "versioning": "default", + "packages": { + ".": { + "changelog-sections": [ + { "type": "feat", "section": ":sparkles: Features" }, + { "type": "feature", "section": ":sparkles: Features" }, + { "type": "fix", "section": ":bug: Bug Fixes" }, + { "type": "patch", "section": ":bug: Bug Fixes" }, + { "type": "perf", "section": ":zap: Performance Improvements" }, + { "type": "refactor", "section": ":wrench: Code Refactoring" }, + { "type": "docs", "section": ":books: Documentation" }, + { "type": "style", "section": ":art: Styles" }, + { "type": "test", "section": ":test_tube: Tests" }, + { "type": "build", "section": ":building_construction: Build System and dependencies" }, + { "type": "ci", "section": ":building_construction: Build System and dependencies" }, + { "type": "chore", "section": ":broom: Chores", "hidden": false }, + { "type": "revert", "section": ":rewind: Reverts" } + ], + "extra-files": [ + { + "type": "json", + "path": ".github/prerelease-manifest.json", + "jsonpath": "$[\".\"]" + } + ] + } + } +} diff --git a/.github/release-manifest.json b/.github/release-manifest.json new file mode 100644 index 000000000..ffcd4415b --- /dev/null +++ b/.github/release-manifest.json @@ -0,0 +1 @@ +{ } diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 5c6798f96..4604c27d9 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -1,30 +1,62 @@ -name: release-please +name: Create release on: push: branches: - main + workflow_dispatch: + inputs: + prerelease: + description: Create a prerelease instead of a release + type: boolean + required: false + default: false jobs: - release-please: + release: runs-on: ubuntu-latest permissions: contents: write issues: write pull-requests: write outputs: - release_created: ${{ steps.release.outputs.release_created }} - tag_name: ${{ steps.release.outputs.tag_name }} + release_created: ${{ steps.release.outputs.release_created || steps.prerelease.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name || steps.prerelease.outputs.tag_name }} + is_prerelease: ${{ steps.detect-prerelease.outputs.is_prerelease }} steps: - - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Detect prerelease from version in package.json + id: detect-prerelease + run: | + VERSION=$(sed -nE 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' package.json | head -n 1) + IS_PRERELEASE=false + if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then + IS_PRERELEASE=true + fi + echo "is_prerelease=${IS_PRERELEASE}" >> "$GITHUB_OUTPUT" + + - name: Create prerelease + if: (github.event_name == 'workflow_dispatch' && inputs.prerelease == true) || steps.detect-prerelease.outputs.is_prerelease == 'true' + uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 + id: prerelease + with: + config-file: .github/prerelease-config.json + manifest-file: .github/prerelease-manifest.json + + - name: Create release + if: (github.event_name == 'workflow_dispatch' && inputs.prerelease == false) || steps.detect-prerelease.outputs.is_prerelease == 'false' + uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 id: release with: - config-file: .github/release-please-config.json + config-file: .github/release-config.json + manifest-file: .github/release-manifest.json upload-asset: - needs: release-please - if: ${{ needs.release-please.outputs.release_created }} + needs: release + if: ${{ needs.release.outputs.release_created }} runs-on: ubuntu-latest permissions: contents: write @@ -32,7 +64,7 @@ jobs: attestations: write env: - TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + TAG_NAME: ${{ needs.release.outputs.tag_name }} steps: - name: Checkout repository @@ -58,8 +90,8 @@ jobs: gh release upload ${{ env.TAG_NAME }} pxweb-${{ env.TAG_NAME }}.zip docker-publish: - needs: release-please - if: ${{ needs.release-please.outputs.release_created }} + needs: release + if: ${{ needs.release.outputs.release_created }} runs-on: ubuntu-latest permissions: contents: read @@ -68,7 +100,7 @@ jobs: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} - TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + TAG_NAME: ${{ needs.release.outputs.tag_name }} steps: - name: Checkout repository @@ -108,14 +140,14 @@ jobs: labels: ${{ steps.meta.outputs.labels }} publish-release: - needs: [release-please, upload-asset, docker-publish] - if: ${{ needs.release-please.outputs.release_created }} + needs: [release, upload-asset, docker-publish] + if: ${{ needs.release.outputs.release_created }} runs-on: ubuntu-latest permissions: contents: write env: - TAG_NAME: ${{ needs.release-please.outputs.tag_name }} + TAG_NAME: ${{ needs.release.outputs.tag_name }} steps: - name: Checkout repository diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 7a9e259b4..4848f598b 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -29,7 +29,7 @@ An overview of the current technical debt in the project: - For security reasons, we want to wait at least 9 days before updating packages. - Use NPM '--before' or npm-check-updates '--cooldown' flags. - Note: There are challenges with using npm-check-updates and cooldown, read this issue: - https://github.com/raineorshine/npm-check-updates/issues/1556#issuecomment-3809050192 + - First update Storybook to the latest version that is outside the cooldown of 9 days: - Go to Storybook and find the correct version to update to OR look at which Storybook version is wanted in the command output of: @@ -138,3 +138,76 @@ For existing third-party component dependencies, we will utilize Dependabot to h We are committed to continuously updating our dependencies to ensure that we are using the latest versions. However, in some cases, we may encounter conflicts with NX plugins that prevent us from updating to the latest versions. In such situations, we carefully evaluate the impact and risks before deciding on the appropriate course of action. In the event of a security vulnerability being discovered in any of our dependencies, we will prioritize attending to it urgently. Our team will take immediate action to mitigate the risk and apply necessary patches or updates. + +## Releases and pre-releases + +We publish releases through the GitHub workflow [release-please.yml](.github/workflows/release-please.yml). +The workflow uses [release-please](https://github.com/googleapis/release-please) and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) to decide version bumps and generate release notes. + +Useful release-please links: + +1. [release-please repository](https://github.com/googleapis/release-please) +2. [release-please-action](https://github.com/googleapis/release-please-action) +3. [Action inputs and outputs](https://github.com/googleapis/release-please-action#action-inputs) +4. [Manifest configuration](https://github.com/googleapis/release-please/blob/main/docs/manifest-releaser.md) +5. [release-please config reference](https://github.com/googleapis/release-please/blob/main/docs/customizing.md) + +### Release PR flow (important) + +Release-please does not create a release immediately. +It first creates or updates a generated release PR. + +1. A generated PR is opened with the proposed version bump and changelog updates. +2. Maintainers must review and approve that PR. +3. The PR must be merged to main. +4. After merge, release-please creates the GitHub release and tag. + +Without approving and merging the generated release PR, there is no final release. + +### Linear commit history (important) + +Keep a linear history on main. +This makes release-please easier to reason about and keeps changelog generation predictable. + +1. Prefer squash-and-merge or rebase-and-merge for PRs. +2. Avoid unnecessary merge commits from outdated branches. +3. Keep commit messages clean, because they are used to generate release notes. + +### How it is triggered + +1. Push to main: runs automatically. +2. Manual run: use GitHub Actions and start the release-please workflow with workflow_dispatch. + - You can set the prerelease input to true for a manual pre-release run. + +### How stable vs pre-release is selected + +The workflow checks package.json version. + +1. If version is a semver pre-release (for example 2.9.10-rc or 2.9.10-beta.1), it uses the pre-release config. +2. If version is a normal semver release (for example 2.9.10), it uses the normal release config. +3. For manual runs, prerelease input can be used to force pre-release behavior. + +### What the workflow publishes + +When a release is created, the pipeline also: + +1. Builds and uploads a zip artifact named pxweb-{tag}.zip to the GitHub release. +2. Builds and publishes multi-arch Docker images to GHCR. +3. Publishes the GitHub release (removes draft state). + +### Commit message rules (important) + +release-please depends on [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). +Use commit messages like: + +1. feat: add x +2. fix: correct y + +If commits do not follow this style, release-please may not create the expected release PR or tag. + +### Maintainer checklist + +1. Ensure PR titles and commit messages are descriptive and follow conventional commits. +2. Confirm package.json version format is correct for the intended release type. +3. Maintain a linear history on main when merging PRs. +4. Verify workflow success in Actions before announcing the release.