--- 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 (). 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 `` profile property (that older approach is passed to gpg literally and fails): ```xml apache.snapshots.httpsID{ENC} apache.releases.httpsID{ENC} gpg.passphrase{ENC} apache-release loopback YOUR_KEY_ID smtp.gmail.com ``` 5. **`~/.m2/settings-security.xml`** with the `` 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 [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 ``/`` 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 -x AUTO ``` The description is auto-derived from the staged POM's ` ` (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 ``` 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 # review docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release prepare-email -r -x AUTO # send ``` ### 2.4 — Wait 72h, then tally At least 72 hours on dev@sling.apache.org and ≥3 binding (PMC) +1 votes are required. ```bash docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release tally-votes -r # review docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli release tally-votes -r -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 -x AUTO git push --delete origin # e.g. org.apache.sling.feature.launcher-1.3.4 git tag -d # 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 -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 ``` Review the diff, then commit & push the sling-site changes separately. ## Quick reference `` = `docker run --rm --env-file=$HOME/.apache-committer apache/sling-cli` | Command | When | |---------|------| | ` release list` | List staging repos with `[open]`/`[closed]` state + description | | ` release close-staging -r -x AUTO` | After `mvn release:perform` | | ` release verify -r ` | Before sending the vote email | | ` release prepare-email -r -x AUTO` | Send the `[VOTE]` email | | ` release tally-votes -r -x AUTO` | After 72h with ≥3 binding votes (PMC auto-detected) | | ` release finalize -r -x AUTO` | All post-vote steps (dist included automatically for PMC) | | ` release promote -r -x AUTO` | Promote to Maven Central (individual step) | | ` release update-dist -r -x AUTO` | Update dist.apache.org (PMC only; prev version auto-deduced) | | ` release drop -r -x AUTO` | Drop staging (failed vote / cleanup) | | ` release create-new-jira-version -r -x AUTO` | Create next JIRA version | | ` release release-jira-version -r -x AUTO` | Mark JIRA version released | | ` release update-reporter -r -x AUTO` | Update Apache Reporter | | ` release update-local-site -r ` | 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.