You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2026/07/01 06:52:03 UTC
(struts-site) branch docs/jenkins-javadocs-pipeline-spec created (now 0800911aa)
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a change to branch docs/jenkins-javadocs-pipeline-spec
in repository https://gitbox.apache.org/repos/asf/struts-site.git
at 0800911aa ci: add declarative pipeline for the javadocs job
This branch includes the following new commits:
new ac12e766e docs: add design spec for javadocs Jenkins pipeline conversion
new d738d844d docs: add implementation plan for javadocs Jenkins pipeline
new 0800911aa ci: add declarative pipeline for the javadocs job
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(struts-site) 01/03: docs: add design spec for javadocs Jenkins pipeline conversion
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/jenkins-javadocs-pipeline-spec
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit ac12e766e9495efa05b56e1c29d5ac233ba9003d
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Wed Jul 1 08:46:00 2026 +0200
docs: add design spec for javadocs Jenkins pipeline conversion
Converts the shell-based Struts-site-javadocs freestyle job into a
declarative Jenkins pipeline (Jenkinsfile.javadocs), mirroring the
existing root Jenkinsfile conventions. Two intended deviations: use
plain `mvn` instead of `./mvnw`, and push via the explicit `asf`
remote.
Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
.../2026-07-01-jenkins-javadocs-pipeline-design.md | 127 +++++++++++++++++++++
1 file changed, 127 insertions(+)
diff --git a/docs/superpowers/specs/2026-07-01-jenkins-javadocs-pipeline-design.md b/docs/superpowers/specs/2026-07-01-jenkins-javadocs-pipeline-design.md
new file mode 100644
index 000000000..9f72588c7
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-01-jenkins-javadocs-pipeline-design.md
@@ -0,0 +1,127 @@
+# Convert the Struts-site-javadocs Jenkins job to a declarative pipeline
+
+**Date:** 2026-07-01
+**Status:** Approved — ready for implementation plan
+
+## Problem
+
+The `Struts-site-javadocs` Jenkins job (https://ci-builds.apache.org/job/Struts/job/Struts-site-javadocs/)
+is currently a freestyle job with an inline `#!/bin/sh` build step. It:
+
+1. Clones `apache/struts` into `target/struts`, checks out `main` or a release tag.
+2. Builds the project and generates + stages the Maven site.
+3. Publishes the staged site into `source/maven/` on the `struts-site` `main` branch,
+ commits, and pushes. The ASF Jekyll buildbot then republishes `main → asf-site`.
+
+We want this expressed as a declarative Jenkins pipeline (Groovy), consistent with the
+existing website-build pipeline already in this repo.
+
+## Goals
+
+- Replace the shell freestyle job with a reviewable, version-controlled declarative pipeline.
+- Preserve current behavior exactly, except for the two deliberate changes below.
+- Match the conventions of the existing root `Jenkinsfile` (the `Struts-site` job).
+
+## Non-goals
+
+- No change to what content is published or where (`source/maven/` on `main`).
+- No change to the ASF `main → asf-site` republish mechanism.
+- Removing the `mvnw`/`.mvn/` wrapper files from the **apache/struts** repo (separate
+ repo, separate commit — see Follow-ups).
+
+## Deliberate changes vs. the current shell script
+
+1. **`./mvnw` → `mvn`.** Use the Maven installation on the ASF agent instead of the
+ Struts project's Maven wrapper. This makes the `MAVEN_3_LATEST_HOME` PATH entry
+ load-bearing (it is what resolves `mvn`), so it is kept.
+2. **`git push origin main` → `git push asf main`.** Mirror the existing `Jenkinsfile`'s
+ explicit `asf` remote pattern rather than relying on the ambient `origin`.
+
+## Design
+
+### Placement
+
+A new file **`Jenkinsfile.javadocs`** at the repo root. The `Struts-site-javadocs` job is
+reconfigured in Jenkins as **Pipeline script from SCM** → this repo, branch `main`, script
+path `Jenkinsfile.javadocs`. Both job definitions then live in git.
+
+### Trigger & parameters
+
+Manually triggered ("Build with Parameters"). One parameter:
+
+```groovy
+parameters {
+ string(name: 'STRUTS_TAG', defaultValue: 'main',
+ description: 'Struts release tag (e.g. STRUTS_7_2_1) or "main"')
+}
+```
+
+### Agent, options, environment
+
+```groovy
+agent { label 'git-websites' }
+
+options {
+ buildDiscarder logRotator(numToKeepStr: '5')
+ timeout(90) // full Struts build + site:site is slow
+ disableConcurrentBuilds()
+ skipStagesAfterUnstable()
+}
+
+environment {
+ MAVEN_OPTS = '-Xmx2048m -Dhttps.protocols=TLSv1.2 -DfailOnError=false'
+ PATH = "${MAVEN_3_LATEST_HOME}:${env.PATH}" // required: resolves `mvn` on the ASF agent
+}
+```
+
+### Stages
+
+**Stage 1 — Build Struts & Maven site**
+
+Single `sh` step, all work under the gitignored `target/` so the struts clone never
+pollutes the site repo:
+
+- `rm -rf target/struts`
+- clone `https://gitbox.apache.org/repos/asf/struts.git` into `target/struts`
+- checkout: if `STRUTS_TAG == main` → `git checkout main`, else `git checkout "tags/${STRUTS_TAG}"`
+- `mvn -B -V clean install -DskipTests`
+- `mvn -B -V site:site site:stage`
+
+**Stage 2 — Publish to source/maven**
+
+Mirror the existing `Jenkinsfile` deploy pattern:
+
+- add the `asf` remote if missing → `https://gitbox.apache.org/repos/asf/struts-site.git`
+- `git checkout main` && `git pull asf main`
+- `rm -rf source/maven && mkdir -p source/maven`
+- `mv target/struts/target/staging/* source/maven/`
+- `git add source/maven`
+- `git diff --cached --quiet || git commit -m "Updates Maven site by Jenkins"`
+- `git push asf main`
+
+### Post
+
+Copy the `post { failure {} fixed {} }` `emailext` blocks verbatim from the existing
+root `Jenkinsfile` (from "Mr. Jenkins", recipients via `DevelopersRecipientProvider`).
+
+## Behavior parity checklist
+
+| Aspect | Shell script | Pipeline | Same? |
+|-------------------------------|-------------------------|-------------------------|-------|
+| Clone location | `target/struts` | `target/struts` | ✅ |
+| Tag/main selection | `STRUTS_TAG` | `STRUTS_TAG` param | ✅ |
+| Build command | `./mvnw clean install` | `mvn clean install` | ⚠️ intended |
+| Site command | `./mvnw site:site …` | `mvn site:site …` | ⚠️ intended |
+| MAVEN_OPTS | same | same | ✅ |
+| Publish target | `source/maven` on main | `source/maven` on main | ✅ |
+| Commit message | "Updates Maven site …" | identical | ✅ |
+| Empty-commit guard | `git diff --cached -q` | identical | ✅ |
+| Push remote | `origin` | `asf` | ⚠️ intended |
+
+## Follow-ups (out of scope for this change)
+
+- Delete `mvnw`, `mvnw.cmd`, and `.mvn/` from the **apache/struts** repo so the wrapper and
+ the CI job do not drift now that CI uses plain `mvn`.
+- Optional: revisit PR #293's note that the javadocs job is the "sole source of truth" for
+ `maven/` on `asf-site`, to confirm the `source/maven` on `main` publish path is still the
+ intended flow.
(struts-site) 02/03: docs: add implementation plan for javadocs Jenkins pipeline
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/jenkins-javadocs-pipeline-spec
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit d738d844d6441ee1b1bb6bd90435225ea4d3bb9d
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Wed Jul 1 08:48:19 2026 +0200
docs: add implementation plan for javadocs Jenkins pipeline
Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
.../plans/2026-07-01-jenkins-javadocs-pipeline.md | 234 +++++++++++++++++++++
1 file changed, 234 insertions(+)
diff --git a/docs/superpowers/plans/2026-07-01-jenkins-javadocs-pipeline.md b/docs/superpowers/plans/2026-07-01-jenkins-javadocs-pipeline.md
new file mode 100644
index 000000000..3b6fb75c8
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-01-jenkins-javadocs-pipeline.md
@@ -0,0 +1,234 @@
+# Jenkins JavaDocs Pipeline Conversion Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Replace the shell-based `Struts-site-javadocs` freestyle Jenkins job with a version-controlled declarative pipeline, `Jenkinsfile.javadocs`.
+
+**Architecture:** A declarative Jenkins pipeline at the repo root, run on the ASF `git-websites` agent, manually triggered with a `STRUTS_TAG` parameter. Stage 1 clones + builds Struts and stages its Maven site under the gitignored `target/`; Stage 2 publishes the staged site into `source/maven/` on `main` and pushes to the `asf` gitbox remote. Mirrors the existing root `Jenkinsfile` conventions.
+
+**Tech Stack:** Jenkins declarative pipeline (Groovy DSL), shell, Maven (`mvn` on the ASF agent via `MAVEN_3_LATEST_HOME`), git (gitbox).
+
+## Global Constraints
+
+- Spec: `docs/superpowers/specs/2026-07-01-jenkins-javadocs-pipeline-design.md`.
+- Behavior must match the current shell script exactly, except two intended deviations:
+ - Build with plain `mvn`, not `./mvnw`.
+ - Push via the explicit `asf` remote, not `origin`.
+- Commit message that publishes the site MUST be exactly `Updates Maven site by Jenkins`.
+- Empty-commit guard MUST be preserved: `git diff --cached --quiet || git commit ...`.
+- Clone location MUST remain `target/struts` (under the gitignored `target/`).
+- `STRUTS_TAG` default is `main`; any other value is treated as a git tag (`tags/${STRUTS_TAG}`).
+- Do NOT modify the existing root `Jenkinsfile` (that is the separate `Struts-site` job).
+- Declarative pipelines cannot be validated by a standalone `groovy` binary; local checks are structural only, real acceptance is a manual Jenkins run (Task 2).
+
+---
+
+### Task 1: Author `Jenkinsfile.javadocs`
+
+**Files:**
+- Create: `Jenkinsfile.javadocs`
+- Reference (do not modify): `Jenkinsfile` (source of the `post` email blocks and style)
+
+**Interfaces:**
+- Consumes: ASF Jenkins agent env var `MAVEN_3_LATEST_HOME`; agent label `git-websites`; `emailext` and `DevelopersRecipientProvider` (provided by the Jenkins controller, same as the existing `Jenkinsfile`).
+- Produces: a pipeline definition file that the Jenkins job (Task 2) points at via "Pipeline script from SCM".
+
+- [ ] **Step 1: Create the file with the full pipeline**
+
+Create `Jenkinsfile.javadocs` with exactly this content:
+
+```groovy
+#!groovy
+
+pipeline {
+ agent {
+ label 'git-websites'
+ }
+ parameters {
+ string(name: 'STRUTS_TAG', defaultValue: 'main',
+ description: 'Struts release tag (e.g. STRUTS_7_2_1) or "main"')
+ }
+ options {
+ buildDiscarder logRotator(numToKeepStr: '5')
+ timeout(90)
+ disableConcurrentBuilds()
+ skipStagesAfterUnstable()
+ }
+ environment {
+ MAVEN_OPTS = '-Xmx2048m -Dhttps.protocols=TLSv1.2 -DfailOnError=false'
+ // Required: resolves `mvn` on the ASF agent (we use plain mvn, not the wrapper).
+ PATH = "${MAVEN_3_LATEST_HOME}:${env.PATH}"
+ }
+ stages {
+ stage('Build Struts & Maven site') {
+ steps {
+ sh '''
+ echo "Building Struts ${STRUTS_TAG} and staging the Maven site"
+
+ rm -rf target/struts
+ git clone https://gitbox.apache.org/repos/asf/struts.git target/struts
+
+ cd target/struts
+ if [ "${STRUTS_TAG}" = "main" ]; then
+ git checkout main
+ else
+ git checkout "tags/${STRUTS_TAG}"
+ fi
+
+ mvn -B -V clean install -DskipTests
+ mvn -B -V site:site site:stage
+ '''
+ }
+ }
+ stage('Publish to source/maven') {
+ steps {
+ sh '''
+ echo "Publishing the staged Maven site into source/maven on main"
+
+ if ! git config remote.asf.url > /dev/null; then
+ git remote add asf https://gitbox.apache.org/repos/asf/struts-site.git
+ fi
+
+ git fetch asf
+ git checkout main
+ git pull asf main
+
+ rm -rf source/maven
+ mkdir -p source/maven
+ mv target/struts/target/staging/* source/maven/
+
+ git add source/maven
+ git status
+
+ git diff --cached --quiet || git commit -m "Updates Maven site by Jenkins"
+ git push asf main
+ '''
+ }
+ }
+ }
+ post {
+ // If this build failed, send an email to the developers.
+ failure {
+ script {
+ emailext(
+ recipientProviders: [[$class: 'DevelopersRecipientProvider']],
+ from: "Mr. Jenkins <je...@builds.apache.org>",
+ subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} failed",
+ body: """
+There is a build failure in ${env.JOB_NAME}.
+
+Build: ${env.BUILD_URL}
+Logs: ${env.BUILD_URL}console
+Changes: ${env.BUILD_URL}changes
+
+--
+Mr. Jenkins
+Director of Continuous Integration
+"""
+ )
+ }
+ }
+ // Send an email, if the last build was not successful and this one is.
+ fixed {
+ script {
+ emailext(
+ recipientProviders: [[$class: 'DevelopersRecipientProvider']],
+ from: 'Mr. Jenkins <je...@builds.apache.org>',
+ subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} back to normal",
+ body: """
+The build for ${env.JOB_NAME} completed successfully and is back to normal.
+
+Build: ${env.BUILD_URL}
+Logs: ${env.BUILD_URL}console
+Changes: ${env.BUILD_URL}changes
+
+--
+Mr. Jenkins
+Director of Continuous Integration
+"""
+ )
+ }
+ }
+ }
+}
+```
+
+- [ ] **Step 2: Structural sanity checks**
+
+Run:
+```bash
+# Balanced braces (should print: braces OK)
+awk '{for(i=1;i<=length($0);i++){c=substr($0,i,1);if(c=="{")n++;if(c=="}")n--}} END{print (n==0)?"braces OK":"UNBALANCED: "n}' Jenkinsfile.javadocs
+
+# Required blocks are present (each grep should print a match)
+grep -n "agent {" Jenkinsfile.javadocs
+grep -n "string(name: 'STRUTS_TAG'" Jenkinsfile.javadocs
+grep -n "mvn -B -V clean install -DskipTests" Jenkinsfile.javadocs
+grep -n "mvn -B -V site:site site:stage" Jenkinsfile.javadocs
+grep -n 'git push asf main' Jenkinsfile.javadocs
+grep -n 'Updates Maven site by Jenkins' Jenkinsfile.javadocs
+
+# The wrapper must NOT be referenced anymore (should print: no mvnw refs OK)
+grep -q './mvnw' Jenkinsfile.javadocs && echo "FOUND mvnw — must be removed" || echo "no mvnw refs OK"
+```
+Expected: `braces OK`; every `grep -n` prints its line; final line prints `no mvnw refs OK`.
+
+- [ ] **Step 3: Confirm the existing Jenkinsfile is untouched**
+
+Run: `git status --porcelain Jenkinsfile`
+Expected: no output (the `Struts-site` job's file is unchanged).
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add Jenkinsfile.javadocs
+git commit -m "ci: add declarative pipeline for the javadocs job
+
+Converts the shell-based Struts-site-javadocs freestyle job into
+Jenkinsfile.javadocs. Builds Struts with plain \`mvn\` and publishes the
+staged Maven site into source/maven on main via the asf remote.
+
+Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>"
+```
+
+---
+
+### Task 2: Wire up and verify the Jenkins job (operational — runs in Jenkins, not the repo)
+
+This task has no repo commit; its deliverable is a green build that publishes the site. It cannot be done until Task 1's branch is merged to `main` (the job checks out `main`).
+
+**Interfaces:**
+- Consumes: `Jenkinsfile.javadocs` on `main`; ASF Jenkins credentials on the `git-websites` agent.
+- Produces: an updated `source/maven/` on `main` (and, via the ASF Jekyll buildbot, `asf-site`).
+
+- [ ] **Step 1: Merge Task 1 to `main`**
+
+Open a PR from the Task 1 branch and merge it, so `Jenkinsfile.javadocs` exists on `main`.
+
+- [ ] **Step 2: Reconfigure the Jenkins job**
+
+In `Struts-site-javadocs` → Configure:
+- Definition: **Pipeline script from SCM**
+- SCM: Git, repo `https://gitbox.apache.org/repos/asf/struts-site.git`, branch `*/main`
+- Script Path: `Jenkinsfile.javadocs`
+- Save.
+
+- [ ] **Step 3: Dry-run against `main`**
+
+Trigger **Build with Parameters** with `STRUTS_TAG=main`.
+Expected: both stages green; console shows `mvn` (not `mvnw`) being used; final step either commits `Updates Maven site by Jenkins` and pushes to `asf` `main`, or reports nothing to commit if the site is unchanged.
+
+- [ ] **Step 4: Verify the published output**
+
+On `main` after the run, confirm `source/maven/` contains freshly generated Maven site HTML (e.g. `source/maven/index.html` present, timestamps current). Confirm the ASF buildbot republished to `asf-site` (check https://struts.apache.org/maven/).
+
+- [ ] **Step 5: (Optional) Tag run**
+
+Re-run with a real tag (e.g. `STRUTS_TAG=STRUTS_7_2_1`) to confirm the `tags/${STRUTS_TAG}` checkout path works.
+
+---
+
+## Follow-ups (tracked in the spec, not part of this plan)
+
+- Delete `mvnw`, `mvnw.cmd`, `.mvn/` from the **apache/struts** repo (separate repo/commit) so the wrapper and CI don't drift now that CI uses plain `mvn`.
+- Revisit PR #293's "sole source of truth" note to confirm the `source/maven` on `main` publish path is still intended.
(struts-site) 03/03: ci: add declarative pipeline for the javadocs job
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/jenkins-javadocs-pipeline-spec
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit 0800911aa50363f794edc665297da35c7ea028c3
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Wed Jul 1 08:50:33 2026 +0200
ci: add declarative pipeline for the javadocs job
Converts the shell-based Struts-site-javadocs freestyle job into
Jenkinsfile.javadocs. Builds Struts with plain `mvn` and publishes the
staged Maven site into source/maven on main via the asf remote.
Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
Jenkinsfile.javadocs | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/Jenkinsfile.javadocs b/Jenkinsfile.javadocs
new file mode 100644
index 000000000..4fc90a4f6
--- /dev/null
+++ b/Jenkinsfile.javadocs
@@ -0,0 +1,113 @@
+#!groovy
+
+pipeline {
+ agent {
+ label 'git-websites'
+ }
+ parameters {
+ string(name: 'STRUTS_TAG', defaultValue: 'main',
+ description: 'Struts release tag (e.g. STRUTS_7_2_1) or "main"')
+ }
+ options {
+ buildDiscarder logRotator(numToKeepStr: '5')
+ timeout(90)
+ disableConcurrentBuilds()
+ skipStagesAfterUnstable()
+ }
+ environment {
+ MAVEN_OPTS = '-Xmx2048m -Dhttps.protocols=TLSv1.2 -DfailOnError=false'
+ // Required: resolves `mvn` on the ASF agent (we use plain mvn, not the wrapper).
+ PATH = "${MAVEN_3_LATEST_HOME}:${env.PATH}"
+ }
+ stages {
+ stage('Build Struts & Maven site') {
+ steps {
+ sh '''
+ echo "Building Struts ${STRUTS_TAG} and staging the Maven site"
+
+ rm -rf target/struts
+ git clone https://gitbox.apache.org/repos/asf/struts.git target/struts
+
+ cd target/struts
+ if [ "${STRUTS_TAG}" = "main" ]; then
+ git checkout main
+ else
+ git checkout "tags/${STRUTS_TAG}"
+ fi
+
+ mvn -B -V clean install -DskipTests
+ mvn -B -V site:site site:stage
+ '''
+ }
+ }
+ stage('Publish to source/maven') {
+ steps {
+ sh '''
+ echo "Publishing the staged Maven site into source/maven on main"
+
+ if ! git config remote.asf.url > /dev/null; then
+ git remote add asf https://gitbox.apache.org/repos/asf/struts-site.git
+ fi
+
+ git fetch asf
+ git checkout main
+ git pull asf main
+
+ rm -rf source/maven
+ mkdir -p source/maven
+ mv target/struts/target/staging/* source/maven/
+
+ git add source/maven
+ git status
+
+ git diff --cached --quiet || git commit -m "Updates Maven site by Jenkins"
+ git push asf main
+ '''
+ }
+ }
+ }
+ post {
+ // If this build failed, send an email to the developers.
+ failure {
+ script {
+ emailext(
+ recipientProviders: [[$class: 'DevelopersRecipientProvider']],
+ from: "Mr. Jenkins <je...@builds.apache.org>",
+ subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} failed",
+ body: """
+There is a build failure in ${env.JOB_NAME}.
+
+Build: ${env.BUILD_URL}
+Logs: ${env.BUILD_URL}console
+Changes: ${env.BUILD_URL}changes
+
+--
+Mr. Jenkins
+Director of Continuous Integration
+"""
+ )
+ }
+ }
+ // Send an email, if the last build was not successful and this one is.
+ fixed {
+ script {
+ emailext(
+ recipientProviders: [[$class: 'DevelopersRecipientProvider']],
+ from: 'Mr. Jenkins <je...@builds.apache.org>',
+ subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} back to normal",
+ body: """
+The build for ${env.JOB_NAME} completed successfully and is back to normal.
+
+Build: ${env.BUILD_URL}
+Logs: ${env.BUILD_URL}console
+Changes: ${env.BUILD_URL}changes
+
+--
+Mr. Jenkins
+Director of Continuous Integration
+"""
+ )
+ }
+ }
+ }
+}