Skip to content
Merged
Show file tree
Hide file tree
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
342 changes: 342 additions & 0 deletions .claude/skills/release/SKILL.md

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,13 @@ updates:
semver-major-days: 7
semver-minor-days: 3
semver-patch-days: 1

# Bumps third-party actions pinned by SHA. The cuioss-organization workflow pins are NOT updated
# here but by the cuioss-release-bot (org release, consumers list), so this lane is idle until a
# workflow uses another action. Add a docker lane per digest-pinned Dockerfile directory likewise.
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 3
8 changes: 6 additions & 2 deletions .github/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
name: cui-java-module-template
description: Template for cuioss Java modules

# MERGING A CHANGE OF current-version IS A RELEASE to Maven Central (central version-changed guard
# in reusable-maven-release.yml). Never change it while customizing or in an ordinary PR:
# 0.1.0 is the first release of a derived repository, cut deliberately via workflow_dispatch.
# Later versions go through the release runbook (.claude/skills/release/SKILL.md).
release:
current-version: 1.0.0
next-version: 1.1.0-SNAPSHOT
current-version: 0.1.0
next-version: 0.1.1-SNAPSHOT
create-github-release: true

maven-build:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
# branch; without it, queued PRs stay CLEAN but never merge (queue times out).
merge_group:
push:
branches: [main, "feature/*", "fix/*", "chore/*", "dependabot/**"]
branches: [main, "feature/*", "fix/*", "chore/*", "release/*", "dependabot/**"]
pull_request:
branches: [main]
workflow_dispatch:
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@
**/.vscode
.DS_Store
.asciidoctorconfig.adoc
.factorypath

