This is an automated email from the ASF dual-hosted git repository. royteeuwen pushed a commit to branch sling-release-skill in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit 4854801a348370112567024e39ffdfe2d8e534e2 Author: Roy Teeuwen <[email protected]> AuthorDate: Sat Jul 4 15:10:05 2026 +0200 Add sling-release agent skill Releases an Apache Sling module end-to-end using Maven and the apache/sling-cli Docker tool (staging, voting, and post-vote finalization). Moved here from the sling-org-apache-sling-committer-cli PR per review feedback. --- skills/README.md | 9 +++ skills/sling-release/SKILL.md | 180 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/skills/README.md b/skills/README.md index 423ed78f..d9ee6a1c 100644 --- a/skills/README.md +++ b/skills/README.md @@ -6,6 +6,7 @@ Current skills: - `update-sling-parent-pom`: Updates the parent POM of a Sling project to the next version. - `osgi-scr-migrator`: Migrates OSGi-based Java projects from deprecated Felix SCR annotations to official OSGi R6/R7 Component annotations, including Java source and Maven POM updates. +- `sling-release`: Releases an Apache Sling module end-to-end using Maven and the `apache/sling-cli` Docker tool (staging, voting, and post-vote finalization). ## Prerequisites @@ -39,6 +40,14 @@ export JAVA_HOME mvn "$@" ``` +### Docker and Maven for releasing + +The `sling-release` skill requires: + +- Docker, to run the `apache/sling-cli` image for the Nexus/vote/finalize steps +- Apache Maven, to stage and perform the release from the project being released +- A configured ASF committer environment (SSH/SVN access, GPG signing key, `settings.xml` with the ASF repository server) + ### Generating diffs for for OSGi components Some parent pom updates require changes to the OSGi components descriptors. These can be validated using the [osgi-ds-metatype-diff](https://github.com/jsedding/osgi-ds-metatype-diff) tool. Since there is no release of this tool yet you will need to build it and install it to your local Maven repository. Building using `-DskipTests -DskipITs` is required for recent Java versions. diff --git a/skills/sling-release/SKILL.md b/skills/sling-release/SKILL.md new file mode 100644 index 00000000..5d0252d3 --- /dev/null +++ b/skills/sling-release/SKILL.md @@ -0,0 +1,180 @@ +--- +name: sling-release +description: Automates releasing an Apache Sling project end-to-end using Maven and the sling-cli Docker tool. Use when the user wants to release a Sling project, start a release, perform any step of the Apache Sling release process, or asks about releasing/voting/promoting a Sling module. +tools: Bash, Read, Edit, Write +--- + +This skill releases an Apache Sling module end-to-end by combining **Maven** steps (run in the +project being released) with the **`apache/sling-cli`** Docker tool (this repo) for the +Nexus/vote/finalize steps. + +## Overview + +Three phases: +1. **Stage** — Maven prepares the release and stages signed artifacts to Nexus. +2. **Vote** — close the staging repo, verify, send the `[VOTE]` email, wait 72h, tally. +3. **Finalize** — after a passing vote: promote to Maven Central, update JIRA + Reporter, and (for + PMC members) publish to `dist.apache.org`. + +## Prerequisites (verify before starting) + +1. **Docker** is available, and the `apache/sling-cli` image is built/pulled. +2. **`~/.apache-committer`** (or any env file) with ASF credentials, passed to the container: + ``` + ASF_USERNAME=your-apache-id + ASF_PASSWORD=your-apache-password + ``` +3. **GPG signing key** published to `keys.openpgp.org` and added to the Sling `KEYS` file + (<https://dist.apache.org/repos/dist/release/sling/KEYS>). +4. **`~/.m2/settings.xml`** configured for maven-gpg-plugin **3.x** (used by recent parent POMs). The + passphrase is read from a **server** whose id is `gpg.passphrase` (the `gpg.passphraseServerId` + default) and decrypted via `settings-security.xml` — **not** from a `<gpg.passphrase>` profile + property (that older approach is passed to gpg literally and fails): + ```xml + <servers> + <server><id>apache.snapshots.https</id><username>ID</username><password>{ENC}</password></server> + <server><id>apache.releases.https</id><username>ID</username><password>{ENC}</password></server> + <server><id>gpg.passphrase</id><passphrase>{ENC}</passphrase></server> + </servers> + <profiles><profile><id>apache-release</id><properties> + <gpg.pinentryMode>loopback</gpg.pinentryMode> + <gpg.keyname>YOUR_KEY_ID</gpg.keyname> + <smtp.host>smtp.gmail.com</smtp.host> + </properties></profile></profiles> + ``` +5. **`~/.m2/settings-security.xml`** with the `<master>` password used to decrypt the above. + +If any prerequisite is missing, stop and tell the user how to set it up before proceeding. + +## Running the CLI + +Use the Docker image directly. A `sling-cli` shell alias may exist but usually includes `-it` (TTY), +which **fails in non-interactive contexts** like Claude Code — so do not rely on it: + +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release <command> [options] +``` + +- Default mode is `DRY_RUN` (shows what would happen). Add `-x AUTO` to execute, `-x INTERACTIVE` to confirm each step. +- Always run a **DRY_RUN first** for any command that sends mail or mutates Nexus/dist, show the user the output, then re-run with `-x AUTO`. +- `~` does not expand inside quoted docker args — use `$HOME`. + +## Determining the Java version (Maven steps) + +Build with the Java version required by the project's Sling parent POM (recent parents require Java +17). If `mvnXX` wrappers are absent, set `JAVA_HOME` explicitly to an installed JDK +(`/usr/libexec/java_home -V` to list). + +## Phase 1: Stage (Maven, in the project being released) + +1. **Parent POM current?** Confirm it's up to date and `mvn clean verify` is green. +2. **Dry-run prepare**, then clean. Verify only `<version>`/`<scm>` differ in `pom.xml.tag`: + ```bash + mvn release:prepare -DdryRun=true && mvn release:clean + ``` +3. **Deploy snapshot**; confirm `META-INF/LICENSE` + `META-INF/NOTICE` are inside the jar: + ```bash + mvn deploy + ``` +4. **Prepare + perform** (creates the tag, bumps to next SNAPSHOT, signs + stages to Nexus): + ```bash + mvn release:prepare + mvn release:perform + ``` + Capture the staging repo id from a `…/orgapachesling-NNNN` line. If it scrolled off, find it with + `release list` (below). + +## Phase 2: Vote + +### 2.0 — Find the staging repo id (if not captured) +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release list +``` +Lists every staging repo with its `[open]`/`[closed]` state. A freshly staged repo is `[open]`; the +numeric suffix of `orgapachesling-NNNN` is the `REPO_ID`. + +### 2.1 — Close the staging repository +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release close-staging -r <REPO_ID> -x AUTO +``` +The description is auto-derived from the staged POM's `<name> <version>` (so it is correct even for an +open repo not yet in the Lucene index). After closing, the repo shows as `[closed]`. + +### 2.2 — Verify artifacts +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release verify -r <REPO_ID> +``` +Confirm PGP signatures, SHA-1, MD5, and CI status all pass before voting. + +### 2.3 — Send the vote email (dry-run first!) +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release prepare-email -r <REPO_ID> # review +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release prepare-email -r <REPO_ID> -x AUTO # send +``` + +### 2.4 — Wait 72h, then tally +At least 72 hours on [email protected] and ≥3 binding (PMC) +1 votes are required. +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release tally-votes -r <REPO_ID> # review +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release tally-votes -r <REPO_ID> -x AUTO # send [RESULT] +``` +**PMC membership is auto-detected from your ASF id** — no flag needed. If you are a PMC member the +result email says you will copy the release to the dist directory yourself; otherwise it asks a PMC +member to do the dist upload. + +### If the vote FAILS +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release drop -r <REPO_ID> -x AUTO +git push --delete origin <TAG_NAME> # e.g. org.apache.sling.feature.launcher-1.3.4 +git tag -d <TAG_NAME> +# restart Phase 1 with a new version +``` + +## Phase 3: Finalize (after a passing vote) + +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release finalize -r <REPO_ID> -x AUTO +``` +Runs in order: promote to Maven Central → (if you are a PMC member) update `dist.apache.org` → +create next JIRA version & move unresolved issues → mark JIRA version released → update Apache +Reporter. + +- **PMC detection is automatic.** A PMC member's run also publishes to `dist.apache.org`; the previous + version to remove is **deduced from the dist/release directory**, so no `--previous-version` is + needed (override with `--previous-version X.Y.Z` only if necessary). A non-PMC run skips the dist + step (a PMC member handles it, as requested in the tally-votes email). + +### Update the website (optional) +```bash +docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release update-local-site -r <REPO_ID> +``` +Review the diff, then commit & push the sling-site changes separately. + +## Quick reference + +`<cli>` = `docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli` + +| Command | When | +|---------|------| +| `<cli> release list` | List staging repos with `[open]`/`[closed]` state + description | +| `<cli> release close-staging -r <ID> -x AUTO` | After `mvn release:perform` | +| `<cli> release verify -r <ID>` | Before sending the vote email | +| `<cli> release prepare-email -r <ID> -x AUTO` | Send the `[VOTE]` email | +| `<cli> release tally-votes -r <ID> -x AUTO` | After 72h with ≥3 binding votes (PMC auto-detected) | +| `<cli> release finalize -r <ID> -x AUTO` | All post-vote steps (dist included automatically for PMC) | +| `<cli> release promote -r <ID> -x AUTO` | Promote to Maven Central (individual step) | +| `<cli> release update-dist -r <ID> -x AUTO` | Update dist.apache.org (PMC only; prev version auto-deduced) | +| `<cli> release drop -r <ID> -x AUTO` | Drop staging (failed vote / cleanup) | +| `<cli> release create-new-jira-version -r <ID> -x AUTO` | Create next JIRA version | +| `<cli> release release-jira-version -r <ID> -x AUTO` | Mark JIRA version released | +| `<cli> release update-reporter -r <ID> -x AUTO` | Update Apache Reporter | +| `<cli> release update-local-site -r <ID>` | Update JBake website content | + +## Execution notes + +When this skill is invoked: +1. Confirm which phase the user is starting from (Stage / Vote / Finalize / Cancel) and the `REPO_ID` if past Phase 1. +2. Verify the prerequisites above before any mutating step. +3. For mail/Nexus/dist commands, run DRY_RUN first, show output, then `-x AUTO`. +4. On failure, diagnose (often a missing prereq or wrong `REPO_ID`) and suggest a fix before retrying. +5. Do not touch git state beyond what the documented steps require.
