From 945633e5bdc917f8743c4c1b0e6e311f6c0f888b Mon Sep 17 00:00:00 2001 From: Relism Date: Mon, 11 May 2026 14:19:54 +0200 Subject: [PATCH] ci: setup CI/CD pipelines, versioning and agent guidelines --- .github/settings.xml | 17 +++ .github/workflows/ci.yml | 47 ++++++ .github/workflows/prepare-release.yml | 69 +++++++++ .github/workflows/release.yml | 136 ++++++++++++++++++ .github/workflows/snapshot.yml | 30 ++++ .gitignore | 3 + AGENTS.md | 118 +++++++++++++++ flash-extensions/flash-ext-data-core/pom.xml | 2 +- .../flash-ext-data-hibernate/pom.xml | 2 +- flash-extensions/flash-ext-data-jdbc/pom.xml | 2 +- flash-extensions/flash-ext-jackson/pom.xml | 2 +- flash-extensions/flash-ext-limiter/pom.xml | 2 +- flash-extensions/flash-ext-oidc/pom.xml | 2 +- flash-extensions/flash-ext-openapi/pom.xml | 2 +- .../flash-ext-routeviewer/pom.xml | 2 +- flash-extensions/flash-ext-view-core/pom.xml | 2 +- flash-extensions/flash-ext-view-jte/pom.xml | 2 +- .../flash-ext-view-thymeleaf/pom.xml | 2 +- .../flash-ext-web-bundler/pom.xml | 2 +- flash-extensions/pom.xml | 2 +- flash/pom.xml | 2 +- pom.xml | 111 +++++++++++++- 22 files changed, 544 insertions(+), 15 deletions(-) create mode 100644 .github/settings.xml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/prepare-release.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/snapshot.yml create mode 100644 AGENTS.md diff --git a/.github/settings.xml b/.github/settings.xml new file mode 100644 index 0000000..bef4174 --- /dev/null +++ b/.github/settings.xml @@ -0,0 +1,17 @@ + + + + Personal + ${env.MAVEN_USERNAME} + ${env.MAVEN_PASSWORD} + + + Personal-snapshots + ${env.MAVEN_USERNAME} + ${env.MAVEN_PASSWORD} + + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d904df8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - master + - 'feature/**' + - 'fix/**' + - 'hotfix/**' + tags-ignore: + - 'v*' + pull_request: + branches: + - master + +jobs: + build: + name: Build & Test + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Temurin 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + server-id: Personal + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: Build and test + run: mvn -B --settings .github/settings.xml clean verify + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Publish test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: '**/target/surefire-reports/*.xml' + retention-days: 7 diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 0000000..4c6086c --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,69 @@ +name: Prepare Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g. 2.0.0)' + required: true + type: string + next_version: + description: 'Next development version without -SNAPSHOT (e.g. 2.1.0)' + required: true + type: string + +jobs: + prepare: + name: Bump, Tag & Push + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Set up Temurin 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Set release version + run: mvn -B --settings .github/settings.xml versions:set -DnewVersion=${{ inputs.version }} + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Commit release version + run: | + git add -A + git commit -m "chore(release): ${{ inputs.version }}" + + - name: Tag release + run: git tag v${{ inputs.version }} + + - name: Set next snapshot version + run: mvn -B --settings .github/settings.xml versions:set -DnewVersion=${{ inputs.next_version }}-SNAPSHOT + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Commit next snapshot version + run: | + git add -A + git commit -m "chore(release): prepare ${{ inputs.next_version }}-SNAPSHOT" + + - name: Push commits and tag + run: | + git push origin master + git push origin v${{ inputs.version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..cbc74bd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,136 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Build, Sign, Deploy & Publish + runs-on: ubuntu-latest + permissions: + contents: write + pages: write + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Extract version from tag + id: version + run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT + + - name: Set up Temurin 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + + - name: Import GPG key + run: | + echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import + GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | grep '^sec' | cut -d: -f5 | head -1) + echo "GPG_KEY_ID=$GPG_KEY_ID" >> $GITHUB_ENV + + - name: Build, sign and deploy to releases + run: | + mvn -B --settings .github/settings.xml \ + -DperformRelease=true \ + -Dgpg.keyname=$GPG_KEY_ID \ + clean deploy + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Generate aggregated JavaDoc + run: | + mvn -B --settings .github/settings.xml \ + -pl flash,flash-extensions -am \ + javadoc:aggregate -DskipTests + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} + + - name: Checkout gh-pages + uses: actions/checkout@v4 + with: + ref: gh-pages + path: gh-pages-out + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Copy JavaDoc to versioned folder + run: | + VERSION=${{ steps.version.outputs.VERSION }} + mkdir -p gh-pages-out/javadoc/$VERSION + cp -r target/reports/apidocs/. gh-pages-out/javadoc/$VERSION/ + rm -rf gh-pages-out/latest + mkdir -p gh-pages-out/latest + cp -r target/reports/apidocs/. gh-pages-out/latest/ + + - name: Regenerate index.html + run: | + cd gh-pages-out + python3 - <<'EOF' + import os, re + + versions = sorted( + [d for d in os.listdir("javadoc") if os.path.isdir(f"javadoc/{d}")], + key=lambda v: [int(x) for x in re.sub(r'[^0-9.]', '', v).split('.') if x], + reverse=True + ) + + rows = "\n".join( + f'
  • {v}
  • ' + for v in versions + ) + + html = f""" + + + + Flash JavaDoc + + + +

    Flash — JavaDoc

    +

    → Latest

    +

    All versions

    + + + """ + + with open("index.html", "w") as f: + f.write(html) + print(f"index.html generated with {len(versions)} versions: {versions}") + EOF + + - name: Push gh-pages + run: | + cd gh-pages-out + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A + git diff --cached --quiet || git commit -m "docs(javadoc): release ${{ steps.version.outputs.VERSION }}" + git push origin gh-pages + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ steps.version.outputs.VERSION }} + name: v${{ steps.version.outputs.VERSION }} + generate_release_notes: true + draft: false + prerelease: false diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..5d1d90c --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,30 @@ +name: Publish Snapshot + +on: + push: + branches: + - master + tags-ignore: + - 'v*' + +jobs: + snapshot: + name: Deploy Snapshot + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Temurin 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + + - name: Deploy snapshot + run: mvn -B --settings .github/settings.xml clean deploy -DskipTests + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/.gitignore b/.gitignore index 6439a65..67d5b27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ target/ +*.versionsBackup +.mvn/timing.properties +*.class !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b37c568 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,118 @@ +# Flash — Agent Guidelines + +This document defines the conventions and rules that all agents (AI or human) must follow +when working on this repository. Read it entirely before making any change. + +--- + +## Git Workflow + +### Branch Naming + +| Type | Pattern | Example | +|------|---------|---------| +| New feature | `feature//` | `feature/ext-oidc/pkce-support` | +| Bug fix | `fix//` | `fix/core/router-npe` | +| Hotfix on released version | `hotfix//` | `hotfix/2.0.1/auth-bypass` | +| CI/infra changes | `feature/ci/` | `feature/ci/add-snapshot-workflow` | + +Rules: +- Always branch from `master`. +- Branch names are lowercase, words separated by `-`. +- Never push directly to `master`. +- Never create `develop`, `release/*`, or any other long-lived branch. + +### Commit Messages — Conventional Commits + +Format: `(): ` + +| Type | When to use | +|------|-------------| +| `feat` | New feature | +| `fix` | Bug fix | +| `refactor` | Code change without feature/fix | +| `test` | Adding or updating tests | +| `docs` | Documentation only | +| `chore` | Build, deps, tooling — no production code | +| `ci` | Changes to GitHub Actions workflows | + +Allowed scopes: `core`, `ext-jackson`, `ext-openapi`, `ext-oidc`, `ext-routeviewer`, +`ext-view-core`, `ext-view-jte`, `ext-view-thymeleaf`, `ext-limiter`, `ext-web-bundler`, +`ext-data-core`, `ext-data-jdbc`, `ext-data-hibernate`, `release`, `deps`, `ci`. + +Examples: +``` +feat(ext-oidc): add PKCE support +fix(core): fix NPE in RouteHandler when path is null +chore(deps): upgrade jackson to 2.18.0 +ci: add timeout to snapshot workflow +chore(release): 2.1.0 +``` + +### Pull Requests + +- Every branch must be merged via PR, never with a direct push. +- PR title must follow Conventional Commits format. +- CI (`ci.yml`) must be green before merging. +- Squash merge is preferred for `feature/*` and `fix/*` to keep history clean. +- Merge commit is preferred for hotfixes (preserves the fix commit intact). + +--- + +## Versioning + +- All modules share a single version defined in the root `pom.xml` (`flash-parent`). +- Never change the version in child POMs — always and only in the parent. +- Current scheme: `MAJOR.MINOR.PATCH` + - MAJOR: breaking API changes + - MINOR: new backward-compatible features + - PATCH: backward-compatible bug fixes on an already-released version +- During development, master always carries a `-SNAPSHOT` version. +- **Never manually edit the version** — versions are bumped exclusively by the + `prepare-release` GitHub Actions workflow. + +### Release Process (for maintainers only) + +1. Ensure `master` is green (CI passing). +2. Go to GitHub Actions → `Prepare Release` → `Run workflow`. +3. Input `version` (e.g. `2.1.0`) and `next_version` (e.g. `2.2.0`). +4. The workflow handles everything: bump, commit, tag, push. +5. The `release` workflow then triggers automatically on the tag. + +--- + +## Maven & Module Structure + +- Root POM: `flash-parent` — defines all dependency versions and plugin config. +- `flash` module: the core framework JAR. +- `flash-extensions` POM: aggregator for all extension modules. +- Extensions live under `flash-extensions/flash-ext-*/`. +- When adding a new extension: + 1. Add the module to `flash-extensions/pom.xml` ``. + 2. Add the dependency to `flash-extensions/pom.xml` ``. + 3. Add the dependency to the root `pom.xml` ``. + 4. Do **not** declare a `` in the new module's POM — it inherits from the parent. + +--- + +## CI/CD Pipelines + +| Workflow | Trigger | What it does | +|----------|---------|--------------| +| `ci.yml` | Push to any branch, PR to master | Compile + test — required gate | +| `snapshot.yml` | Push to `master` | Deploy `-SNAPSHOT` to `maven.relism.dev/snapshots` | +| `prepare-release.yml` | Manual `workflow_dispatch` | Bump version, commit, tag, push | +| `release.yml` | Push of tag `v*` | GPG sign, deploy to `/releases`, JavaDoc to GitHub Pages, GitHub Release | + +**Agents must never manually trigger `prepare-release` or modify version strings.** + +--- + +## What Agents Must NOT Do + +- Push directly to `master` or `gh-pages`. +- Manually edit `` tags in any POM. +- Add new `` or `` entries without explicit instruction. +- Modify `.github/workflows/*.yml` files without explicit instruction. +- Commit generated files (`target/`, `*.class`, `*.versionsBackup`). +- Use `git push --force` on any branch. diff --git a/flash-extensions/flash-ext-data-core/pom.xml b/flash-extensions/flash-ext-data-core/pom.xml index 9ffd101..3fa5807 100644 --- a/flash-extensions/flash-ext-data-core/pom.xml +++ b/flash-extensions/flash-ext-data-core/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-data-core diff --git a/flash-extensions/flash-ext-data-hibernate/pom.xml b/flash-extensions/flash-ext-data-hibernate/pom.xml index 6153e4d..d0389fc 100644 --- a/flash-extensions/flash-ext-data-hibernate/pom.xml +++ b/flash-extensions/flash-ext-data-hibernate/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-data-hibernate diff --git a/flash-extensions/flash-ext-data-jdbc/pom.xml b/flash-extensions/flash-ext-data-jdbc/pom.xml index 1a32111..796bd5c 100644 --- a/flash-extensions/flash-ext-data-jdbc/pom.xml +++ b/flash-extensions/flash-ext-data-jdbc/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-data-jdbc diff --git a/flash-extensions/flash-ext-jackson/pom.xml b/flash-extensions/flash-ext-jackson/pom.xml index 0cddcdb..ab5e348 100644 --- a/flash-extensions/flash-ext-jackson/pom.xml +++ b/flash-extensions/flash-ext-jackson/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-jackson diff --git a/flash-extensions/flash-ext-limiter/pom.xml b/flash-extensions/flash-ext-limiter/pom.xml index 225e10f..23c48cf 100644 --- a/flash-extensions/flash-ext-limiter/pom.xml +++ b/flash-extensions/flash-ext-limiter/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-limiter diff --git a/flash-extensions/flash-ext-oidc/pom.xml b/flash-extensions/flash-ext-oidc/pom.xml index 97742ab..acbb00b 100644 --- a/flash-extensions/flash-ext-oidc/pom.xml +++ b/flash-extensions/flash-ext-oidc/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-oidc diff --git a/flash-extensions/flash-ext-openapi/pom.xml b/flash-extensions/flash-ext-openapi/pom.xml index 62c8c15..1c82efa 100644 --- a/flash-extensions/flash-ext-openapi/pom.xml +++ b/flash-extensions/flash-ext-openapi/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-openapi diff --git a/flash-extensions/flash-ext-routeviewer/pom.xml b/flash-extensions/flash-ext-routeviewer/pom.xml index b1b68d1..36698ad 100644 --- a/flash-extensions/flash-ext-routeviewer/pom.xml +++ b/flash-extensions/flash-ext-routeviewer/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-routeviewer diff --git a/flash-extensions/flash-ext-view-core/pom.xml b/flash-extensions/flash-ext-view-core/pom.xml index da55ba0..b7ba2ca 100644 --- a/flash-extensions/flash-ext-view-core/pom.xml +++ b/flash-extensions/flash-ext-view-core/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-view-core diff --git a/flash-extensions/flash-ext-view-jte/pom.xml b/flash-extensions/flash-ext-view-jte/pom.xml index b6c7a0e..1debbab 100644 --- a/flash-extensions/flash-ext-view-jte/pom.xml +++ b/flash-extensions/flash-ext-view-jte/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-view-jte diff --git a/flash-extensions/flash-ext-view-thymeleaf/pom.xml b/flash-extensions/flash-ext-view-thymeleaf/pom.xml index a12783f..84c2bcc 100644 --- a/flash-extensions/flash-ext-view-thymeleaf/pom.xml +++ b/flash-extensions/flash-ext-view-thymeleaf/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-view-thymeleaf diff --git a/flash-extensions/flash-ext-web-bundler/pom.xml b/flash-extensions/flash-ext-web-bundler/pom.xml index dcdec5b..113eb8b 100644 --- a/flash-extensions/flash-ext-web-bundler/pom.xml +++ b/flash-extensions/flash-ext-web-bundler/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-extensions - 1.1-indev6 + 2.0.0-SNAPSHOT flash-ext-web-bundler diff --git a/flash-extensions/pom.xml b/flash-extensions/pom.xml index c3020fc..5e024ce 100644 --- a/flash-extensions/pom.xml +++ b/flash-extensions/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-parent - 1.1-indev6 + 2.0.0-SNAPSHOT flash-extensions diff --git a/flash/pom.xml b/flash/pom.xml index f9e102a..e3cc907 100644 --- a/flash/pom.xml +++ b/flash/pom.xml @@ -7,7 +7,7 @@ dev.relism flash-parent - 1.1-indev6 + 2.0.0-SNAPSHOT flash diff --git a/pom.xml b/pom.xml index d88505a..2094dd3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.relism flash-parent - 1.1-indev6 + 2.0.0-SNAPSHOT pom @@ -19,6 +19,10 @@ Personal https://maven.relism.dev/releases + + Personal-snapshots + https://maven.relism.dev/snapshots + @@ -27,6 +31,10 @@ UTF-8 1.18.44 2.0.16 + 3.11.2 + 3.3.1 + 3.2.8 + 2.18.0 @@ -141,8 +149,109 @@ + + org.apache.maven.plugins + maven-source-plugin + ${maven.source.plugin.version} + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc.plugin.version} + + ${maven.compiler.source} + ${project.build.sourceEncoding} + none + true + + + + org.apache.maven.plugins + maven-gpg-plugin + ${maven.gpg.plugin.version} + + + org.codehaus.mojo + versions-maven-plugin + ${maven.versions.plugin.version} + + false + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + + + attach-artifacts + + + src/main/java + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + verify + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + verify + + jar + + + + + + + + + sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + + + +