Skip to content

Extract Gradle Plugin Portal publish into a separate dispatchable workflow#231

Merged
kirich1409 merged 1 commit into
developfrom
chore/portal-publish-separate-job
Jun 1, 2026
Merged

Extract Gradle Plugin Portal publish into a separate dispatchable workflow#231
kirich1409 merged 1 commit into
developfrom
chore/portal-publish-separate-job

Conversation

@kirich1409
Copy link
Copy Markdown
Contributor

What changed

Adds .github/workflows/publish-plugin-portal.yml — a dedicated workflow that publishes :featured-gradle-plugin to the Gradle Plugin Portal, separate from the Maven Central job in publish.yml.

  • Triggers on version tags (v*) and workflow_dispatch with required ref + version inputs.
  • workflow_dispatch checks out the supplied ref (the release tag), so an already-cut release can be (re)published to the Portal without re-running the Maven Central upload.
  • The Portal step now carries both Portal credentials (GRADLE_PUBLISH_KEY/SECRET) and the GPG signing env (signingInMemoryKey*).

Why

The v1.0.0 publish run failed at signFeaturedApplicationPluginMarkerMavenPublication"no configured signatory". com.gradle.plugin-publish creates Maven publications for the plugin markers; the signing plugin signs them, so publishPlugins depends on the sign tasks. The inline Portal step lacked the GPG env (only the Maven Central step had it). The Maven Central upload itself succeeded — only Portal publishing was blocked.

Splitting Portal into its own workflow means a re-run never re-triggers the already-successful publishToMavenCentral step (no risk of a duplicate Central staging repo).

Note for reviewers

workflow_dispatch is only exposed once this file reaches the default branch (main). Until then, dispatching fails with "workflow not found"; the tag-push path works for future releases regardless. Publishing the current 1.0.0 to the Portal therefore happens out-of-band (local publishPlugins from the v1.0.0 tag) — tracked separately.

version is passed via the INPUT_VERSION env var rather than inline shell interpolation (injection-safe).

See swarm-report/v1-portal-publish-state.md.

🤖 Generated with Claude Code

Isolates Portal publication so a re-run never re-triggers the Maven Central
step. Adds workflow_dispatch with required ref/version inputs so the v1.0.0
tag can be published retroactively.

Root cause fixed: the missing GPG signing env (ORG_GRADLE_PROJECT_signingInMemoryKey*)
is now present alongside Portal creds, resolving the signatory error on
marker publications.
@kirich1409 kirich1409 marked this pull request as ready for review June 1, 2026 09:02
Copilot AI review requested due to automatic review settings June 1, 2026 09:02
@kirich1409 kirich1409 merged commit fe9a32c into develop Jun 1, 2026
6 checks passed
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Extract Gradle Plugin Portal publish into separate workflow

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Extracts Gradle Plugin Portal publishing into dedicated workflow
• Adds workflow_dispatch for manual re-publishing with custom ref/version
• Includes GPG signing environment variables for marker publication signing
• Prevents duplicate Maven Central uploads on Portal re-runs
Diagram
flowchart LR
  A["Version Tag Push"] --> B["publish-plugin-portal.yml"]
  C["workflow_dispatch"] --> B
  B --> D["Checkout ref"]
  D --> E["Determine version"]
  E --> F["publishPlugins with GPG env"]
  F --> G["Gradle Plugin Portal"]

Loading

Grey Divider

File Changes

1. .github/workflows/publish-plugin-portal.yml ✨ Enhancement +66/-0

New dedicated Gradle Plugin Portal publish workflow

• New workflow file triggered by version tags and manual dispatch
• Accepts ref and version inputs for retroactive publishing
• Determines version from tag or explicit input with leading 'v' stripped
• Publishes :featured-gradle-plugin with Portal credentials and GPG signing environment

.github/workflows/publish-plugin-portal.yml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Jun 1, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0)

Grey Divider


Action required

1. Ref/version not validated 🐞 Bug ≡ Correctness
Description
For workflow_dispatch, the workflow checks out inputs.ref but always publishes the explicitly
provided inputs.version as ORG_GRADLE_PROJECT_VERSION_NAME without verifying they match. This
can publish a version number that doesn’t correspond to the source being built, creating incorrect
artifacts in the Gradle Plugin Portal.
Code

.github/workflows/publish-plugin-portal.yml[R9-66]

Evidence
The workflow explicitly decouples the ref being built (inputs.ref) from the version being
published (inputs.version) and has no guardrail to prevent mismatches.

.github/workflows/publish-plugin-portal.yml[9-53]
.github/workflows/publish-plugin-portal.yml[55-66]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`workflow_dispatch` accepts both `ref` and `version`, but the workflow never verifies that the checked-out ref corresponds to the version being published.

## Issue Context
The checkout step uses `ref: ${{ inputs.ref || github.ref }}` while `Determine version` uses `inputs.version` when present, and `Publish` exports `ORG_GRADLE_PROJECT_VERSION_NAME` from that computed version.

## Fix Focus Areas
- .github/workflows/publish-plugin-portal.yml[31-66]

## Suggested fix
Add a validation step for `workflow_dispatch` before publishing, e.g.:
- Require `inputs.ref` to be a tag of the form `v${inputs.version}` (string compare).
- Optionally verify it is an exact tag checkout: `git describe --tags --exact-match`.
- Alternatively, remove `version` input entirely and derive version strictly from `inputs.ref` (strip leading `v`) to eliminate mismatch risk.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Dispatch concurrency mis-keyed 🐞 Bug ☼ Reliability
Description
Concurrency is keyed to ${{ github.ref }} even though workflow_dispatch runs may check out `${{
inputs.ref }}`, so manual republishes for different tags can be forced into the same concurrency
group. This can unnecessarily serialize or block unrelated Portal publishes.
Code

.github/workflows/publish-plugin-portal.yml[R21-37]

Evidence
The concurrency group is derived from github.ref, while the actual checkout ref can be
inputs.ref, so grouping can diverge from what is actually being published.

