Skip to content
Merged
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
66 changes: 66 additions & 0 deletions .github/workflows/publish-plugin-portal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Publish Plugin to Gradle Plugin Portal

on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-*"
Comment on lines +4 to +7
# No branches: branch pushes produce SNAPSHOTs; Portal rejects them.
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 }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The concurrency group uses github.ref, which for workflow_dispatch events resolves to the branch ref (e.g. refs/heads/main) rather than the tag being published. This means all manual dispatch runs will share the same concurrency group and serialize against each other, even when publishing different tags. Consider incorporating inputs.ref into the group key for dispatch runs, e.g.:

group: ${{ github.workflow }}-${{ inputs.ref || github.ref }}
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish-plugin-portal.yml, line 22:

<comment>The concurrency group uses `github.ref`, which for `workflow_dispatch` events resolves to the branch ref (e.g. `refs/heads/main`) rather than the tag being published. This means all manual dispatch runs will share the same concurrency group and serialize against each other, even when publishing different tags. Consider incorporating `inputs.ref` into the group key for dispatch runs, e.g.:
```yaml
group: ${{ github.workflow }}-${{ inputs.ref || github.ref }}
```</comment>

<file context>
@@ -0,0 +1,66 @@
+  contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: false
+
</file context>
Suggested change
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.workflow }}-${{ inputs.ref || github.ref }}

cancel-in-progress: false
Comment on lines +21 to +23

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 }}
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: workflow_dispatch accepts ref and version independently without enforcing they match, so a manual run can publish a release version from non-tag code.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish-plugin-portal.yml, line 37:

<comment>`workflow_dispatch` accepts `ref` and `version` independently without enforcing they match, so a manual run can publish a release version from non-tag code.</comment>

<file context>
@@ -0,0 +1,66 @@
+          # 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
</file context>


- 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
Comment on lines +37 to +52
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 mismatch publish 🐞 Bug ≡ Correctness

On workflow_dispatch, the workflow checks out inputs.ref but publishes using the separately
supplied inputs.version without verifying they correspond, so it can publish the wrong code under
the wrong version to the Gradle Plugin Portal. This contradicts the repo’s documented release
convention that tag name and VERSION_NAME must match (minus the leading v).
Agent Prompt
### Issue description
`workflow_dispatch` accepts `ref` and `version` as independent required inputs, but the workflow does not validate that the checked-out ref corresponds to the version being published. This can lead to publishing code from one tag/commit under a different version number.

### Issue Context
The repository’s release process documentation states that the tag name must match `VERSION_NAME` in `gradle.properties` (with the `v` prefix stripped). The workflow currently relies on operator correctness but provides no guardrails.

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

### Suggested fix
Add a validation step for `workflow_dispatch` runs before publishing. For example:
- Ensure `inputs.ref` is a tag-like value (e.g., starts with `v`).
- Compute `TAG_VERSION="${REF#v}"` and fail if `inputs.version != TAG_VERSION`.
- Optionally, make `version` optional and derive it from `ref` by default to eliminate mismatch risk.

Example (bash):
```bash
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
  REF="${{ inputs.ref }}"
  TAG_VERSION="${REF#v}"
  if [[ "${REF}" == "${TAG_VERSION}" ]]; then
    echo "ref must start with 'v' (e.g. v1.0.0)"; exit 1
  fi
  if [[ "${{ inputs.version }}" != "${TAG_VERSION}" ]]; then
    echo "version input (${{ inputs.version }}) must match ref ($TAG_VERSION)"; exit 1
  fi
fi
```

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

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
Loading