# Planning system (managed by plan-marshall)
# Runtime state (plans, run-configuration, lessons-learned, memory, logs — managed by plan-marshall)
.plan/*
!.plan/marshal.json
!.plan/project-architecture/
17 changes: 15 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,24 @@ All cuioss repositories have branch protection on `main`. Direct pushes to `main
2. Commit changes: `git add <files> && git commit -m "<message>"`
3. Push the branch: `git push -u origin <branch-name>`
4. Create a PR: `gh pr create --repo cuioss/cui-java-module-template --head <branch-name> --base main --title "<title>" --body "<body>"`
5. Wait for CI + Gemini review (waits until checks complete): `gh pr checks --watch`
6. **Handle Gemini review comments** — fetch with `gh api repos/cuioss/cui-java-module-template/pulls/<pr-number>/comments` and for each:
5. Wait for CI + review bots (waits until checks complete): `gh pr checks --watch`
6. **Handle review comments** — fetch with `gh api repos/cuioss/cui-java-module-template/pulls/<pr-number>/comments` and for each:
- If clearly valid and fixable: fix it, commit, push, then reply explaining the fix and resolve the comment
- If disagree or out of scope: reply explaining why, then resolve the comment
- If uncertain (not 100% confident): **ask the user** before acting
- Every comment MUST get a reply (reason for fix or reason for not fixing) and MUST be resolved
7. Do **NOT** enable auto-merge unless explicitly instructed. Wait for user approval.
8. Return to main: `git checkout main && git pull`

## Releases

Merging a change of `release.current-version` in `.github/project.yml` **is** a Maven Central
release: the central version-changed guard of `reusable-maven-release.yml` publishes whenever the
value differs from the merge commit's first parent and is untagged. Maven Central releases cannot be
withdrawn. Never change it in an ordinary PR (not while customizing either); releases go through the
runbook `.claude/skills/release/SKILL.md`. Do not rewrite the `github.repository` literal in
`.github/workflows/release.yml`: it only excludes the template repository itself.

## Temporary Files

Use `.plan/temp/` for all temporary and generated files.
44 changes: 41 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,35 @@ The key must *not* contain spaces. They are used for creating urls as well.

* `README.adoc` -> the badges on top
* `pom.xml`
* `SECURITY.adoc`
* `.github/project.yml`
* `.github/project.yml` -> `name`, `description`, `sonar.project-key`, `pages.reference` only
* `CLAUDE.md`, `.claude/skills/release/SKILL.md` -> the repository slug
* `src/site/site.xml`
* `src/site/asciidoc/about.adoc`

[WARNING]
====
Do *not* touch `release.current-version` in `.github/project.yml`, and do *not* replace
`cuioss/cui-java-module-template` in `.github/workflows/release.yml` (it only excludes this template
from releasing). See <<releasing>>.
====

=== Credentials

All secrets (GPG, Sonatype, Sonar, Pages, Release App) are managed at the https://github.com/cuioss/cuioss-organization[cuioss organization level] and inherited automatically via `secrets: inherit` in the reusable workflows. No repo-level secrets need to be configured.
All secrets (GPG, Sonatype, Sonar, Release App) are managed at the https://github.com/cuioss/cuioss-organization[cuioss organization level]. The caller workflows pass them explicitly to the reusable workflows; pass only the secrets a reusable workflow declares, an undeclared one makes every run end in `startup_failure`. No repo-level secrets need to be configured.

=== After creating the repository

* *cuioss-organization*: add the repository to `consumers:` in
https://github.com/cuioss/cuioss-organization/blob/main/.github/project.yml[`.github/project.yml`],
so every org workflow release opens the pin-bump PR here. Apply repository settings and branch
protection (merge queue) with the org's `repo-settings` and `branch-protection` scripts.
* *SonarCloud*: create the project `cuioss_<key>`. New projects start with a main branch called
`master`; rename it to `main` (Administration -> Branches and Pull Requests) *before* the first
analysis. Otherwise `main` is analysed as a short-lived branch and the overview stays empty. If it
already happened: delete the short-lived `main`, then rename `master`. Set New Code to "Previous
version". The first analysis of the renamed branch reports quality gate `NONE` (no baseline yet),
which fails `sonar.qualitygate.wait`; the next analysis is green.
* *Release*: leave `release.current-version` alone, see <<releasing>>.

=== Further Steps

Expand Down Expand Up @@ -108,3 +129,20 @@ The script automatically derives additional properties:
* `project.scm.url` - SCM URL based on the project key
* `project.pages.url` - GitHub Pages URL based on the project key
* `project.sonar.id` - Sonar ID based on the project key

[#releasing]
== Releasing

Merging a change of `release.current-version` in `.github/project.yml` *is* a release: the central
guard in `reusable-maven-release.yml` publishes to Maven Central whenever that value differs from the
merge commit's first parent and no tag for it exists. Maven Central releases cannot be withdrawn.
Every other `project.yml` edit reaches the release workflow too and is refused by the guard.

* This template declares `current-version: 0.1.0` together with `0.1.0-SNAPSHOT` in `pom.xml`, so a
new repository never has to touch the value. Its first release is a deliberate
`workflow_dispatch` from `main`.
* Every later release goes through the runbook `.claude/skills/release/SKILL.md`: a dedicated
`chore/release_<version>` PR that changes nothing but the version, merged only after the pre-cut
checks.
* The release workflow excludes this template repository itself, so it never publishes
`cui-java-module-template`.
7 changes: 4 additions & 3 deletions customization.properties
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Project customization properties

# Used in pom.xml (artifactId), README.adoc (badges), .github/project.yml (name, pages-reference) src/site/site.xml (links), SECURITY.md (links)
# Used in pom.xml (artifactId), README.adoc (badges), .github/project.yml (name, pages reference, sonar project-key),
# src/site/site.xml (links), CLAUDE.md and .claude/skills/release/SKILL.md (repository slug)
project.key=test-java-module

# Used in pom.xml (<n> tag)
# Used in pom.xml (<name> tag)
project.name=Test Java Module

# Used in pom.xml (<description> tag)
# Used in pom.xml (<description> tag) and .github/project.yml (description)
project.description=This is a test module for testing customization.

# Used in pom.xml (property maven.jar.plugin.automatic.module.name)
Expand Down
32 changes: 22 additions & 10 deletions customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ replace_in_file() {

# Update pom.xml
replace_in_file "pom.xml" "<artifactId>cui-java-module-template</artifactId>" "<artifactId>${PROJECT_KEY}</artifactId>"
replace_in_file "pom.xml" "<n>cui java module template</n>" "<n>${PROJECT_NAME}</n>"
replace_in_file "pom.xml" "<name>cui java module template</name>" "<name>${PROJECT_NAME}</name>"
replace_in_file "pom.xml" "<description>Template module for cuioss open source projects." "<description>${PROJECT_DESCRIPTION}"
replace_in_file "pom.xml" "<inceptionYear>2023</inceptionYear>" "<inceptionYear>${PROJECT_INCEPTION_YEAR}</inceptionYear>"
replace_in_file "pom.xml" "<maven.jar.plugin.automatic.module.name>de.cuioss.template</maven.jar.plugin.automatic.module.name>" "<maven.jar.plugin.automatic.module.name>${PROJECT_MODULE_NAME}</maven.jar.plugin.automatic.module.name>"
Expand All @@ -90,26 +90,38 @@ replace_in_file "README.adoc" "maven-central/v/de.cuioss/" "maven-central/v/${PR
replace_in_file "README.adoc" "central.sonatype.com/artifact/de.cuioss/" "central.sonatype.com/artifact/${PROJECT_GROUP_ID}/"
replace_in_file "README.adoc" "cuioss_cui-java-module-template" "${PROJECT_SONAR_ID}"

# Update SECURITY.md
replace_in_file "SECURITY.md" "cuioss/cui-java-module-template" "cuioss/${PROJECT_KEY}"

# Update .github/project.yml
replace_in_file ".github/project.yml" "name: cui-java-module-template" "name: ${PROJECT_KEY}"
replace_in_file ".github/project.yml" "pages-reference: cui-java-module-template" "pages-reference: ${PROJECT_KEY}"
replace_in_file ".github/project.yml" "sonar-project-key: cuioss_cui-java-module-template" "sonar-project-key: ${PROJECT_SONAR_ID}"
# Only name, description, sonar and pages keys. NEVER release.current-version: merging a change of
# it is a Maven Central release (see the comment in .github/project.yml).
replace_in_file ".github/project.yml" "^name: cui-java-module-template$" "name: ${PROJECT_KEY}"
replace_in_file ".github/project.yml" "^description: Template for cuioss Java modules$" "description: ${PROJECT_DESCRIPTION}"
replace_in_file ".github/project.yml" "project-key: cuioss_cui-java-module-template" "project-key: ${PROJECT_SONAR_ID}"
replace_in_file ".github/project.yml" "reference: cui-java-module-template" "reference: ${PROJECT_KEY}"

# Update CLAUDE.md and the release runbook (repository slug only).
# .github/workflows/release.yml is deliberately NOT touched: its template-repository exclusion must
# keep naming cuioss/cui-java-module-template, otherwise the new repository could never release.
replace_in_file "CLAUDE.md" "cuioss/cui-java-module-template" "cuioss/${PROJECT_KEY}"
# Only the `--repo` arguments: the template-exclusion literal quoted in the runbook must stay.
replace_in_file ".claude/skills/release/SKILL.md" "repo cuioss/cui-java-module-template" "repo cuioss/${PROJECT_KEY}"

# Update site.xml
replace_in_file "src/site/site.xml" "https://github.com/cuioss/cui-java-module-template" "${PROJECT_SCM_URL}"

# Update module-info.java if module name changed
if [ "${PROJECT_MODULE_NAME}" != "de.cuioss.template" ]; then
replace_in_file "src/main/java/module-info.java" "module de.cuioss.template" "module ${PROJECT_MODULE_NAME}"
# Also update the exports statement if needed
replace_in_file "src/main/java/module-info.java" "exports de.cuioss.template;" "exports ${PROJECT_MODULE_NAME};"
# The exported package stays de.cuioss.template until you move the sources; rename both together.
fi

echo "Customization completed successfully!"
echo ""
echo "Next steps (see README.adoc, 'After creating the repository'):"
echo " - Do NOT change release.current-version in .github/project.yml: merging that change IS a release."
echo " - SonarCloud: create ${PROJECT_SONAR_ID} and rename its main branch 'master' to 'main' before the first analysis."
echo " - Add ${PROJECT_KEY} to 'consumers:' in cuioss-organization/.github/project.yml."
echo " - Apply branch protection / merge queue with cuioss-organization/branch-protection."
echo ""
echo "To reset to original values, you can use Git to revert changes:"
echo " git checkout -- pom.xml README.adoc SECURITY.md .github/project.yml src/site/site.xml src/main/java/module-info.java"
echo " git checkout -- pom.xml README.adoc CLAUDE.md .claude/skills/release/SKILL.md .github/project.yml src/site/site.xml src/main/java/module-info.java"
echo "And then run this script again with the desired values in customization.properties."
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<relativePath/>
</parent>
<artifactId>cui-java-module-template</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- Must be declared: <inceptionYear> is inherited, and the license plugin binds the
copyright ${year} to it. Without this, a new project reports cui-parent-pom's 2022
Expand Down
Loading