.github/workflows/publish-plugin-portal.yml[21-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`concurrency.group` uses `${{ github.ref }}`, which is not aligned with the actual ref being built when running via `workflow_dispatch`.

## Issue Context
The workflow checks out `${{ inputs.ref || github.ref }}` but concurrency is always `${{ github.workflow }}-${{ github.ref }}`.

## Fix Focus Areas
- .github/workflows/publish-plugin-portal.yml[21-37]

## Suggested fix
Change the group to incorporate the effective checkout ref, e.g.:
- `group: ${{ github.workflow }}-${{ inputs.ref || github.ref }}`
(or a normalized value like `${{ inputs.ref || github.ref_name }}` depending on your desired grouping).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tag patterns single-digit 🐞 Bug ≡ Correctness
Description
The tag filters use patterns like v[0-9]+.[0-9]+.[0-9]+, which only allow a single digit per
SemVer component, so tags like v10.0.0 will not trigger this workflow. This is a latent
correctness issue that will eventually prevent release publishes from running.
Code

.github/workflows/publish-plugin-portal.yml[R3-8]

Evidence
The workflow explicitly defines the restrictive tag patterns, and the same pattern is also present
in publish.yml, indicating the pattern is relied upon for release triggering.

.github/workflows/publish-plugin-portal.yml[3-8]
.github/workflows/publish.yml[3-10]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `on.push.tags` patterns are too strict and will stop matching once any SemVer component becomes multi-digit.

## Issue Context
Patterns currently use `[0-9]+` sequences in a GitHub Actions tag filter.

## Fix Focus Areas
- .github/workflows/publish-plugin-portal.yml[3-8]
- .github/workflows/publish.yml[3-10]

## Suggested fix
Use a glob that supports multi-digit components, e.g.:
- `v[0-9]*.[0-9]*.[0-9]*`
- `v[0-9]*.[0-9]*.[0-9]*-*`
(and consider updating `publish.yml` similarly since it uses the same patterns).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a dedicated GitHub Actions workflow for publishing the :featured-gradle-plugin to the Gradle Plugin Portal, decoupling it from the Maven Central publishing workflow so Portal publishes can be re-run independently.

Changes:

  • Added a new dispatchable workflow that publishes to the Gradle Plugin Portal on version tags and via workflow_dispatch.
  • Implemented version resolution from either manual workflow_dispatch input or the pushed tag name.
  • Ensured both Plugin Portal credentials and GPG signing environment variables are provided for publishPlugins.

Comment on lines +5 to +7
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-*"
Comment on lines +21 to +23
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
Comment on lines +46 to +49
if [[ -n "${INPUT_VERSION}" ]]; then
# Manual dispatch: use the explicitly supplied version.
VERSION="${INPUT_VERSION}"
else
Comment on lines +9 to +66
workflow_dispatch:
inputs:
ref:
description: "Git ref to check out (e.g. v1.0.0). Must point to the exact release tag."
required: true
version:
description: "Plugin version to publish (e.g. 1.0.0, without leading v)."
required: true

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
publish-plugin-portal:
name: Publish plugin to Gradle Plugin Portal
runs-on: ubuntu-latest
environment: Main

steps:
- uses: actions/checkout@v6
with:
# On tag push: check out the triggering tag.
# On workflow_dispatch: check out the explicit ref input so develop-HEAD
# (1.1.0-SNAPSHOT) is never published in place of the release tag.
ref: ${{ inputs.ref || github.ref }}

- uses: ./.github/actions/setup-build-env

- name: Determine version
id: version
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
if [[ -n "${INPUT_VERSION}" ]]; then
# Manual dispatch: use the explicitly supplied version.
VERSION="${INPUT_VERSION}"
else
# Tag push: strip the leading "v" from the tag (e.g. v1.0.0 -> 1.0.0).
VERSION="${GITHUB_REF_NAME#v}"
fi
echo "VERSION_NAME=${VERSION}" | tee -a "$GITHUB_OUTPUT"

- name: Publish plugin to Gradle Plugin Portal
# publishPlugins uploads directly — no manual promotion step unlike Maven Central.
# GPG signing env is required: com.gradle.plugin-publish creates maven publications
# for plugin markers and the signing plugin signs them as part of publishPlugins.
env:
GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }}
GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.GPG_KEY_ID }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_KEY_PASSWORD }}
ORG_GRADLE_PROJECT_VERSION_NAME: ${{ steps.version.outputs.VERSION_NAME }}
run: ./gradlew --no-daemon :featured-gradle-plugin:publishPlugins --no-configuration-cache
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Ref/version not validated 🐞 Bug ≡ Correctness

For workflow_dispatch, the workflow checks out inputs.ref but always publishes the explicitly
provided inputs.version as ORG_GRADLE_PROJECT_VERSION_NAME without verifying they match. This
can publish a version number that doesn’t correspond to the source being built, creating incorrect
artifacts in the Gradle Plugin Portal.
Agent Prompt
## Issue description
`workflow_dispatch` accepts both `ref` and `version`, but the workflow never verifies that the checked-out ref corresponds to the version being published.

## Issue Context
The checkout step uses `ref: ${{ inputs.ref || github.ref }}` while `Determine version` uses `inputs.version` when present, and `Publish` exports `ORG_GRADLE_PROJECT_VERSION_NAME` from that computed version.

## Fix Focus Areas
- .github/workflows/publish-plugin-portal.yml[31-66]

## Suggested fix
Add a validation step for `workflow_dispatch` before publishing, e.g.:
- Require `inputs.ref` to be a tag of the form `v${inputs.version}` (string compare).
- Optionally verify it is an exact tag checkout: `git describe --tags --exact-match`.
- Alternatively, remove `version` input entirely and derive version strictly from `inputs.ref` (strip leading `v`) to eliminate mismatch risk.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants