Skip to content

ci(maven): publish artifacts to BunnyCDN S3 instead of Artifactory - #37568

Open
wezell wants to merge 12 commits into
mainfrom
issue-37567-artifactory-to-bunny-s3
Open

wezell wants to merge 12 commits into
mainfrom
issue-37567-artifactory-to-bunny-s3

Conversation

@wezell

@wezell wezell commented Sep 16, 2026

Copy link
Copy Markdown
Member

Summary

Replaces JFrog Artifactory (repo.dotcms.com) with the S3-compatible BunnyCDN storage zone for all Maven/artifact publishing, so this PR can be exercised against the new repository before DNS/cutover.

  • Endpoint: https://ny-s3.storage.bunnycdn.com (region ny)
  • Public: https://dotcms-repo.b-cdn.net/libs-release/...
  • Secrets: MAVEN_BUNNY_RW_USERNAME (storage-zone name = S3 access key id), MAVEN_BUNNY_RW_PASSWORD

Refs #37567 (tracking issue — intentionally not Closes, there is remaining work).

How publishing works now

  1. The build/release installs artifacts locally (mvn install instead of mvn deploy).
  2. .github/scripts/publish-to-s3/publish.sh maven --version <v> walks ~/.m2/repository/com/dotcms/*/<v>/, uploads each subtree to s3://$BUCKET/$PREFIX/com/dotcms/<artifactId>/<version>/ (key prefixes are created implicitly), writes .sha1/.md5 checksums, and regenerates maven-metadata.xml (Artifactory used to; the dotCLI action reads it).
  3. file mode uploads single artifacts (starter zips): .../com/dotcms/starter/<date>/starter-<date>.zip.

Changes

  • New: .github/scripts/publish-to-s3/publish.sh (+ README), deploy-maven-s3 composite action (+ README).
  • Workflows: cicd_comp_release-phase.yml (mvn deploymvn install + S3 publish; removed Artifactory Maven settings), cicd_comp_deployment-phase.yml (deploy-jfrogdeploy-maven-s3, restricted to dotcms-cli), cicd_manual_publish-starter.yml, legacy-release_maven-release-process.yml, and callers (cicd_3/4/6/7/8). Secrets EE_REPO_*MAVEN_BUNNY_RW_*.
  • Removed: deploy-jfrog action.
  • POMs: pom.xml / parent/pom.xml download repositories → https://dotcms-repo.b-cdn.net/libs-release; dropped Artifactory distributionManagement and the dead libs-snapshot repository/pluginRepository entries.
  • Snapshots: publish.sh refuses -SNAPSHOT by default (not consumed at dotCMS, and it would make maven-metadata.xml <latest> a snapshot).
  • Consumers/docs: dotCLI action workflow, SDK scaffold docker-compose.yml, docker examples, onboarding docs.

Configuration

Org secrets: MAVEN_BUNNY_RW_USERNAME, MAVEN_BUNNY_RW_PASSWORD.
Optional repo variables (defaults in the script): MAVEN_S3_BUCKET (defaults to the username), MAVEN_S3_PREFIX (libs-release), MAVEN_S3_ENDPOINT, MAVEN_S3_REGION, MAVEN_S3_PUBLIC_URL.

Testing

  • Script exercised against a mocked aws CLI: upload targets/exclusions, checksum staging contents, maven-metadata.xml generation with semantic version sort, dry-run, file mode + $GITHUB_OUTPUT, missing-module warnings, snapshot refusal, credential export, temp-dir cleanup.
  • All changed YAML parsed. CI will exercise the new repository end-to-end on this PR.

Notes / follow-ups

Migrate every CI/CD Maven/artifact publish path off JFrog Artifactory
(repo.dotcms.com) and onto the S3-compatible BunnyCDN storage zone.

- Add .github/scripts/publish-to-s3/publish.sh (maven + file modes): uploads
  from ~/.m2/repository, writes .sha1/.md5 checksums, and regenerates the
  maven-metadata.xml files Artifactory used to create.
- Add the deploy-maven-s3 composite action; deployment and release phases now
  `mvn install` locally and publish from the local repository.
- Publish starter zips through the same script.
- Remove the deploy-jfrog action.
- Point the poms at https://dotcms-repo.b-cdn.net/libs-release, drop the
  Artifactory distributionManagement and the dead libs-snapshot repositories.
- Refuse to publish shared snapshots (not consumed at dotCMS).
- Update in-repo consumers (dotCLI action, SDK scaffold, docker examples) and docs.

Refs #37567
@wezell
wezell requested a review from a team as a code owner September 16, 2026 12:20
@github-actions github-actions Bot added Area : Backend PR changes Java/Maven backend code Area : CI/CD PR changes GitHub Actions/workflows Area : CLI PR changes dotCMS CLI code Area : Documentation PR changes documentation files Area : Frontend PR changes Angular/TypeScript frontend code Area : SDK PR changes SDK libraries labels Sep 16, 2026
@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Claude finished @wezell's task in 3m 13s —— View job


PR Review — BunnyCDN S3 publishing

Reviewed the latest state (through 26075134) against origin/main, rechecked every prior finding, and read the new CLI-release / metadata commits.

New Issues

None that are new to the latest commits. The one substantive open item is the metadata concern raised in @sfreudenthaler's CHANGES_REQUESTED, tracked below.

Existing

  • 🟡 Medium: .github/scripts/publish-to-s3/publish.sh:218-223update_artifact_metadata computes <latest>/<release> with no upper/sanity bound. The stray test artifact already in the zone (dotcms-cli/99.12.31-98/) has no letter qualifier, so it survives the grep -v -- '-[A-Za-z]' filter and, being highest under sort -V, becomes both <latest> and <release> on the next dotcms-cli publish. Today <release> is still correctly 26.09.14-01; the first real publish through this code path will regress it to 99.12.31-98, and tools/dotcms-cli/action/.github/workflows/main.yml:24 resolves string(//versioning/latest), so the public dotCLI action would then hand users a test build. This is @sfreudenthaler's blocking comment and is unaddressed in code. Two parts:

    1. Delete the 99.12.31-98 tree from the storage zone before cutover (data cleanup, outside this diff).
    2. Add a defensive bound so a bogus version can't be promoted to <latest>/<release>.

    Fix this →

Resolved

  • publish.sh:59-66 — Bunny creds now override any inherited AWS_* and drop AWS_SESSION_TOKEN/AWS_SECURITY_TOKEN (prior P1 credential shadowing).
  • publish.sh:218-223<latest>/<release> computed from unqualified versions only, so a -java25 variant can't become the default (prior P2). (The 99.12.31-98 case above is a separate gap in the same block — the qualifier filter doesn't catch a bogus plain version.)
  • publish.sh:205-209aws s3 ls failure now leaves existing maven-metadata.xml untouched instead of truncating to a single version. Verified the real path is unaffected: artifacts are uploaded (line 346) before metadata rebuild (line 353), so the $base/ prefix always has objects and ls returns 0.
  • publish.sh:245-256 — metadata .sha1/.md5 now written and uploaded (prior Medium).
  • publish.sh:120-125 — dry-run falls back to dry-run-bucket, no more s3:///… (prior Medium).
  • publish.sh:399-410file mode now writes .sha1/.md5 sidecars, matching maven mode.
  • publish.sh:322-333cmd_maven now dies when --modules was given explicitly and none exist; the no-modules case still warns + exits 0. So the now-fatal CLI Deploy step can't pass while publishing nothing (prior P2 silent no-op).
  • cicd_release-cli.yml:194 — runner-jar/zip S3 publish is if: always() && github.event.inputs.dry-run != 'true' (prior P1/P2 dry-run).
  • tools/dotcms-cli/jreleaser.yml + pom.xml — the Artifactory uploader is gone entirely and JReleaser now runs release (not full-release), so the CLI release job no longer hard-depends on libs-release-local (@sfreudenthaler's second concern). The runner jar + native zips are published to S3 explicitly.
  • WORKFLOW_ARCHITECTURE.md:732 — now reads dotcms-repo.b-cdn.net.
  • pom.xml:46-56 / parent/pom.xml — Artifactory distributionManagement and dead libs-snapshot entries dropped; download repos repointed to dotcms-repo.b-cdn.net/libs-release.

One process note (not blocking, already acknowledged in-thread): CI on this PR builds every com.dotcms module in-reactor, so the new <repositories> endpoint is only validated structurally — Maven never actually resolves through dotcms-repo.b-cdn.net here. End-to-end validation of the new zone still rests on a real release.
· issue-37567-artifactory-to-bunny-s3

Note: I review code and provide feedback but cannot submit formal GitHub PR approvals.

@dotCMS dotCMS deleted a comment from github-actions Bot Sep 16, 2026
@wezell wezell added the PR : dotbot review Trigger dotbot AI code review on this PR label Sep 16, 2026
aws s3 ls prints file entries as '<date> <time> <size> <name>', so
awk '{print $2}' picked up the timestamp column and merged times into the
version list on every publish after the first, corrupting <latest>/<release>.

Also:
- publish .sha1/.md5 for maven-metadata.xml (Artifactory parity;
  checksumPolicy=fail consumers)
- give dry-runs a placeholder bucket instead of producing s3:///... URLs
- drop continue-on-error from the CLI Deploy step so a failed S3 publish is
  visible (snapshots no-op before credentials are required)

Refs #37567
@wezell

wezell commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

Thanks @claude[bot] — the High finding was real and is fixed in 87c60bd.

🟠 High — aws s3 ls timestamp column (fixed). Correct: aws s3 ls prints object lines as <date> <time> <size> <name>, so awk '{print $2}' read the timestamp. My only test fixture emitted PRE lines, which is why it slipped through. Now awk '$1 == "PRE" {print $2}', with a comment explaining why. Re-tested against output that includes both PRE dirs and maven-metadata.xml/.sha1/.md5 file lines — the version list stays clean and <latest>/<release> are correct.

🟡 Medium — metadata checksums (fixed). update_artifact_metadata now writes and uploads maven-metadata.xml.sha1/.md5 too.

🟡 Medium — dry-run with no bucket (fixed). require_credentials falls back to a dry-run-bucket placeholder so dry-runs no longer build s3:///….

🟡 Medium — continue-on-error on CLI Deploy (fixed). Removed. It was pre-existing, but you're right that the failure mode changed to "artifact silently missing". It's now safe to remove because trunk/nightly publish snapshots, and publish-to-s3 rejects -SNAPSHOT before requiring credentials, so the step only runs for real releases and only fails when a release publish is genuinely broken.

link-issue check — the linked tracking issue now carries a Team : * label; the check should pass on this push.

Comment thread .github/scripts/publish-to-s3/publish.sh Outdated
@wezell wezell added the CI : No Build Cache Skip the shared S3 Maven build cache for this PR; build everything from source label Sep 16, 2026
Comment thread .github/scripts/publish-to-s3/publish.sh
Comment thread tools/dotcms-cli/action/.github/workflows/main.yml
… <latest>

- Bunny keys now override any AWS_* credentials already in the environment
  (the release job configures AWS creds for the Javadoc upload), and inherited
  session tokens are unset so Bunny accepts the request.
- Compute maven-metadata <latest>/<release> from unqualified versions only.
  GNU sort -V ranks 26.09.14-01-java25 after 26.09.14-01, but Maven's
  ComparableVersion ranks the qualifier first; without this a Java-variant
  release would become the <latest> the dotCLI action downloads.

Refs #37567

@dotCMS-Machine-User dotCMS-Machine-User left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ dotbot review: all reviewer models (meta/muse-spark-1.3, deepseek/deepseek-v4.1-flash) agree — patch is correct.

approved automatically by dotbot

tools/dotcms-cli/action resolves dotcms-cli-<v>-runner.jar from the S3
repository, but that key was only guaranteed by the JReleaser Artifactory
upload. Publish it from the restored maven-repo with publish.sh file so the
action's S3 URL is valid independently of the JReleaser migration (#37567).

Refs #37567
@wezell

wezell commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

Addressed the remaining CLI Medium and a housekeeping note:

  • 🟡 Medium — dotCLI runner jar (tools/dotcms-cli/action/.github/workflows/main.yml:25) — fixed in d7f7d0f. cicd_release-cli.yml now publishes the runner jar to S3 explicitly after JReleaser, from the restored maven-repo:
    publish.sh file --key com/dotcms/dotcms-cli/<v>/dotcms-cli-<v>-runner.jar.
    It fails loudly if the jar is missing, so the action's S3 URL no longer depends on the still-Artifactory JReleaser upload. The runner jar being present in ~/.m2 is exactly why jreleaser.yml:50 can read it from {{m2Dir}}; the new step makes that explicit rather than implied.
  • Non-blocking noteplain is now declared local in update_artifact_metadata (f95f289).

Does CI exercise the new endpoint? (No — and that's worth knowing before cutover)

I pulled the full PR Build / Initial Artifact Build job log (run 35100915969) and it contains zero Downloading from lines and zero dotcms-repo.b-cdn.net mentions. The run restored Linux-mavencore-<hash> and builds every com.dotcms module in-reactor, so Maven never needed the new repository.

The POM <repositories> change is therefore only validated structurally here (the build still succeeds with it). If we want this PR to actually exercise dotcms-repo.b-cdn.net, we should add a deliberate probe — e.g. a step that resolves a real published artifact through Maven (./mvnw -q dependency:get -Dartifact=com.dotcms:dotcms-core:26.09.14-01) or curl -fsSI a known object. Happy to add that if you want it in this PR.

Comment thread .github/workflows/cicd_release-cli.yml Outdated
Comment thread .github/workflows/cicd_release-cli.yml Outdated
A workflow_dispatch with dry-run=true must not write to the public repo.
Keep always() so a failure of the legacy JReleaser/Artifactory upload
(#37567) cannot suppress the now-authoritative S3 publish; the size check
still fails fast if the runner jar is absent.

@dotCMS-Machine-User dotCMS-Machine-User left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ dotbot review: all reviewer models (meta/muse-spark-1.3, deepseek/deepseek-v4.1-flash) agree — patch is correct.

approved automatically by dotbot

@sfreudenthaler

Copy link
Copy Markdown
Member

@wezell was this tested at all in dotcms/core-workflows-test repo?

@wezell

wezell commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

@wezell was this tested at all in dotcms/core-workflows-test repo?

@sfreudenthaler it was not but the build of a new dotcms jar was executed in this pipeline which relied on the new infrastructure - and full builds work locally (they give checksum warnings but I am fixing that out of the scope of this pr).

@sfreudenthaler sfreudenthaler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apparently there’s a bug hidden cuz we copied over some cruft (eg dotcms-cli-99.12.31-98).

https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/maven-metadata.xml
  <latest>99.12.31-98</latest>
  <release>26.09.14-01</release>

99.12.31-98/dotcms-cli-99.12.31-98-runner.jar → HTTP 200, 39,082,293 bytes. It's a real published test artifact (negative control on a bogus version returns 302, so the 200 is meaningful).

tools/dotcms-cli/action/.github/workflows/main.yml:24 reads string(//versioning/latest). So the public dotCLI action hands users a test build today. That's inherited from Artifactory's generated metadata, which got copied into the bucket.

The PR makes it permanent: publish.sh:211 filters on -[A-Za-z], and 99.12.31-98 has no letters, so it survives. Verified:

$ printf '24.05.10\n26.09.14-01\n99.12.31-98\n' | sort -u -V | grep -v -- '-[A-Za-z]' | tail -n1

99.12.31-98
Next CLI publish sets to 99.12.31-98 too — currently is still correct at 26.09.14-01, so this actively makes it worse. Delete the 99.12.31-98 tree from the bucket before cutover, and consider a sanity bound in update_artifact_metadata.

There also is some concern over

libs-release-local is still a hard dependency of the CLI release job

cicd_release-cli.yml:176-189 + tools/dotcms-cli/jreleaser.yml:84-85 (a file this PR doesn't touch): upload.artifactory is active: ALWAYS with a libs-release-local RELEASE path, and the step has no continue-on-error. The if: always() on the S3 step means the jar still publishes, but the job goes red the day Artifactory is switched off — which is the point of #37567. The native zips are fine (they also go to a GitHub Release via jreleaser.yml:26-30). Needs a tracking issue, and probably continue-on-error: true in the interim.

Comment thread .github/scripts/publish-to-s3/publish.sh
cicd_manual_publish-starter.yml uses 'publish.sh file', which only uploaded
the zip, so every starter published after the migration would have repeated
the missing-checksum hole. Write .sha1/.md5 beside the key, matching maven
mode, with --no-checksums to opt out.

Refs #37567
Reviewer nit: the old name reads as AWS S3. Make the Bunny target explicit
in the action directory and display name.

Refs #37567
…s to S3

EE_REPO_* is gone, so jreleaser:full-release would fail on the Artifactory
upload. Remove upload.artifactory from jreleaser.yml (JReleaser now only
creates the GitHub release) and publish the runner jar + native zips to the
S3 repository via publish.sh file, at the same com/dotcms/dotcms-cli/<v>/ path.

Refs #37567
Comment thread .github/workflows/cicd_comp_deployment-phase.yml
Comment thread .github/workflows/WORKFLOW_ARCHITECTURE.md Outdated
We no longer upload via JReleaser (S3 handles it) and there is no Artifactory
uploader, so run the release goal to create/update the GitHub release only.

Refs #37567
The deployment-phase CLI Deploy step is fatal now, but 'maven --modules
dotcms-cli' only warned and returned 0 when the directory was missing, so a
release could report success while publishing nothing. If --modules was given
and none match, error out; the no-modules case still warns and exits 0.

Also fix a stale repo.dotcms.com reference in WORKFLOW_ARCHITECTURE.md.

Refs #37567

@dotCMS-Machine-User dotCMS-Machine-User left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ dotbot review: all reviewer models (meta/muse-spark-1.3, deepseek/deepseek-v4.1-flash) agree — patch is correct.

approved automatically by dotbot

update_artifact_metadata swallowed aws s3 ls errors, so a transient listing
failure after a successful artifact publish would rebuild maven-metadata.xml
from an empty version list and overwrite the existing file with a single
version, silently dropping every prior <version> and resetting
<latest>/<release>. Capture the ls status and leave the last-good metadata in
place on failure.

Also fix the remaining repo.dotcms.com reference in WORKFLOW_ARCHITECTURE.md.

Refs #37567
@wezell

wezell commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

Both fixed in 26075134:

  • 🟡 update_artifact_metadata swallowing aws s3 ls errors — now captures the ls exit status and, on failure, warns and returns without touching maven-metadata.xml, leaving the last-good file in place. Verified: with ls failing, the artifact + checksums still upload and there are 0 metadata writes.
  • 🟡 WORKFLOW_ARCHITECTURE.md:765repo.dotcms.comdotcms-repo.b-cdn.net.

On the 99.12.31-98 note: agreed it's bucket data, not code. The -[A-Za-z] filter can't drop it, and I'd rather not add a value-based sanity bound (it would be guessing at version ranges). The cleaner fixes are: (a) delete the test trees (com/dotcms/dotcms-cli/{99.12.31-98,99.12.31_99,v26.02.23-01,…}) before cutover, and/or (b) make the dotCLI action resolve versioning/release instead of versioning/latestlatest is defined to include snapshots/qualifiers, so <release> is the right field for "give me the current CLI". Happy to do (b) in this PR or a follow-up.

@github-actions

Copy link
Copy Markdown
Contributor

dotbot code review:

  • Reviewer: meta/muse-spark-1.3 (medium)
  • Overall: patch is correct
  • New findings this run: 0
  • Prior unresolved dotbot findings still relevant: 0
  • Active findings total: 0

Incremental change hardens metadata regeneration against failed S3 listings and fixes a stale doc URL; no new defects introduced.

Tip: comment with "/dotbot address comments" to attempt automated fixes for unresolved review threads.

reviewed by dotbot · meta/muse-spark-1.3 · medium

@github-actions

Copy link
Copy Markdown
Contributor

dotbot code review:

  • Reviewer: deepseek/deepseek-v4.1-flash (medium)
  • Overall: patch is correct
  • New findings this run: 0
  • Prior unresolved dotbot findings still relevant: 0
  • Active findings total: 0

The incremental commit makes update_artifact_metadata fail-safe: if aws s3 ls errors it warns and returns without overwriting the existing maven-metadata.xml, avoiding truncation to a single version, and the previously flagged module-absent and stale Artifactory references remain fixed. The plain aws s3 ls on an empty prefix still exits 0, so first-time metadata generation is unaffected.

Tip: comment with "/dotbot address comments" to attempt automated fixes for unresolved review threads.

reviewed by dotbot · deepseek/deepseek-v4.1-flash · medium

@dotCMS-Machine-User dotCMS-Machine-User left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ dotbot review: all reviewer models (meta/muse-spark-1.3, deepseek/deepseek-v4.1-flash) agree — patch is correct.

approved automatically by dotbot

@wezell
wezell enabled auto-merge September 16, 2026 19:14

@sfreudenthaler sfreudenthaler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's see it in action and adjust as needed.

Excited for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : Backend PR changes Java/Maven backend code Area : CI/CD PR changes GitHub Actions/workflows Area : CLI PR changes dotCMS CLI code Area : Documentation PR changes documentation files Area : Frontend PR changes Angular/TypeScript frontend code Area : SDK PR changes SDK libraries CI : No Build Cache Skip the shared S3 Maven build cache for this PR; build everything from source PR : dotbot review Trigger dotbot AI code review on this PR

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants