This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts-intellij-plugin.git
The following commit(s) were added to refs/heads/main by this push:
new 4937d77 ci: add two-phase release workflow with prepare and publish
steps (#44)
4937d77 is described below
commit 4937d77dfea8e76b0547902df8093a607bc2c84b
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Feb 23 18:00:40 2026 +0100
ci: add two-phase release workflow with prepare and publish steps (#44)
Add prepare_release.yml workflow (manual dispatch) that builds the plugin,
creates a git tag, and publishes a GitHub pre-release for PMC review.
When the pre-release is promoted to a full release, the existing release.yml
fires and publishes to the Marketplace Stable channel.
Also fixes:
- release.yml trigger narrowed to [released] only (was [prereleased,
released])
- build.yml nightly builds now publish to Marketplace nightly channel
- build.yml HEREDOC bug in pre-release notes creation
- README.md documents the full release process
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <[email protected]>
---
.github/workflows/build.yml | 37 ++++++----
.github/workflows/prepare_release.yml | 132 ++++++++++++++++++++++++++++++++++
.github/workflows/release.yml | 2 +-
README.md | 18 +++++
4 files changed, 174 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 078ed4e..fbf87bf 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -282,7 +282,7 @@ jobs:
BUILD=$((LATEST_BUILD + 1))
# Update pluginVersion in gradle.properties
- sed -i "s/pluginVersion = [0-9]*\.[0-9]*\.[0-9]*/pluginVersion =
${BRANCH}.${BUILD}.1/" gradle.properties
+ sed -i "s/pluginVersion = [0-9]*\.[0-9]*\.[0-9]*/pluginVersion =
${BRANCH}.${BUILD}-nightly.1/" gradle.properties
# Get final version and changelog
PROPERTIES="$(./gradlew properties --no-configuration-cache
--console=plain -q)"
@@ -298,6 +298,15 @@ jobs:
- name: Build Plugin
run: ./gradlew buildPlugin --no-configuration-cache
+ # Publish pre-release to JetBrains Marketplace nightly channel
+ - name: Publish Plugin to Marketplace (Nightly)
+ env:
+ PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
+ CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}
+ PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
+ PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
+ run: ./gradlew publishPlugin --no-configuration-cache
+
# Prepare plugin archive content for creating artifact
- name: Prepare Plugin Artifact
id: artifact
@@ -336,24 +345,24 @@ jobs:
- name: Create Pre-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ CHANGELOG: ${{ steps.version.outputs.changelog }}
run: |
# Find the plugin zip file
PLUGIN_ZIP=$(find ./build/distributions -name "*.zip" -type f | head
-1)
-
- gh release create "v${{ steps.version.outputs.version }}" \
- --prerelease \
- --title "v${{ steps.version.outputs.version }}" \
- --notes "$(cat << 'EOM'
- 🚀 **Pre-release v${{ steps.version.outputs.version }}**
-
+
+ NOTES="🚀 **Pre-release v${{ steps.version.outputs.version }}**
+
This is an automated pre-release build from the main branch.
-
+
## Changes
- ${{ steps.version.outputs.changelog }}
-
+ ${CHANGELOG}
+
## Installation
Download the plugin zip file and install it manually in IntelliJ
IDEA via:
- `Settings → Plugins → ⚙️ → Install Plugin from Disk...`
- EOM
- )" \
+ \`Settings → Plugins → ⚙️ → Install Plugin from Disk...\`"
+
+ gh release create "v${{ steps.version.outputs.version }}" \
+ --prerelease \
+ --title "v${{ steps.version.outputs.version }}" \
+ --notes "$NOTES" \
"$PLUGIN_ZIP"
\ No newline at end of file
diff --git a/.github/workflows/prepare_release.yml
b/.github/workflows/prepare_release.yml
new file mode 100644
index 0000000..8b7c641
--- /dev/null
+++ b/.github/workflows/prepare_release.yml
@@ -0,0 +1,132 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+# GitHub Actions Workflow for preparing a release candidate.
+# Builds the plugin, creates a git tag, and publishes a GitHub pre-release
+# with the plugin zip attached for PMC review and voting.
+# Does NOT publish to JetBrains Marketplace — that happens when the
+# pre-release is promoted to a full release (see release.yml).
+
+name: Prepare Release
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Release version (e.g. 253.18970.1). Leave empty to use
pluginVersion from gradle.properties.'
+ required: false
+ default: ''
+
+jobs:
+ prepare:
+ name: Prepare Release
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+
+ # Free GitHub Actions Environment Disk Space
+ - name: Maximize Build Space
+ uses: jlumbroso/[email protected]
+ with:
+ tool-cache: false
+ large-packages: false
+
+ # Check out the selected branch
+ - name: Fetch Sources
+ uses: actions/checkout@v6
+
+ # Set up Java environment for the next steps
+ - name: Setup Java
+ uses: actions/setup-java@v5
+ with:
+ distribution: zulu
+ java-version: 21
+
+ # Setup Gradle
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v5
+ with:
+ gradle-home-cache-cleanup: true
+
+ # Resolve the release version
+ - name: Resolve Version
+ id: version
+ shell: bash
+ run: |
+ if [ -n "${{ github.event.inputs.version }}" ]; then
+ VERSION="${{ github.event.inputs.version }}"
+ # Update pluginVersion in gradle.properties with the override
+ sed -i "s/pluginVersion = .*/pluginVersion = ${VERSION}/"
gradle.properties
+ echo "Using version override: $VERSION"
+ else
+ VERSION=$(grep "pluginVersion" gradle.properties | cut -d '=' -f2
| tr -d ' ')
+ echo "Using version from gradle.properties: $VERSION"
+ fi
+
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+ # Build plugin
+ - name: Build Plugin
+ run: ./gradlew buildPlugin --no-configuration-cache
+
+ # Get changelog for release notes
+ - name: Get Changelog
+ id: changelog
+ shell: bash
+ run: |
+ CHANGELOG="$(./gradlew getChangelog --no-configuration-cache
--unreleased --no-header --console=plain -q)"
+
+ echo "changelog<<EOF" >> $GITHUB_OUTPUT
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
+ # Create and push git tag
+ - name: Create Tag
+ run: |
+ TAG="v${{ steps.version.outputs.version }}"
+ git config user.email "[email protected]"
+ git config user.name "GitHub Action"
+ git tag -a "$TAG" -m "Release $TAG"
+ git push origin "$TAG"
+
+ # Create GitHub pre-release with plugin zip attached
+ - name: Create Pre-release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ CHANGELOG: ${{ steps.changelog.outputs.changelog }}
+ run: |
+ TAG="v${{ steps.version.outputs.version }}"
+ PLUGIN_ZIP=$(find ./build/distributions -name "*.zip" -type f | head
-1)
+
+ NOTES="## Release candidate ${{ steps.version.outputs.version }}
+
+ This is a release candidate for PMC review and voting.
+
+ ### Changes
+ ${CHANGELOG}
+
+ ### Installation
+ Download the plugin zip file and install it manually in IntelliJ
IDEA via:
+ \`Settings → Plugins → ⚙️ → Install Plugin from Disk...\`
+
+ ### Voting
+ Once testing is complete, promote this pre-release to a full release
to
+ trigger publication to the JetBrains Marketplace Stable channel."
+
+ gh release create "$TAG" \
+ --prerelease \
+ --title "$TAG" \
+ --notes "$NOTES" \
+ "$PLUGIN_ZIP"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bcf79a9..7bbe259 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,7 +20,7 @@
name: Release
on:
release:
- types: [prereleased, released]
+ types: [released]
jobs:
release:
diff --git a/README.md b/README.md
index d3b1f75..f872a5a 100644
--- a/README.md
+++ b/README.md
@@ -167,3 +167,21 @@ GitHub Actions will swap it and provide you an empty
section for the next releas
```
To configure how the Changelog plugin behaves, i.e., to create headers with
the release date, see [Gradle Changelog Plugin][gh:gradle-changelog-plugin]
README file.
+
+### Release process
+
+The plugin uses a two-phase release process with nightly builds for continuous
delivery:
+
+**Nightly builds** are created automatically when commits are merged to
`main`. The [Build](.github/workflows/build.yml) workflow runs tests, builds
the plugin, and publishes it to the JetBrains Marketplace **nightly** channel.
A GitHub pre-release is also created with the plugin zip attached.
+
+**Preparing a release** is a manual step. Go to **Actions → Prepare Release →
Run workflow**, optionally providing a version override. This workflow:
+1. Builds the plugin (using the version from `gradle.properties` or your
override)
+2. Creates a git tag `v{VERSION}` and pushes it
+3. Creates a GitHub **pre-release** with the plugin zip attached
+
+PMC members can then download the zip from the pre-release, test it locally,
and vote.
+
+**Publishing a release** happens when the pre-release is promoted to a full
release. Edit the GitHub pre-release, uncheck **"Set as a pre-release"**, and
save. This triggers the [Release](.github/workflows/release.yml) workflow which:
+1. Publishes the plugin to the JetBrains Marketplace **Stable** channel
+2. Uploads the plugin zip as a release asset
+3. Creates a pull request to update the changelog