Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 111 additions & 97 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,154 +1,168 @@
name: Build
name: Test and prepare release draft

on:
push:
branches: [ main ]
branches: [main]
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
build:
name: Build
detect_version:
name: Detect new version
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
is_new_version: ${{ steps.version.outputs.is_new_version }}
version: ${{ steps.version.outputs.version }}
steps:
- name: Maximize Build Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false

- name: Fetch Sources
- name: Fetch sources
uses: actions/checkout@v6

- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21
fetch-depth: 0

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
- name: Check version
id: version
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail

- name: Build plugin
run: ./gradlew buildPlugin
version=$(sed -nE 's/^version[[:space:]]*=[[:space:]]*(.+)[[:space:]]*$/\1/p' gradle.properties | head -n 1)
if [[ -z "$version" ]]; then
echo "Unable to read version from gradle.properties" >&2
exit 1
fi

- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: plugin-distribution
path: ./build/distributions/*.zip
echo "version=$version" >> "$GITHUB_OUTPUT"

if git rev-parse --verify --quiet "refs/tags/$version" >/dev/null || \
gh release view "$version" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
Comment on lines +45 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow existing drafts to be refreshed

When another commit is pushed while the version remains unchanged, the draft created by the first run makes gh release view "$version" succeed, so this run sets is_new_version=false and skips the release job. The existing draft therefore retains the distribution and target SHA from the earlier commit, even though lines 152–160 explicitly attempt to support updating an existing release. The GitHub CLI documentation confirms that gh release view returns release metadata including isDraft; distinguish published releases/tags from drafts so subsequent successful pushes can rebuild and replace the draft assets.

Useful? React with 👍 / 👎.

echo "Version $version already has a tag or release; nothing to publish."
echo "is_new_version=false" >> "$GITHUB_OUTPUT"
else
echo "Version $version is new and will be released."
echo "is_new_version=true" >> "$GITHUB_OUTPUT"
fi

test:
name: Test
needs: [ build ]
name: Unit, integration, and UI component tests
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Maximize Build Space
- name: Maximize build space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false

- name: Fetch Sources
- name: Fetch sources
uses: actions/checkout@v6

- name: Setup Java
- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21

- name: Setup Gradle
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6
with:
cache-read-only: true

- name: Run Tests
run: ./gradlew check
- name: Run unit, integration, and UI component tests
run: >-
./gradlew unitTest integrationTest ideaUiTest
--continue
--no-configuration-cache
--console=plain

- name: Collect Tests Result
- name: Upload test reports on failure
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: tests-result
path: ${{ github.workspace }}/build/reports/tests

verify:
name: Verify plugin
needs: [ build ]
name: test-reports-${{ github.run_id }}
path: build/reports/tests
if-no-files-found: ignore
retention-days: 7

release:
name: Build draft ${{ needs.detect_version.outputs.version }}
needs: [detect_version, test]
if: github.event_name != 'pull_request' && needs.detect_version.outputs.is_new_version == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Maximize Build Space
- name: Maximize build space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: false
large-packages: false

- name: Fetch Sources
- name: Fetch sources
uses: actions/checkout@v6

- name: Setup Java
- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21

- name: Setup Gradle
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6
with:
cache-read-only: true

- name: Run Plugin Verification tasks
run: ./gradlew verifyPlugin

- name: Collect Plugin Verifier Result
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: pluginVerifier-result
path: ${{ github.workspace }}/build/reports/pluginVerifier
- name: Build plugin distribution
run: ./gradlew buildPlugin --console=plain

releaseDraft:
name: Release draft
if: github.event_name != 'pull_request'
needs: [ build, test, verify ]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Fetch Sources
uses: actions/checkout@v6

- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
with:
cache-read-only: true

- name: Remove Old Release Drafts
- name: Create release notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ needs.detect_version.outputs.version }}
run: |
gh api repos/{owner}/{repo}/releases \
--jq '.[] | select(.draft == true) | .id' \
| xargs -r -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}

- name: Create Release Draft
mkdir -p build/tmp
./gradlew getChangelog \
--project-version "$VERSION" \
--no-header \
--no-links \
--quiet \
--console=plain \
--output-file=build/tmp/release-note.md

- name: Create draft release and upload distribution
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ github.token }}
VERSION: ${{ needs.detect_version.outputs.version }}
shell: bash
run: |
VERSION=$(./gradlew properties --property version --quiet --console=plain | tail -n 1 | cut -f2- -d ' ')
RELEASE_NOTE="./build/tmp/release_note.txt"
./gradlew getChangelog --unreleased --no-header --quiet --console=plain --output-file=$RELEASE_NOTE

gh release create "$VERSION" \
--draft \
--title "$VERSION" \
--notes-file "$RELEASE_NOTE"
set -euo pipefail
shopt -s nullglob
distributions=(build/distributions/*.zip)

if (( ${#distributions[@]} == 0 )); then
echo "No plugin distribution found in build/distributions" >&2
exit 1
fi

if gh release view "$VERSION" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
gh release edit "$VERSION" \
--repo "$GITHUB_REPOSITORY" \
--draft \
--title "$VERSION" \
--notes-file build/tmp/release-note.md
gh release upload "$VERSION" "${distributions[@]}" \
--repo "$GITHUB_REPOSITORY" \
--clobber
else
gh release create "$VERSION" "${distributions[@]}" \
--repo "$GITHUB_REPOSITORY" \
--target "$GITHUB_SHA" \
--draft \
--title "$VERSION" \
--notes-file build/tmp/release-note.md
fi
75 changes: 75 additions & 0 deletions .github/workflows/publish-marketplace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Publish plugin to JetBrains Marketplace

on:
release:
types: [published]

concurrency:
group: marketplace-${{ github.event.release.tag_name }}
cancel-in-progress: false

jobs:
publish:
name: Publish ${{ github.event.release.tag_name }}
runs-on: ubuntu-latest
steps:
- name: Fetch released sources
uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}

- name: Validate release version
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
shell: bash
run: |
set -euo pipefail
project_version=$(sed -nE 's/^version[[:space:]]*=[[:space:]]*(.+)[[:space:]]*$/\1/p' gradle.properties | head -n 1)

if [[ -z "$project_version" ]]; then
echo "Unable to read version from gradle.properties" >&2
exit 1
fi

if [[ "$RELEASE_TAG" != "$project_version" ]]; then
echo "Release tag '$RELEASE_TAG' does not match gradle.properties version '$project_version'." >&2
exit 1
fi

- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6

- name: Check publishing secrets
env:
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
shell: bash
run: |
set -euo pipefail
missing_secrets=()
for secret_name in PUBLISH_TOKEN CERTIFICATE_CHAIN PRIVATE_KEY PRIVATE_KEY_PASSWORD; do
if [[ -z "${!secret_name}" ]]; then
missing_secrets+=("$secret_name")
fi
done

if (( ${#missing_secrets[@]} > 0 )); then
echo "Missing required repository secrets: ${missing_secrets[*]}" >&2
exit 1
fi

- name: Publish to JetBrains Marketplace
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 --console=plain
Loading