From 9066c98cd4a1c7390e28045a59c621917f7230fc Mon Sep 17 00:00:00 2001 From: Will Ezell Date: Wed, 16 Sep 2026 08:20:03 -0400 Subject: [PATCH 01/12] ci(maven): publish artifacts to BunnyCDN S3 instead of Artifactory 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 --- .../deployment/deploy-jfrog/README.md | 43 -- .../deployment/deploy-jfrog/action.yml | 218 ----------- .../deployment/deploy-maven-s3/README.md | 48 +++ .../deployment/deploy-maven-s3/action.yml | 113 ++++++ .github/scripts/publish-to-s3/README.md | 81 ++++ .github/scripts/publish-to-s3/publish.sh | 368 ++++++++++++++++++ .github/workflows/README.md | 8 +- .github/workflows/WORKFLOW_ARCHITECTURE.md | 22 +- .github/workflows/cicd_3-trunk.yml | 4 +- .github/workflows/cicd_4-nightly.yml | 4 +- .github/workflows/cicd_6-release.yml | 14 +- .../workflows/cicd_7-release-java-variant.yml | 10 +- .github/workflows/cicd_8-manual-deploy.yml | 8 +- .../workflows/cicd_comp_deployment-phase.yml | 29 +- .github/workflows/cicd_comp_release-phase.yml | 44 ++- .../workflows/cicd_manual_publish-starter.yml | 59 ++- .github/workflows/cicd_release-cli.yml | 5 + .../legacy-release_maven-release-process.yml | 24 +- .github/workflows/maven-release-process.md | 2 +- ONBOARDING.md | 4 +- .../sdk/create-app/assets/docker-compose.yml | 2 +- docker/dev-env/README.md | 4 +- .../cluster-mode/README.md | 2 +- .../cluster-mode/docker-compose-node-1.yml | 2 +- .../cluster-mode/docker-compose-node-2.yml | 2 +- .../experiments/docker-compose.yml | 2 +- .../load-db-dump/README.md | 2 +- .../load-db-dump/docker-compose.yml | 2 +- .../push-publish/README.md | 2 +- .../push-publish/docker-compose.yml | 4 +- .../dotcms-get-demo-site-starter-urls.sh | 2 +- .../single-node-debug-mode/README.md | 2 +- .../single-node-debug-mode/docker-compose.yml | 2 +- .../single-node-demo-site/README.md | 2 +- .../single-node-demo-site/docker-compose.yml | 2 +- .../docker-compose.yml | 2 +- .../single-node/README.md | 2 +- .../single-node/docker-compose.yml | 2 +- .../with-opensearch-dashboard/README.md | 2 +- .../docker-compose.yml | 2 +- .../with-redis-session/README.md | 2 +- .../docker-compose-node-1.yml | 2 +- .../with-redis/README.md | 2 +- .../with-redis/docker-compose-node-1.yml | 2 +- .../with-redis/docker-compose-node-2.yml | 2 +- docs/cli/CLI_BUILD_SYSTEM.md | 4 +- dotBackendOnboarding.md | 2 +- .../local-run/docker-compose.yml | 2 +- parent/pom.xml | 50 +-- pom.xml | 17 +- tools/dotcms-cli/README.md | 2 +- .../action/.github/workflows/main.yml | 6 +- .../src/test/resources/docker-compose.yaml | 2 +- .../src/test/resources/docker-compose.yaml | 2 +- 54 files changed, 803 insertions(+), 446 deletions(-) delete mode 100644 .github/actions/core-cicd/deployment/deploy-jfrog/README.md delete mode 100644 .github/actions/core-cicd/deployment/deploy-jfrog/action.yml create mode 100644 .github/actions/core-cicd/deployment/deploy-maven-s3/README.md create mode 100644 .github/actions/core-cicd/deployment/deploy-maven-s3/action.yml create mode 100644 .github/scripts/publish-to-s3/README.md create mode 100755 .github/scripts/publish-to-s3/publish.sh diff --git a/.github/actions/core-cicd/deployment/deploy-jfrog/README.md b/.github/actions/core-cicd/deployment/deploy-jfrog/README.md deleted file mode 100644 index ef001e49b9de..000000000000 --- a/.github/actions/core-cicd/deployment/deploy-jfrog/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Deploy Artifact to Artifactory GitHub Action - -This GitHub Action is used to deploy the dotCMS artifacts to Artifactory. It includes steps to extract project modules, version, and repository details from the POM file and deploy artifacts to the specified Artifactory repository. - -## Inputs - -- **modules**: (Optional) Comma-separated list of modules to deploy. If not provided, it will be extracted from the project POM file. -- **exclude-ext**: (Optional) Comma-separated list of extensions to be excluded. -- **dry-run**: (Optional) Enable dry-run mode. If it sets `true` the action will not deploy artifacts to Artifactory. -- **version**: (Optional) Version of the artifacts to deploy. If not provided, it will be extracted from the project POM file. -- **artifactory-repository**: (Optional) Artifactory Repository. If not provided, it will be extracted from the project POM file. -- **artifactory-url**: (Optional) Artifactory URL. If not provided, it will be extracted from the project POM file. -- **artifactory-access-token**: (Optional) Artifactory Access Token. It takes precedence over `artifactory-username` and - `artifactory-password`. -- **artifactory-username**: (Optional) Artifactory username. -- **artifactory-password**: (Optional) Artifactory password. -- **github-token**: (Required) GitHub Token. - -## Outputs - -This action does not produce explicit outputs but uses extracted values within the workflow. - -## Example Usage - -```yaml -name: Deploy Artifact to Artifactory - -on: - push: - branches: - - main - -jobs: - deploy: - runs-on: ubuntu-${{ vars.UBUNTU_RUNNER_VERSION || '24.04' }} - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - - name: Deploy Artifact - uses: ./.github/actions/core-cicd/deployment/deploy-jfrog - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - artifactory-access-token: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }} diff --git a/.github/actions/core-cicd/deployment/deploy-jfrog/action.yml b/.github/actions/core-cicd/deployment/deploy-jfrog/action.yml deleted file mode 100644 index f3df12c28dfa..000000000000 --- a/.github/actions/core-cicd/deployment/deploy-jfrog/action.yml +++ /dev/null @@ -1,218 +0,0 @@ -name: 'Deploy Artifact to Artifactory' -description: 'Deploy the dotCMS artifacts to Artifactory' -inputs: - modules: - description: 'Comma-separated list of modules to deploy, if not provided, will be extracted from the project POM file.' - required: false - exclude-ext: - description: 'Comma-separated list of extensions to be excluded.' - required: false - dry-run: - description: 'Enable dry-run mode' - required: false - version: - description: 'Version of the artifacts to deploy, if not provided, will be extracted from the project POM file.' - required: false - artifactory-repository: - description: 'Artifactory Repository, if not provided, will be extracted from the project POM file.' - required: false - artifactory-url: - description: 'Artifactory URL, if not provided, will be extracted from the project POM file.' - required: false - artifactory-access-token: - description: 'Artifactory Access Token. It takes precedence over artifactory-username and artifactory-password.' - required: false - artifactory-username: - description: 'Artifactory username' - required: false - artifactory-password: - description: 'Artifactory password' - required: false - github-token: - description: 'GitHub Token' - required: true - artifact-run-id: - default: ${{ github.run_id }} - description: 'The run id of the core artifacts' - -runs: - using: "composite" - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - - uses: ./.github/actions/core-cicd/maven-job - with: - github-token: ${{ inputs.github-token }} - stage-name: "Deploy Artifacts Validate" - maven-args: "validate" # We don't need to build just get the repo and use validate to check everything exists - artifacts-from: ${{ inputs.artifact-run-id }} - - - uses: jfrog/setup-jfrog-cli@v4 - - - name: 'Extract project modules' - if: ${{ inputs.modules == '' || inputs.modules == null }} - id: maven-modules - run: | - echo "::group::Extract project modules" - POM_PATH="${{ inputs.pom-path }}" - artifact_ids="" - - # Function to extract artifact ID from POM file - extract_artifact_id() { - mvn -f "$1" help:evaluate -Dexpression=project.artifactId -q -DforceStdout 2>/dev/null || true - } - - # Function to get submodules from POM file - get_submodules() { - mvn -f "$1" help:evaluate -Dexpression=project.modules -q -DforceStdout 2>/dev/null | sed 's/<[^>]*>//g' | tr -d '\n' | tr -s ' ' | tr ' ' ',' || true - } - - # Function to process each module and its submodules - process_module() { - - local module_path="$1" - local module_pom="$module_path/pom.xml" - - if [ -f "$module_pom" ]; then - artifactId=$(extract_artifact_id "$module_pom") - - if [[ -z "$artifactId" || "$artifactId" == *"[ERROR]"* ]]; then - artifact_ids+="$module_path," - else - artifact_ids+="$artifactId," - fi - - submodules=$(get_submodules "$module_pom") - if [[ -z "$submodules" || "$submodules" == *"[ERROR]"* ]]; then - return - fi - - submodules=$(echo $submodules | sed 's/^,//' || true) - - # Process each module and submodule recursively - for submodule in ${submodules//,/ }; do - process_module "$module_path/$submodule" - done - else - artifact_ids+="$module_path," - fi - } - - modules=$(mvn -f "$POM_PATH" help:evaluate -Dexpression=project.modules -q -DforceStdout 2>/dev/null | sed 's/<[^>]*>//g' | tr -d '\n' | tr -s ' ' | tr ' ' ',' || true) - modules=$(echo $modules | sed 's/^,//' || true) - - for module in ${modules//,/ }; do - process_module "$module" - done - - artifact_ids=$(echo $artifact_ids | sed 's/,$/,dotcms-root/' || true) - echo "::notice::modules: $artifact_ids" - echo "artifact-ids=${artifact_ids}" >> $GITHUB_OUTPUT - echo "::endgroup::" - shell: bash - - - name: 'Extract project version' - if: ${{ inputs.version == '' || inputs.version == null }} - id: maven-version - run: | - echo "::group::Extract project version" - version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - echo "::notice::version: $version" - echo "version=$version" >> $GITHUB_OUTPUT - echo "::endgroup::" - shell: bash - - - name: 'Extract project repo' - if: ${{ inputs.artifactory-repository == '' || inputs.artifactory-repository == null }} - id: maven-artifact-repository - env: - VERSION: ${{ inputs.version || steps.maven-version.outputs.version }} - run: | - echo "::group::Extract artifact repository" - echo "" - - POM_FILE="pom.xml" - - if [[ ! -f "$POM_FILE" ]]; then - echo "$POM_FILE file is missing." - exit 1 - fi - - # Determine the node type based on the version - if [[ "$VERSION" =~ [Ss][Nn][Aa][Pp][Ss][Hh][Oo][Tt] ]]; then - NODE_TYPE="snapshotRepository" - else - NODE_TYPE="repository" - fi - - echo "NODE_TYPE=$NODE_TYPE" - - # Extract the repository URL from the POM file - REPO=$(mvn -f "$POM_FILE" -N help:evaluate -Dexpression=project.distributionManagement.$NODE_TYPE.url -q -DforceStdout 2>/dev/null) - - if [[ "$REPO" =~ ^(https://[^/]+/[^/]+)/(.+)$ ]]; then - SERVER_URL="${BASH_REMATCH[1]}" - REPO_NAME="${BASH_REMATCH[2]}" - - echo "url=$SERVER_URL" >> $GITHUB_OUTPUT - echo "repo=$REPO_NAME" >> $GITHUB_OUTPUT - else - echo "Invalid REPO format" - exit 1 - fi - - echo "::notice::ARTIFACTORY_URL=$SERVER_URL" - echo "::notice::ARTIFACTORY_REPO=$REPO_NAME" - - echo "::endgroup::" - shell: bash - - - name: 'JFrog CLI context' - env: - ARTIFACTORY_URL: ${{ inputs.artifactory-url || steps.maven-artifact-repository.outputs.url }} - ARTIFACTORY_ACCESS_TOKEN: ${{ inputs.artifactory-access-token }} - run: | - echo "::group::JFrog CLI context" - jf rt ping --url=$ARTIFACTORY_URL --access-token=$ARTIFACTORY_ACCESS_TOKEN - echo "::endgroup::" - shell: bash - - - name: 'Deploy artifacts' - env: - ARTIFACTORY_ACCESS_TOKEN: ${{ inputs.artifactory-access-token }} - ARTIFACTORY_URL: ${{ inputs.artifactory-url || steps.maven-artifact-repository.outputs.url }} - ARTIFACTORY_USERNAME: ${{ inputs.artifactory-username }} - ARTIFACTORY_PASSWORD: ${{ inputs.artifactory-password }} - ARTIFACTORY_REPO: ${{ inputs.artifactory-repository || steps.maven-artifact-repository.outputs.repo }} - VERSION: ${{ inputs.version || steps.maven-version.outputs.version }} - PRJ_MODULES: ${{ inputs.modules || steps.maven-modules.outputs.artifact-ids }} - EXCLUDE_EXT: ${{ inputs.exclude-ext || 'repositories,excludeext' }} - DRY_RUN_MODE: ${{ inputs.dry-run }} - run: | - echo "::group::Deploy Artifacts" - - MAVEN_DIR=${HOME}/.m2/repository - cd $MAVEN_DIR - - # Replace ',' with '|' - MODULES=$(echo $PRJ_MODULES | sed 's/,/|/g') - # Replace '.' with '\.' - ESCAPED_VERSION=$(echo $VERSION | sed 's/\./\\./g') - # Replace ',' with '|' - EXCLUDE=$(echo $EXCLUDE_EXT | sed 's/,/|/g') - - if [[ $DRY_RUN_MODE == true ]]; then - DRY_RUN='--dry-run' - fi - - # Deploy the artifacts using JFrog CLI with appropriate credentials and options - if [[ -n "$ARTIFACTORY_ACCESS_TOKEN" ]]; then - jf rt u "com/dotcms/(${MODULES})/${ESCAPED_VERSION}" $ARTIFACTORY_REPO --url=$ARTIFACTORY_URL --access-token=$ARTIFACTORY_ACCESS_TOKEN --flat=false --exclusions ".*\.(${EXCLUDE})$" --recursive --regexp $DRY_RUN - elif [[ -n "$ARTIFACTORY_USERNAME" && -n "$ARTIFACTORY_PASSWORD" ]]; then - jf rt u "com/dotcms/(${MODULES})/${ESCAPED_VERSION}" $ARTIFACTORY_REPO --url=$ARTIFACTORY_URL --user=$ARTIFACTORY_USERNAME --password=$ARTIFACTORY_PASSWORD --flat=false --exclusions ".*\.(${EXCLUDE})$" --recursive --regexp $DRY_RUN - else - echo "Credentials not provided." - exit 1 - fi - echo "::endgroup::" - shell: bash diff --git a/.github/actions/core-cicd/deployment/deploy-maven-s3/README.md b/.github/actions/core-cicd/deployment/deploy-maven-s3/README.md new file mode 100644 index 000000000000..2f4a05a26891 --- /dev/null +++ b/.github/actions/core-cicd/deployment/deploy-maven-s3/README.md @@ -0,0 +1,48 @@ +# Deploy Maven Artifacts to S3 + +Publishes the locally-installed dotCMS Maven artifacts to the BunnyCDN +S3-compatible repository. This replaces the former `deploy-jfrog` (Artifactory) +action. + +The action restores the `maven-repo` artifact produced by the build phase, +resolves the project version, and delegates the upload to +[`.github/scripts/publish-to-s3/publish.sh`](../../../../scripts/publish-to-s3/README.md). +The script preserves the `com/dotcms//` layout, writes +`.sha1`/`.md5` checksums, and regenerates the `maven-metadata.xml` files that +Artifactory used to create. + +## Inputs + +| Input | Required | Default | Description | +| --- | --- | --- | --- | +| `version` | no | project version | Version to publish. Set it when the restored `maven-repo` artifact was built from a different ref than the checked-out POM (e.g. releases). | +| `modules` | no | all modules for the version | Comma-separated artifactIds to restrict the publish to. | +| `exclude-ext` | no | `repositories,excludeext` | Extra file extensions to skip. | +| `dry-run` | no | `false` | Print what would be uploaded without writing. | +| `bucket` | no | `MAVEN_BUNNY_RW_USERNAME` | S3 bucket / Bunny storage zone. | +| `prefix` | no | `libs-release` | Key prefix inside the bucket. | +| `endpoint` | no | `https://ny-s3.storage.bunnycdn.com` | S3 endpoint URL. | +| `region` | no | `ny` | S3 signing region. | +| `access-key-id` | **yes** | — | S3 access key id (Bunny storage-zone name). | +| `secret-access-key` | **yes** | — | S3 secret access key (Bunny storage-zone password). | +| `checksums` | no | `true` | Upload `.sha1`/`.md5` checksums. | +| `github-token` | **yes** | — | Token used to download the `maven-repo` artifact. | +| `artifact-run-id` | no | `${{ github.run_id }}` | Run id that holds the `maven-repo` artifact. | + +## Example + +```yaml +- name: Deploy Maven artifacts + uses: ./.github/actions/core-cicd/deployment/deploy-maven-s3 + with: + access-key-id: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + secret-access-key: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} + github-token: ${{ secrets.GITHUB_TOKEN }} + artifact-run-id: ${{ inputs.artifact-run-id }} +``` + +Public URL for the above with the defaults: + +``` +https://dotcms-repo.b-cdn.net/libs-release/com/dotcms///-.jar +``` diff --git a/.github/actions/core-cicd/deployment/deploy-maven-s3/action.yml b/.github/actions/core-cicd/deployment/deploy-maven-s3/action.yml new file mode 100644 index 000000000000..5c145bd478bd --- /dev/null +++ b/.github/actions/core-cicd/deployment/deploy-maven-s3/action.yml @@ -0,0 +1,113 @@ +name: 'Deploy Maven Artifacts to S3' +description: | + Publish the locally-installed dotCMS Maven artifacts to the BunnyCDN + S3-compatible storage zone. This replaces the former Artifactory + (deploy-jfrog) deployment. + + The action restores the `maven-repo` artifact produced by the build phase, + resolves the project version, then delegates to + `.github/scripts/publish-to-s3/publish.sh maven`, which uploads every + com/dotcms module for that version and regenerates maven-metadata.xml. + +inputs: + version: + description: 'Version of the artifacts to deploy. Defaults to the project version in the checked-out POM.' + required: false + modules: + description: 'Comma-separated artifactIds to publish. Defaults to every com/dotcms module with a directory for the version.' + required: false + exclude-ext: + description: 'Comma-separated file extensions to skip.' + required: false + default: 'repositories,excludeext' + dry-run: + description: 'Enable dry-run mode (no writes).' + required: false + bucket: + description: 'S3 bucket / Bunny storage zone. Defaults to MAVEN_BUNNY_RW_USERNAME.' + required: false + prefix: + description: 'Key prefix inside the bucket.' + required: false + default: 'libs-release' + endpoint: + description: 'S3 endpoint URL.' + required: false + default: 'https://ny-s3.storage.bunnycdn.com' + region: + description: 'S3 signing region.' + required: false + default: 'ny' + access-key-id: + description: 'S3 access key id (Bunny storage-zone name).' + required: true + secret-access-key: + description: 'S3 secret access key (Bunny storage-zone password).' + required: true + checksums: + description: 'Upload .sha1/.md5 checksums alongside the artifacts.' + required: false + default: 'true' + github-token: + description: 'GitHub Token' + required: true + artifact-run-id: + default: ${{ github.run_id }} + description: 'The run id of the core artifacts' + +runs: + using: "composite" + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: ./.github/actions/core-cicd/maven-job + with: + github-token: ${{ inputs.github-token }} + stage-name: "Deploy Artifacts Validate" + maven-args: "validate" # No build needed; only restore the maven-repo artifact + artifacts-from: ${{ inputs.artifact-run-id }} + + - name: 'Extract project version' + if: ${{ inputs.version == '' || inputs.version == null }} + id: maven-version + shell: bash + run: | + echo "::group::Extract project version" + version=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "::notice::version: $version" + echo "version=$version" >> $GITHUB_OUTPUT + echo "::endgroup::" + + - name: 'Deploy artifacts to S3' + shell: bash + env: + MAVEN_BUNNY_RW_USERNAME: ${{ inputs.access-key-id }} + MAVEN_BUNNY_RW_PASSWORD: ${{ inputs.secret-access-key }} + MAVEN_S3_ENDPOINT: ${{ inputs.endpoint }} + MAVEN_S3_REGION: ${{ inputs.region }} + MAVEN_S3_BUCKET: ${{ inputs.bucket }} + MAVEN_S3_PREFIX: ${{ inputs.prefix }} + VERSION: ${{ inputs.version || steps.maven-version.outputs.version }} + PRJ_MODULES: ${{ inputs.modules }} + EXCLUDE_EXT: ${{ inputs.exclude-ext }} + DRY_RUN_MODE: ${{ inputs.dry-run }} + CHECKSUMS: ${{ inputs.checksums }} + run: | + echo "::group::Deploy Artifacts to S3" + args=(maven --version "$VERSION" --exclude-ext "$EXCLUDE_EXT") + + if [[ -n "${PRJ_MODULES:-}" ]]; then + args+=(--modules "$PRJ_MODULES") + fi + if [[ -n "${MAVEN_S3_BUCKET:-}" ]]; then + args+=(--bucket "$MAVEN_S3_BUCKET") + fi + if [[ "${DRY_RUN_MODE:-false}" == "true" ]]; then + args+=(--dry-run) + fi + if [[ "${CHECKSUMS:-true}" != "true" ]]; then + args+=(--no-checksums) + fi + + ./.github/scripts/publish-to-s3/publish.sh "${args[@]}" + echo "::endgroup::" \ No newline at end of file diff --git a/.github/scripts/publish-to-s3/README.md b/.github/scripts/publish-to-s3/README.md new file mode 100644 index 000000000000..93edd8f7880f --- /dev/null +++ b/.github/scripts/publish-to-s3/README.md @@ -0,0 +1,81 @@ +# publish-to-s3 + +Helper that publishes dotCMS build artifacts to the BunnyCDN S3-compatible +storage zone. It replaces the former Artifactory (`repo.dotcms.com`) +deployments, so every CI/CD publish path goes through one place instead of +duplicating endpoint/credential wiring in each workflow. + +## Usage + +```bash +# Publish one version of every com/dotcms module installed in ~/.m2/repository +.github/scripts/publish-to-s3/publish.sh maven --version 26.09.14-01 + +# Publish a single file to an explicit key +.github/scripts/publish-to-s3/publish.sh file \ + --source ./starter/20260910.zip \ + --key com/dotcms/starter/20260910/starter-20260910.zip + +# Preview without writing +.github/scripts/publish-to-s3/publish.sh maven --version 26.09.14-01 --dry-run +``` + +## Configuration + +CLI flags take precedence over these environment variables: + +| Variable | Default | Purpose | +| --- | --- | --- | +| `MAVEN_BUNNY_RW_USERNAME` | — | Bunny storage-zone name / S3 access key id | +| `MAVEN_BUNNY_RW_PASSWORD` | — | Bunny storage-zone password / S3 secret key | +| `MAVEN_S3_BUCKET` | `$MAVEN_BUNNY_RW_USERNAME` | Bucket (storage zone) | +| `MAVEN_S3_PREFIX` | `libs-release` | Key prefix inside the bucket | +| `MAVEN_S3_ENDPOINT` | `https://ny-s3.storage.bunnycdn.com` | S3 endpoint | +| `MAVEN_S3_REGION` | `ny` | S3 signing region | +| `MAVEN_S3_PUBLIC_URL` | `https://dotcms-repo.b-cdn.net` | Public CDN base used for printed URLs | +| `MAVEN_REPO_DIR` | `$HOME/.m2/repository` | Local Maven repository | +| `MAVEN_S3_EXCLUDE_EXT` | `repositories,excludeext` | Extra extensions to skip | +| `MAVEN_S3_UPDATE_METADATA` | `true` | Regenerate `maven-metadata.xml` | +| `MAVEN_S3_CHECKSUMS` | `true` | Upload `.sha1`/`.md5` checksums | +| `MAVEN_S3_ALLOW_SNAPSHOTS` | `false` | Publish `-SNAPSHOT` versions | + +BunnyCDN convention: the S3 access key id **is** the storage-zone name, so the +bucket defaults to `MAVEN_BUNNY_RW_USERNAME`. + +## What `maven` does + +1. Walks `$MAVEN_REPO_DIR/com/dotcms/*/` and uploads each subtree to + `s3://$BUCKET/$PREFIX/com/dotcms///`. S3 has no real + folders; nested key prefixes are created implicitly, so the layout matches + the old Artifactory `libs-release` layout. +2. Uploads `.sha1`/`.md5` checksums for the primary artifacts (`.pom`, `.jar`, + `.zip`, `.war`, `.aar`, `.module`). +3. Regenerates `com/dotcms//maven-metadata.xml` from the versions + already present in the bucket plus the one just uploaded. Artifactory used to + do this automatically and consumers (for example the dotCLI action) read it, + so a plain file copy is not enough. + +Step 3 is best-effort: a metadata failure logs a warning but does not fail a +publish whose artifacts are already in place. + +### Snapshots + +`maven` **refuses to publish `-SNAPSHOT` versions** by default (logs a warning +and exits 0). dotCMS does not consume shared snapshots, and publishing one to +`libs-release` would make the artifact-level `maven-metadata.xml` `` a +snapshot, breaking the release lookup the CLI action performs. Pass +`--allow-snapshots` to override. + +## Resulting URLs + +With the defaults, an artifact published for version `26.09.14-01` is served at: + +``` +https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-core/26.09.14-01/dotcms-core-26.09.14-01.jar +``` + +> **Prefix note:** the request that introduced this migration said the repo +> starts under `/libs-releases`, but the example URLs (and the retired +> Artifactory `libs-release` repo) use `/libs-release`. The script defaults to +> `libs-release`; set `MAVEN_S3_PREFIX` to override if the storage zone really +> uses the plural form. diff --git a/.github/scripts/publish-to-s3/publish.sh b/.github/scripts/publish-to-s3/publish.sh new file mode 100755 index 000000000000..4c8df610a43e --- /dev/null +++ b/.github/scripts/publish-to-s3/publish.sh @@ -0,0 +1,368 @@ +#!/usr/bin/env bash +# +# publish-to-s3/publish.sh +# +# Publishes build artifacts to the dotCMS BunnyCDN S3-compatible storage zone. +# This replaces the Artifactory deployments (repo.dotcms.com). +# +# Two sub-commands: +# +# maven Publish one version of every com/dotcms module found in a local +# Maven repository (~/.m2/repository), preserving the +# groupId/artifactId/version layout, and (re)generate the +# maven-metadata.xml files Artifactory used to create. +# +# file Upload a single file to an explicit key. Used for artifacts that do +# not live in a Maven repository (e.g. the starter zips). +# +# BunnyCDN convention: the S3 access key id IS the storage-zone name, so when +# MAVEN_S3_BUCKET is not set it defaults to MAVEN_BUNNY_RW_USERNAME. +# +# Environment (all optional, CLI flags take precedence): +# MAVEN_BUNNY_RW_USERNAME Bunny storage-zone name / S3 access key id +# MAVEN_BUNNY_RW_PASSWORD Bunny storage-zone password / S3 secret key +# MAVEN_S3_BUCKET Bucket (storage zone). Defaults to the username. +# MAVEN_S3_PREFIX Key prefix. Default: libs-release +# MAVEN_S3_ENDPOINT Default: https://ny-s3.storage.bunnycdn.com +# MAVEN_S3_REGION Default: ny +# MAVEN_S3_PUBLIC_URL Public CDN base, used for printed download URLs. +# Default: https://dotcms-repo.b-cdn.net +# MAVEN_REPO_DIR Default: $HOME/.m2/repository +# MAVEN_S3_EXCLUDE_EXT Extra extensions to skip. Default: repositories,excludeext +# MAVEN_S3_UPDATE_METADATA Default: true +# MAVEN_S3_CHECKSUMS Default: true +# MAVEN_S3_ALLOW_SNAPSHOTS Default: false (shared snapshots are not consumed) +# +# Exit codes: 0 success, 1 error. + +set -euo pipefail + +S3_ENDPOINT="${MAVEN_S3_ENDPOINT:-https://ny-s3.storage.bunnycdn.com}" +S3_REGION="${MAVEN_S3_REGION:-ny}" +S3_PREFIX="${MAVEN_S3_PREFIX:-libs-release}" +S3_BUCKET="${MAVEN_S3_BUCKET:-${MAVEN_BUNNY_RW_USERNAME:-}}" +S3_PUBLIC_URL="${MAVEN_S3_PUBLIC_URL:-https://dotcms-repo.b-cdn.net}" +MAVEN_REPO_DIR="${MAVEN_REPO_DIR:-$HOME/.m2/repository}" +EXCLUDE_EXT="${MAVEN_S3_EXCLUDE_EXT:-repositories,excludeext}" +UPDATE_METADATA="${MAVEN_S3_UPDATE_METADATA:-true}" +CHECKSUMS="${MAVEN_S3_CHECKSUMS:-true}" +ALLOW_SNAPSHOTS="${MAVEN_S3_ALLOW_SNAPSHOTS:-false}" + +# Resolve S3 credentials. Org secrets are exposed under the MAVEN_BUNNY_* names; +# the AWS CLI reads the standard AWS_* variables. These must be exported so the +# `aws` child process inherits them. +if [[ -z "${AWS_ACCESS_KEY_ID:-}" && -n "${MAVEN_BUNNY_RW_USERNAME:-}" ]]; then + AWS_ACCESS_KEY_ID="$MAVEN_BUNNY_RW_USERNAME" +fi +if [[ -z "${AWS_SECRET_ACCESS_KEY:-}" && -n "${MAVEN_BUNNY_RW_PASSWORD:-}" ]]; then + AWS_SECRET_ACCESS_KEY="$MAVEN_BUNNY_RW_PASSWORD" +fi +export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY +export AWS_DEFAULT_REGION="$S3_REGION" + +log() { printf '::notice::%s\n' "$*"; } +warn() { printf '::warning::%s\n' "$*" >&2; } +die() { printf '::error::%s\n' "$*" >&2; exit 1; } + +# Temp dirs are cleaned up once, on exit. A per-function RETURN trap would fire +# on every function return (including the aws_s3 helper) and delete the staging +# directory before it has been uploaded. +CLEANUP_DIRS=() +cleanup() { + local d + for d in ${CLEANUP_DIRS[@]+"${CLEANUP_DIRS[@]}"}; do + [[ -n "$d" ]] && rm -rf "$d" + done +} +trap cleanup EXIT + +usage() { + cat <<'EOF' +Usage: + publish.sh maven --version [options] + publish.sh file --source --key [options] + +Common options: + --bucket S3 bucket / storage zone (default: $MAVEN_BUNNY_RW_USERNAME) + --prefix Key prefix (default: libs-release) + --endpoint S3 endpoint (default: https://ny-s3.storage.bunnycdn.com) + --region S3 signing region (default: ny) + --dry-run Print what would be uploaded; do not write + --no-metadata (maven) Do not (re)generate maven-metadata.xml + --no-checksums (maven) Do not upload .sha1/.md5 checksums + --allow-snapshots (maven) Publish a -SNAPSHOT version (default: refuse) + +maven options: + --version Version subtree to publish (required) + --repo-dir Local Maven repository (default: $HOME/.m2/repository) + --modules Restrict to these artifactIds (default: every com/dotcms module + that has a directory for ) + --exclude-ext Extra file extensions to skip (default: repositories,excludeext) + +file options: + --source File to upload (required) + --key Destination key relative to the prefix (required) +EOF +} + +# Thin wrapper so every call shares the endpoint, region and credentials. +aws_s3() { + aws --endpoint-url "$S3_ENDPOINT" --region "$S3_REGION" s3 "$@" +} + +require_credentials() { + if [[ "${DRY_RUN:-false}" == "true" ]]; then + return 0 + fi + [[ -n "$S3_BUCKET" ]] || die "Bucket is empty. Set MAVEN_S3_BUCKET or MAVEN_BUNNY_RW_USERNAME." + [[ -n "${AWS_ACCESS_KEY_ID:-}" ]] || die "Missing MAVEN_BUNNY_RW_USERNAME / AWS_ACCESS_KEY_ID." + [[ -n "${AWS_SECRET_ACCESS_KEY:-}" ]] || die "Missing MAVEN_BUNNY_RW_PASSWORD / AWS_SECRET_ACCESS_KEY." +} + +# Emits "key=value" lines to $GITHUB_OUTPUT when running inside Actions. +emit_output() { + local name="$1" value="$2" + if [[ -n "${GITHUB_OUTPUT:-}" ]]; then + printf '%s=%s\n' "$name" "$value" >> "$GITHUB_OUTPUT" + fi +} + +# --------------------------------------------------------------------------- +# maven +# --------------------------------------------------------------------------- + +# extra_args are bash-glob exclusions derived from --exclude-ext. +build_exclude_args() { + EXCLUDE_ARGS=( + --exclude "*.lastUpdated" + --exclude "resolver-status.properties" + --exclude "maven-metadata-local.xml" + --exclude "*.sha1" + --exclude "*.md5" + --exclude "*.sha256" + ) + if [[ -n "$EXCLUDE_EXT" ]]; then + local ext + IFS=',' read -ra _exts <<< "$EXCLUDE_EXT" + for ext in "${_exts[@]}"; do + [[ -n "$ext" ]] && EXCLUDE_ARGS+=(--exclude "*.$ext") + done + fi +} + +# Uploads .sha1/.md5 checksums for the primary artifacts of one version dir. +upload_checksums() { + local src_dir="$1" dest="$2" tmp rel + tmp="$(mktemp -d)" + CLEANUP_DIRS+=("$tmp") + + while IFS= read -r -d '' rel; do + mkdir -p "$tmp/$(dirname "$rel")" + sha1sum "$src_dir/$rel" | awk '{print $1}' > "$tmp/$rel.sha1" + md5sum "$src_dir/$rel" | awk '{print $1}' > "$tmp/$rel.md5" + done < <(cd "$src_dir" && find . -type f \ + \( -name '*.pom' -o -name '*.jar' -o -name '*.zip' \ + -o -name '*.war' -o -name '*.aar' -o -name '*.module' \) -print0) + + local args=(--recursive --no-progress) + if [[ "${DRY_RUN:-false}" == "true" ]]; then + args+=(--dryrun) + fi + aws_s3 cp "$tmp" "$dest" "${args[@]}" +} + +# Rebuilds com/dotcms//maven-metadata.xml from the versions that +# already exist in the bucket plus the version just uploaded. Best-effort: a +# failure here must not fail the publish, because the artifacts themselves are +# already in place. +update_artifact_metadata() { + local artifact="$1" version="$2" ts + ts="$(date -u +%Y%m%d%H%M%S)" + local base="$S3_PREFIX/com/dotcms/$artifact" + local tmp versions latest release v + + tmp="$(mktemp -d)" + CLEANUP_DIRS+=("$tmp") + + versions="$( + aws_s3 ls "s3://$S3_BUCKET/$base/" 2>/dev/null \ + | awk '{print $2}' | sed 's:/$::' || true + )" + versions="$(printf '%s\n%s\n' "$versions" "$version" | sed '/^$/d' | sort -u -V)" + + latest="$(printf '%s\n' "$versions" | tail -n1)" + release="$(printf '%s\n' "$versions" | grep -v -- '-SNAPSHOT$' | tail -n1 || true)" + [[ -n "$release" ]] || release="$latest" + + { + printf '\n' + printf ' com.dotcms\n' + printf ' %s\n' "$artifact" + printf ' \n' + printf ' %s\n' "$latest" + printf ' %s\n' "$release" + printf ' \n' + while IFS= read -r v; do + [[ -n "$v" ]] && printf ' %s\n' "$v" + done <<< "$versions" + printf ' \n' + printf ' %s\n' "$ts" + printf ' \n' + printf '\n' + } > "$tmp/maven-metadata.xml" + + local args=(--no-progress --content-type application/xml) + [[ "${DRY_RUN:-false}" == "true" ]] && args+=(--dryrun) + aws_s3 cp "$tmp/maven-metadata.xml" "s3://$S3_BUCKET/$base/maven-metadata.xml" "${args[@]}" +} + +# Non-unique SNAPSHOT deployments would need a version-level maven-metadata.xml +# so Maven can resolve -SNAPSHOT coordinates. We do not publish snapshots to the +# shared repository (see cmd_maven), so this is intentionally not implemented. + +cmd_maven() { + local version="" modules="" dry_run="$DRY_RUN" + while [[ $# -gt 0 ]]; do + case "$1" in + --version) version="${2:?}"; shift 2 ;; + --repo-dir) MAVEN_REPO_DIR="${2:?}"; shift 2 ;; + --modules) modules="${2:-}"; shift 2 ;; + --exclude-ext) EXCLUDE_EXT="${2:-}"; shift 2 ;; + --bucket) S3_BUCKET="${2:?}"; shift 2 ;; + --prefix) S3_PREFIX="${2:?}"; shift 2 ;; + --endpoint) S3_ENDPOINT="${2:?}"; shift 2 ;; + --region) S3_REGION="${2:?}"; shift 2 ;; + --dry-run) dry_run=true; shift ;; + --no-metadata) UPDATE_METADATA=false; shift ;; + --no-checksums) CHECKSUMS=false; shift ;; + --allow-snapshots) ALLOW_SNAPSHOTS=true; shift ;; + -h|--help) usage; exit 0 ;; + *) die "Unknown maven option: $1" ;; + esac + done + DRY_RUN="$dry_run" + + [[ -n "$version" ]] || die "--version is required" + + # No shared snapshots are consumed at dotCMS. Publishing one would also make + # the artifact-level maven-metadata.xml a snapshot, breaking the + # release lookup the CLI action performs. Refuse unless explicitly allowed. + if [[ "$version" == *-SNAPSHOT && "$ALLOW_SNAPSHOTS" != "true" ]]; then + warn "Skipping snapshot version '$version': shared snapshots are not published (pass --allow-snapshots to override)." + return 0 + fi + + require_credentials + + local group_dir="$MAVEN_REPO_DIR/com/dotcms" + [[ -d "$group_dir" ]] || die "No com/dotcms directory under $MAVEN_REPO_DIR" + + local artifacts=() artifact + if [[ -n "$modules" ]]; then + local wanted + IFS=',' read -ra wanted <<< "$modules" + for artifact in "${wanted[@]}"; do + artifact="${artifact//[[:space:]]/}" + [[ -n "$artifact" ]] || continue + if [[ -d "$group_dir/$artifact/$version" ]]; then + artifacts+=("$artifact") + else + warn "Module $artifact has no $version directory; skipping." + fi + done + else + shopt -s nullglob + local dirs=("$group_dir"/*/"$version") + shopt -u nullglob + for dir in "${dirs[@]}"; do + [[ -d "$dir" ]] && artifacts+=("$(basename "$(dirname "$dir")")") + done + fi + + if [[ ${#artifacts[@]} -eq 0 ]]; then + # An empty publish is only legitimate for the intentionally-skipped + # conditionals (e.g. java variants), so keep it non-fatal but loud. + warn "No com/dotcms artifacts found for version '$version' under $MAVEN_REPO_DIR." + return 0 + fi + + log "Publishing ${#artifacts[@]} artifact(s) for version '$version' to s3://$S3_BUCKET/$S3_PREFIX/com/dotcms/" + build_exclude_args + + local dest upload_args + for artifact in "${artifacts[@]}"; do + local src="$group_dir/$artifact/$version" + dest="s3://$S3_BUCKET/$S3_PREFIX/com/dotcms/$artifact/$version/" + upload_args=(--recursive --no-progress "${EXCLUDE_ARGS[@]}") + [[ "$DRY_RUN" == "true" ]] && upload_args+=(--dryrun) + + log " $artifact:$version -> $dest" + aws_s3 cp "$src" "$dest" "${upload_args[@]}" + + if [[ "$CHECKSUMS" == "true" ]]; then + upload_checksums "$src" "$dest" || warn "Checksum upload failed for $artifact:$version." + fi + + if [[ "$UPDATE_METADATA" == "true" ]]; then + update_artifact_metadata "$artifact" "$version" \ + || warn "maven-metadata.xml update failed for $artifact." + fi + done + + log "Published version '$version'." +} + +# --------------------------------------------------------------------------- +# file +# --------------------------------------------------------------------------- + +cmd_file() { + local source="" key="" dry_run="$DRY_RUN" + while [[ $# -gt 0 ]]; do + case "$1" in + --source) source="${2:?}"; shift 2 ;; + --key) key="${2:?}"; shift 2 ;; + --bucket) S3_BUCKET="${2:?}"; shift 2 ;; + --prefix) S3_PREFIX="${2:?}"; shift 2 ;; + --endpoint) S3_ENDPOINT="${2:?}"; shift 2 ;; + --region) S3_REGION="${2:?}"; shift 2 ;; + --dry-run) dry_run=true; shift ;; + -h|--help) usage; exit 0 ;; + *) die "Unknown file option: $1" ;; + esac + done + DRY_RUN="$dry_run" + + [[ -n "$source" ]] || die "--source is required" + [[ -f "$source" ]] || die "Source file not found: $source" + [[ -n "$key" ]] || die "--key is required" + key="${key#/}" + require_credentials + + local dest="s3://$S3_BUCKET/$S3_PREFIX/$key" + local args=(--no-progress) + [[ "$DRY_RUN" == "true" ]] && args+=(--dryrun) + + log "Uploading $source -> $dest" + aws_s3 cp "$source" "$dest" "${args[@]}" + + local public_url="$S3_PUBLIC_URL/$S3_PREFIX/$key" + log "Artifact URL: $public_url" + emit_output "filename" "$(basename "$source")" + emit_output "key" "$key" + emit_output "url" "$public_url" +} + +# --------------------------------------------------------------------------- + +DRY_RUN="${MAVEN_S3_DRY_RUN:-false}" + +cmd="${1:-}" +[[ $# -gt 0 ]] && shift || true + +case "$cmd" in + maven) cmd_maven "$@" ;; + file) cmd_file "$@" ;; + -h|--help|"") usage; exit 0 ;; + *) usage >&2; die "Unknown command: $cmd" ;; +esac \ No newline at end of file diff --git a/.github/workflows/README.md b/.github/workflows/README.md index e0d531646913..ae942bf71f1a 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -195,9 +195,9 @@ Located in `.github/workflows/cicd_comp_*-phase.yml`: | **Test** | Matrix-driven parallel test execution | Test results, build reports | | **Semgrep** | Security and code quality scanning | Quality gate status | | **CLI Build** | Multi-platform native CLI builds | CLI artifacts (Linux, macOS x2) | -| **Deployment** | Docker images, NPM packages, Artifactory | Docker tags, NPM versions | +| **Deployment** | Docker images, NPM packages, S3 Maven repo | Docker tags, NPM versions | | **Release Prepare** | Version validation, branch creation | Release version, tag, branch | -| **Release** | Artifactory, Javadocs, SBOM, labels | Release artifacts | +| **Release** | S3 Maven repo, Javadocs, SBOM, labels | Release artifacts | | **Finalize** | Aggregate results, determine status | `aggregate_status` | | **Reporting** | Generate reports, send notifications | Slack messages, test reports | @@ -218,7 +218,7 @@ Located in `.github/actions/`: ### Deployment Actions - **deploy-docker**: Multi-platform Docker builds and pushes -- **deploy-jfrog**: Artifactory deployments +- **deploy-maven-s3**: S3 Maven repository deployments - **deploy-cli-npm**: CLI NPM package publishing - **deploy-javadoc**: S3 javadoc uploads - **deploy-javascript-sdk**: SDK NPM publishing @@ -252,7 +252,7 @@ Each workflow has specific optimizations and purposes: **Optimization**: Artifact Reuse - ♻️ Reuses merge queue artifacts (saves 5-10 min) - 🔨 Native CLI builds (3 platforms) -- 📦 Snapshot deployments (GitHub, Artifactory) +- 📦 Snapshot deployments (GitHub, S3 Maven repo) - 📚 Optional SDK publishing ### 4-Nightly (Trunk Health Monitor) diff --git a/.github/workflows/WORKFLOW_ARCHITECTURE.md b/.github/workflows/WORKFLOW_ARCHITECTURE.md index 181e8f140934..d372b9555f75 100644 --- a/.github/workflows/WORKFLOW_ARCHITECTURE.md +++ b/.github/workflows/WORKFLOW_ARCHITECTURE.md @@ -80,8 +80,8 @@ graph TB subgraph Actions[" "] direction LR ATitle["🔧 Composite Actions"] - A1["Core CICD:
maven-job • setup-java
prepare-runner • cleanup-runner"] - A2["Deployment:
deploy-docker • deploy-jfrog
deploy-cli-npm • deploy-javadoc"] + A1["Core CI/CD:
maven-job • setup-java
prepare-runner • cleanup-runner"] + A2["Deployment:
deploy-docker • deploy-maven-s3
deploy-cli-npm • deploy-javadoc"] A3["Support:
notify-slack • issue-fetcher
issue-labeler • sbom-generator"] end @@ -184,10 +184,10 @@ Each top-level CICD workflow has specific triggers, purposes, and configuration |----------|---------|------------------------| | **cicd_1-pr.yml** | Push of PR to GitHub | • **No secrets** - runs on unreviewed code
• **Selective testing** - uses filters to skip unaffected tests
• **Post-workflow reporting** - separate workflow handles secrets
• **Filter-based** - `.github/filters.yaml` determines what runs | | **cicd_2-merge-queue.yml** | PR added to merge queue | • **All tests** - catches flaky tests and filter issues
• **Includes all PRs ahead** - tests combined code
• **Same commit as main** - success means HEAD of main will be identical
• **Critical monitoring** - failures here block all developers | -| **cicd_3-trunk.yml** | Push to main branch | • **Artifact reuse** - uses merge queue build artifacts
• **Native CLI builds** - too expensive for every PR
• **Snapshot deployments** - GitHub packages, Artifactory
• **SDK publishing** - optional NPM package publishing | +| **cicd_3-trunk.yml** | Push to main branch | • **Artifact reuse** - uses merge queue build artifacts
• **Native CLI builds** - too expensive for every PR
• **Snapshot deployments** - GitHub packages, S3 Maven repo
• **SDK publishing** - optional NPM package publishing | | **cicd_4-nightly.yml** | Scheduled (3:18 AM daily) | • **Trunk health monitor** - fail-safe detection of breakage
• **Prevents change accumulation** - catch issues before they pile up
• **Critical for CI success** - enabled increased release frequency
• **NOT a release gate** - legacy workflow for codebase quality
• **Long-running tests** - tests too slow for PR workflow | | **cicd_5-lts.yml** | Push to release-* branches | • **LTS validation** - tests for long-term support branches
• **Full test suite** - comprehensive validation
• **Version-specific** - uses hardcoded version in workflow | -| **cicd_6-release.yml** | Manual workflow_dispatch | • **Production release** - creates official releases
• **Full deployment** - Artifactory, Docker, Javadocs
• **Version management** - creates release branches and tags
• **GitHub labels** - updates issue tracking labels | +| **cicd_6-release.yml** | Manual workflow_dispatch | • **Production release** - creates official releases
• **Full deployment** - S3 Maven repo, Docker, Javadocs
• **Version management** - creates release branches and tags
• **GitHub labels** - updates issue tracking labels | ### Development Philosophy @@ -336,12 +336,12 @@ flowchart TD Deploy --> Release[Release Phase] Release --> Parallel{Parallel
Operations} - Parallel --> Artifactory[Deploy to Artifactory] + Parallel --> S3Repo[Publish to S3 repo] Parallel --> Javadoc[Upload Javadocs to S3] Parallel --> Plugins[Update Plugin Repos] Parallel --> SBOM[Generate SBOM] - Artifactory --> Labels{Update
GitHub
Labels?} + S3Repo --> Labels{Update
GitHub
Labels?} Labels -->|Yes| UpdateLabels[Release Labeling
Next Release → Release vX.X.X] Labels -->|No| Finalize UpdateLabels --> Finalize[Finalize Phase] @@ -390,7 +390,7 @@ flowchart TD MacSilicon --> Deploy Deploy --> DeployDocker[Docker Images] - Deploy --> DeployCLI[CLI to JFrog] + Deploy --> DeployCLI[CLI to S3 repo] Deploy --> DeploySDK{Publish
NPM SDKs?} DeploySDK -->|Yes| SDKPublish[NPM SDK Libs] @@ -613,7 +613,7 @@ on: | Action | Purpose | Used By | |--------|---------|---------| | **deploy-docker** | Multi-platform Docker builds | Deployment phase | -| **deploy-jfrog** | Artifactory deployment | Deployment, Release | +| **deploy-maven-s3** | S3 Maven repository deployment | Deployment, Release | | **deploy-cli-npm** | CLI NPM publishing | Deployment phase | | **deploy-javadoc** | Javadoc S3 upload | Release phase | | **deploy-javascript-sdk** | SDK NPM publishing | Deployment phase | @@ -729,7 +729,7 @@ Navigate to: https://github.com/dotCMS/core/actions → **"-6 Release Process"** | Option | Default | Purpose | |--------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Deploy Artifact** | ✅ Enabled | Deploy to Artifactory (repo.dotcms.com)
**Required for successful release** | +| **Deploy Artifact** | ✅ Enabled | Publish to S3 repo (repo.dotcms.com)
**Required for successful release** | | **Update Plugins** | ✅ Enabled | Triggers plugin-examples repo update
**Note**: Currently requires manual execution at [dotcms-community/plugin-examples/release-target.yml](https://github.com/dotcms-community/plugin-examples/actions/workflows/release-target.yml) | | **Upload Javadocs** | ✅ Enabled | Generate and upload to S3 static bucket
Creates HTML documentation bundle | | **Update GitHub Labels** | ✅ Enabled | Replaces "Next Release" with "Release vX.X.X"
Enables filtering issues by release | @@ -744,7 +744,7 @@ Navigate to: https://github.com/dotCMS/core/actions → **"-6 Release Process"** 5. **Create GitHub Release** - Creates draft release with tag 6. **Build Artifacts** - Production build with version 7. **Deploy Images** - Docker images (dotcms, dotcms-dev) to Docker Hub -8. **Deploy Artifacts** - Maven artifacts to Artifactory +8. **Deploy Artifacts** - Maven artifacts to the S3 repository 9. **Upload Javadocs** - Documentation to S3 10. **Update Plugins** - Triggers plugin repository workflow 11. **Generate SBOM** - Software Bill of Materials @@ -830,7 +830,7 @@ Our CI/CD process extensively uses caching and artifacts to optimize performance - **cli-artifacts**: Native CLI distributions - Per-platform artifacts (Linux, macOS Intel, macOS Silicon) - - Used for NPM publishing and JFrog deployment + - Used for NPM publishing and S3 Maven publishing - 2-day retention for snapshot builds ### Parallel Execution Model diff --git a/.github/workflows/cicd_3-trunk.yml b/.github/workflows/cicd_3-trunk.yml index 0e23db06afed..074535bae575 100644 --- a/.github/workflows/cicd_3-trunk.yml +++ b/.github/workflows/cicd_3-trunk.yml @@ -126,8 +126,8 @@ jobs: secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} NPM_ORG_TOKEN: ${{ secrets.NPM_ORG_TOKEN }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/.github/workflows/cicd_4-nightly.yml b/.github/workflows/cicd_4-nightly.yml index 8f0b5b8e919f..345a1bb36a7c 100644 --- a/.github/workflows/cicd_4-nightly.yml +++ b/.github/workflows/cicd_4-nightly.yml @@ -209,8 +209,8 @@ jobs: secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} NPM_ORG_TOKEN: ${{ secrets.NPM_ORG_TOKEN }} DEV_REQUEST_TOKEN: ${{ secrets.DEV_REQUEST_TOKEN }} diff --git a/.github/workflows/cicd_6-release.yml b/.github/workflows/cicd_6-release.yml index d3847dda8b65..8fd95f2762b5 100644 --- a/.github/workflows/cicd_6-release.yml +++ b/.github/workflows/cicd_6-release.yml @@ -7,7 +7,7 @@ # Key features: # - Release preparation (branch creation, version setting) # - Standard build phase for artifact generation -# - Release-specific deployment (Artifactory, Javadocs, plugins) +# - Release-specific publishing (S3 Maven repository, Javadocs, plugins) # - Docker image deployment via standard deployment phase # - SBOM generation # - GitHub label management @@ -30,7 +30,7 @@ on: description: 'Commit Hash (default to latest commit)' required: false deploy_artifact: - description: 'Deploy Artifact to Artifactory' + description: 'Publish Maven artifacts to the S3 repository' type: boolean default: true required: false @@ -265,8 +265,8 @@ jobs: secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} DEV_REQUEST_TOKEN: ${{ secrets.DEV_REQUEST_TOKEN }} @@ -480,7 +480,7 @@ jobs: > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View workflow run — check logs for details> slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} - # Release - release-specific operations (Artifactory, Javadocs, Plugins, SBOM, Labels) + # Release - release-specific operations (S3 Maven repository, Javadocs, Plugins, SBOM, Labels) # Waits for deployment to complete to safely update labels only if both succeed release: name: Release @@ -498,8 +498,8 @@ jobs: java-version: ${{ github.event.inputs.java-version }} artifact-suffix: ${{ github.event.inputs.artifact-suffix }} secrets: - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CI_MACHINE_TOKEN: ${{ secrets.CI_MACHINE_TOKEN }} diff --git a/.github/workflows/cicd_7-release-java-variant.yml b/.github/workflows/cicd_7-release-java-variant.yml index a2f117633b17..2ac34ea64324 100644 --- a/.github/workflows/cicd_7-release-java-variant.yml +++ b/.github/workflows/cicd_7-release-java-variant.yml @@ -139,12 +139,12 @@ jobs: secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} DEV_REQUEST_TOKEN: ${{ secrets.DEV_REQUEST_TOKEN }} - # Release - release-specific operations (Artifactory only, skip one-time operations) + # Release - release-specific operations (S3 Maven repository only, skip one-time operations) release: name: Release needs: [ extract-version, initialize, build, deployment ] @@ -161,8 +161,8 @@ jobs: java-version: ${{ github.event_name == 'workflow_dispatch' && inputs.java_version || vars.RELEASE_JAVA_VARIANT_VERSION }} artifact-suffix: ${{ github.event_name == 'workflow_dispatch' && inputs.artifact_suffix || vars.RELEASE_JAVA_VARIANT_SUFFIX }} secrets: - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CI_MACHINE_TOKEN: ${{ secrets.CI_MACHINE_TOKEN }} diff --git a/.github/workflows/cicd_8-manual-deploy.yml b/.github/workflows/cicd_8-manual-deploy.yml index 03fa80271fc0..9e9858719652 100644 --- a/.github/workflows/cicd_8-manual-deploy.yml +++ b/.github/workflows/cicd_8-manual-deploy.yml @@ -102,7 +102,7 @@ on: type: string default: '' allow_release_override: - description: '⚠️ DANGER: Allow overriding actual release artifacts in Maven/Artifactory. Only enable if you know what you are doing!' + description: '⚠️ DANGER: Allow overriding actual release artifacts in Maven/S3 repository. Only enable if you know what you are doing!' type: boolean default: false @@ -161,7 +161,7 @@ jobs: if [[ "${EFFECTIVE_VERSION}" =~ ^[0-9]{2}\.[0-9]{2}\.[0-9]{2}(-[0-9]{1,2}|_lts_v[0-9]{1,2})$ ]]; then if [[ "${ALLOW_OVERRIDE}" != "true" ]]; then echo "❌ ERROR: Version '${EFFECTIVE_VERSION}' matches release version pattern!" - echo "This could overwrite actual release artifacts in Maven/Artifactory." + echo "This could overwrite actual release artifacts in Maven/S3 repository." echo "" echo "To proceed, you must:" echo "1. Use a different version name (e.g., ${EFFECTIVE_VERSION}-test, manual-${EFFECTIVE_VERSION})" @@ -287,8 +287,8 @@ jobs: secrets: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} - EE_REPO_USERNAME: ${{ secrets.EE_REPO_USERNAME }} - EE_REPO_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} DEV_REQUEST_TOKEN: ${{ secrets.DEV_REQUEST_TOKEN }} diff --git a/.github/workflows/cicd_comp_deployment-phase.yml b/.github/workflows/cicd_comp_deployment-phase.yml index 322465ab4ce6..45d4da83233d 100644 --- a/.github/workflows/cicd_comp_deployment-phase.yml +++ b/.github/workflows/cicd_comp_deployment-phase.yml @@ -7,7 +7,7 @@ # - Configurable deployment environment # - Use of Docker environments to enable per-deployment environment secrets # - Docker image building and pushing (including dev images) -# - Artifact deployment to JFrog Artifactory +# - Artifact deployment to the S3-compatible Maven repository # - CLI publishing to NPM # - Slack notifications for Docker image and CLI deployments # @@ -116,12 +116,12 @@ on: DOCKER_TOKEN: required: false description: 'Docker.io token' - EE_REPO_USERNAME: + MAVEN_BUNNY_RW_USERNAME: required: false - description: 'Artifactory username' - EE_REPO_PASSWORD: + description: 'BunnyCDN storage-zone name (S3 access key id)' + MAVEN_BUNNY_RW_PASSWORD: required: false - description: 'Artifactory password' + description: 'BunnyCDN storage-zone password (S3 secret key)' SLACK_BOT_TOKEN: required: false description: 'Slack webhook for developers' @@ -315,17 +315,28 @@ jobs: identifier-tag: ${{ steps.docker-tags.outputs.identifier_tag }} extra-tags: ${{ steps.get-sdkman-version.outputs.raw_suffix != '' && format('type=raw,value={0},enable=true', steps.get-sdkman-version.outputs.raw_suffix) || '' }} - # Deploy CLI artifacts to JFrog Artifactory + # Deploy CLI Maven artifacts to the S3-compatible repository # Skipped when java-version is overridden (CLI not built due to GraalVM/Quarkus compatibility) # Skipped when deploy-cli is false (e.g., manual builds should not publish CLI artifacts) - name: CLI Deploy continue-on-error: true id: cli_deploy if: inputs.deploy-cli && steps.get-sdkman-version.outputs.java_suffix == '' - uses: ./.github/actions/core-cicd/deployment/deploy-jfrog + uses: ./.github/actions/core-cicd/deployment/deploy-maven-s3 with: - artifactory-username: ${{ secrets.EE_REPO_USERNAME }} - artifactory-password: ${{ secrets.EE_REPO_PASSWORD }} + # Release builds carry the real version from the release build; other + # environments publish the project version (e.g. 1.0.0-SNAPSHOT). + version: ${{ inputs.omit-environment-prefix && inputs.tag-identifier || '' }} + # This step exists to publish the CLI Maven artifact. The full release + # repository is published by the release phase; restricting here avoids + # uploading every module twice. + modules: 'dotcms-cli' + access-key-id: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + secret-access-key: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} + bucket: ${{ vars.MAVEN_S3_BUCKET }} + prefix: ${{ vars.MAVEN_S3_PREFIX }} + endpoint: ${{ vars.MAVEN_S3_ENDPOINT }} + region: ${{ vars.MAVEN_S3_REGION }} github-token: ${{ secrets.GITHUB_TOKEN }} artifact-run-id: ${{ inputs.artifact-run-id }} diff --git a/.github/workflows/cicd_comp_release-phase.yml b/.github/workflows/cicd_comp_release-phase.yml index 8abf96573747..405f9a7be2a1 100644 --- a/.github/workflows/cicd_comp_release-phase.yml +++ b/.github/workflows/cicd_comp_release-phase.yml @@ -1,7 +1,7 @@ # Release Phase Workflow # # This reusable workflow handles release-specific finalization operations: -# - Deploying artifacts to Artifactory (Maven repository) +# - Publishing Maven artifacts to the BunnyCDN S3-compatible repository # - Generating and uploading Javadocs to S3 # - Triggering plugin repository updates # - Generating and uploading SBOM (Software Bill of Materials) @@ -37,7 +37,7 @@ on: type: string default: ${{ github.run_id }} deploy_artifact: - description: 'Deploy artifact to Artifactory' + description: 'Publish Maven artifacts to the S3 repository' type: boolean default: true upload_javadocs: @@ -63,12 +63,12 @@ on: type: string default: '' secrets: - EE_REPO_USERNAME: + MAVEN_BUNNY_RW_USERNAME: required: false - description: 'Artifactory username' - EE_REPO_PASSWORD: + description: 'BunnyCDN storage-zone name (S3 access key id)' + MAVEN_BUNNY_RW_PASSWORD: required: false - description: 'Artifactory password' + description: 'BunnyCDN storage-zone password (S3 secret key)' AWS_ACCESS_KEY_ID: required: false description: 'AWS access key ID' @@ -80,7 +80,7 @@ on: description: 'CI machine token for GitHub API operations' jobs: - # Deploy release artifacts to Artifactory and S3 + # Publish release artifacts to the S3 repository and upload Javadocs to S3 release-artifacts: name: Release Artifacts runs-on: ubuntu-${{ vars.UBUNTU_RUNNER_VERSION || '24.04' }} @@ -150,11 +150,6 @@ jobs: name: maven-repo${{ steps.java-suffix.outputs.suffix }} path: ~/.m2/repository - - name: Configure Maven Settings - uses: whelk-io/maven-settings-xml-action@v20 - with: - servers: '[{ "id": "dotcms-libs-local", "username": "${{ secrets.EE_REPO_USERNAME }}", "password": "${{ secrets.EE_REPO_PASSWORD }}" }]' - - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: @@ -163,7 +158,10 @@ jobs: aws-region: ${{ env.AWS_REGION }} if: inputs.upload_javadocs == true - - name: Deploy Release Artifacts to Artifactory + # Publish locally (install) instead of deploying. The maven-deploy-plugin + # no longer has an Artifactory target; the S3 publish step below uploads the + # artifacts from ~/.m2/repository, preserving the Maven layout. + - name: Install Release Artifacts run: | # Add changelist suffix for alternate Java versions CHANGELIST_ARG="" @@ -179,8 +177,24 @@ jobs: -Dprod=true \ -DskipTests=true \ ${CHANGELIST_ARG} \ - deploy + install + if: inputs.deploy_artifact == true + + - name: Publish Release Artifacts to S3 if: inputs.deploy_artifact == true + env: + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} + MAVEN_S3_ENDPOINT: ${{ vars.MAVEN_S3_ENDPOINT }} + MAVEN_S3_REGION: ${{ vars.MAVEN_S3_REGION }} + MAVEN_S3_BUCKET: ${{ vars.MAVEN_S3_BUCKET }} + MAVEN_S3_PREFIX: ${{ vars.MAVEN_S3_PREFIX }} + # Alternate Java variants append their changelist (e.g. -java25) to the version. + VERSION: ${{ inputs.release_version }}${{ steps.java-suffix.outputs.suffix }} + run: | + echo "::group::Publish Release Artifacts to S3" + ./.github/scripts/publish-to-s3/publish.sh maven --version "$VERSION" + echo "::endgroup::" - name: Generate and Upload Javadocs run: | @@ -275,7 +289,7 @@ jobs: echo "::endgroup::" # Update GitHub labels for release tracking - # Only updates labels if release-artifacts (Artifactory/Javadocs) succeeded. + # Only updates labels if release-artifacts (S3/Javadocs) succeeded. # The calling workflow's dependency chain ensures deployment also succeeded. release-labeling: name: Release Labeling diff --git a/.github/workflows/cicd_manual_publish-starter.yml b/.github/workflows/cicd_manual_publish-starter.yml index faf707fdc1ca..135ea77daed0 100644 --- a/.github/workflows/cicd_manual_publish-starter.yml +++ b/.github/workflows/cicd_manual_publish-starter.yml @@ -111,21 +111,8 @@ jobs: pull_request_url: ${{ steps.create-pull-request.outputs.pull-request-url }} steps: - name: 'Checkout repository' - if: ${{ github.event.inputs.type == 'empty' && github.event.inputs.dry-run == 'false' }} uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: jfrog/setup-jfrog-cli@v4 - env: - JF_URL: ${{ vars.ARTIFACTORY_URL }} - JF_USER: ${{ secrets.EE_REPO_USERNAME }} - JF_PASSWORD: ${{ secrets.EE_REPO_PASSWORD }} - - - name: 'JFrog CLI context' - run: | - echo "::group::JFrog CLI context" - jf rt ping - echo "::endgroup::" - - name: 'Download artifacts' uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -141,36 +128,38 @@ jobs: id: deploy-artifacts working-directory: ${{ github.workspace }}/starter env: - ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} - ARTIFACTORY_REPO: ${{ vars.ARTIFACTORY_REPO }} - GROUP_ID: com.dotcms + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} + MAVEN_S3_ENDPOINT: ${{ vars.MAVEN_S3_ENDPOINT }} + MAVEN_S3_REGION: ${{ vars.MAVEN_S3_REGION }} + MAVEN_S3_BUCKET: ${{ vars.MAVEN_S3_BUCKET }} + MAVEN_S3_PREFIX: ${{ vars.MAVEN_S3_PREFIX }} + MAVEN_S3_PUBLIC_URL: ${{ vars.MAVEN_S3_PUBLIC_URL }} ARTIFACT_ID: starter - PACKAGING: zip DRY_RUN_MODE: ${{ github.event.inputs.dry-run }} run: | echo "::group::Deploy Artifacts" - - if [[ $DRY_RUN_MODE == true ]]; then - DRY_RUN='--dry-run' - fi - + FILENAME=$(ls -ltr | awk 'END {print $NF}') VERSION="${FILENAME%.*}" SOURCE="./${FILENAME}" - TARGET="${ARTIFACTORY_REPO}/com/dotcms/${ARTIFACT_ID}/${VERSION}/${ARTIFACT_ID}-${FILENAME}" - PROPS="groupId=${GROUP_ID};artifactId=${ARTIFACT_ID};version=${VERSION};packaging=${PACKAGING}" - URL="${ARTIFACTORY_URL}/artifactory/${TARGET}" - + DRY_RUN_ARG="" + + if [[ "$DRY_RUN_MODE" == true ]]; then + DRY_RUN_ARG="--dry-run" + fi + echo "FILENAME=${FILENAME}" echo "VERSION=${VERSION}" - echo "::notice::Uploading ${SOURCE} to ${TARGET} with props ${PROPS}" - jfrog rt u "${SOURCE}" ${TARGET} \ - --target-props="${PROPS}" \ - --flat=false \ - $DRY_RUN - echo "filename=${FILENAME}" >> $GITHUB_OUTPUT - echo "url=${URL}" >> $GITHUB_OUTPUT - echo "::notice::Artifact URL ${URL}" + echo "::notice::Uploading ${SOURCE} to com/dotcms/${ARTIFACT_ID}/${VERSION}/" + + # shellcheck disable=SC2086 + # Reason: DRY_RUN_ARG expands to the optional --dry-run flag + "$GITHUB_WORKSPACE/.github/scripts/publish-to-s3/publish.sh" file \ + --source "${SOURCE}" \ + --key "com/dotcms/${ARTIFACT_ID}/${VERSION}/${ARTIFACT_ID}-${FILENAME}" \ + $DRY_RUN_ARG + echo "::notice::Changelog: ${{ github.event.inputs.changelog }}" echo "::endgroup::" @@ -231,7 +220,7 @@ jobs: BASE_MESSAGE=$(cat <<-EOF > :large_green_circle: *Attention dotters:* a new Starter published! - > This automated script is happy to announce that a new *_${STARTER_TYPE} starter_* :package: \`${ARTIFACT_FILENAME}\` is now available on \`ARTIFACTORY\` :frog:! + > This automated script is happy to announce that a new *_${STARTER_TYPE} starter_* :package: \`${ARTIFACT_FILENAME}\` is now available on the \`dotCMS repository\`! > > :link: ${ARTIFACT_URL} > _Old assets included_: ${OLD_ASSETS} diff --git a/.github/workflows/cicd_release-cli.yml b/.github/workflows/cicd_release-cli.yml index c75fd8733e48..5857d2b403b4 100644 --- a/.github/workflows/cicd_release-cli.yml +++ b/.github/workflows/cicd_release-cli.yml @@ -170,6 +170,11 @@ jobs: digest-mismatch: error path: ${{ github.workspace }}/artifacts pattern: cli-artifacts-* + # TODO(#37567): JReleaser still uploads the CLI runner jar and native + # binaries to Artifactory (tools/dotcms-cli/jreleaser.yml). The + # EE_REPO_* secrets are being retired with the Artifactory + # decommissioning, so this upload must move to the S3 repository (or be + # dropped) before those secrets are removed. - uses: ./.github/actions/core-cicd/maven-job env: JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/legacy-release_maven-release-process.yml b/.github/workflows/legacy-release_maven-release-process.yml index 15ea8262ed34..02508c19ad3f 100644 --- a/.github/workflows/legacy-release_maven-release-process.yml +++ b/.github/workflows/legacy-release_maven-release-process.yml @@ -303,11 +303,6 @@ jobs: id: setup-java uses: ./.github/actions/core-cicd/setup-java - - name: maven-settings-xml-action - uses: whelk-io/maven-settings-xml-action@v20 - with: - servers: '[{ "id": "dotcms-libs-local", "username": "${{ secrets.EE_REPO_USERNAME }}", "password": "${{ secrets.EE_REPO_PASSWORD }}" }]' - - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: @@ -315,15 +310,30 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ env.AWS_REGION }} - - name: Deploy Release + - name: Install Release run: | ./mvnw -ntp \ ${JVM_TEST_MAVEN_OPTS} \ -Dprod=true \ -DskipTests=true \ -DskipITs=true \ - deploy + install + if: github.event.inputs.deploy_artifact == 'true' + + - name: Publish Release Artifacts to S3 if: github.event.inputs.deploy_artifact == 'true' + env: + MAVEN_BUNNY_RW_USERNAME: ${{ secrets.MAVEN_BUNNY_RW_USERNAME }} + MAVEN_BUNNY_RW_PASSWORD: ${{ secrets.MAVEN_BUNNY_RW_PASSWORD }} + MAVEN_S3_ENDPOINT: ${{ vars.MAVEN_S3_ENDPOINT }} + MAVEN_S3_REGION: ${{ vars.MAVEN_S3_REGION }} + MAVEN_S3_BUCKET: ${{ vars.MAVEN_S3_BUCKET }} + MAVEN_S3_PREFIX: ${{ vars.MAVEN_S3_PREFIX }} + VERSION: ${{ needs.prepare-release.outputs.release_version }} + run: | + echo "::group::Publish Release Artifacts to S3" + ./.github/scripts/publish-to-s3/publish.sh maven --version "$VERSION" + echo "::endgroup::" - name: Generate/Push Javadoc run: | diff --git a/.github/workflows/maven-release-process.md b/.github/workflows/maven-release-process.md index 69b4a0e65adb..faec8a3e816d 100644 --- a/.github/workflows/maven-release-process.md +++ b/.github/workflows/maven-release-process.md @@ -40,7 +40,7 @@ This field is used to define the LAST commit hash that you want to include in th ### Deploy Artifacts (default enabled): -This checkbox is enabled by default and the function is to deploy all the dependencies in artifact with the release version to our artifact repo (repo.dotcms.com). We always need to have this enabled in order to have a success release. +This checkbox is enabled by default and the function is to deploy all the dependencies with the release version to our artifact repo (the BunnyCDN S3 repository, `dotcms-repo.b-cdn.net`). We always need to have this enabled in order to have a success release. diff --git a/ONBOARDING.md b/ONBOARDING.md index 2ab8bc715f99..a9c52dc1d5c0 100644 --- a/ONBOARDING.md +++ b/ONBOARDING.md @@ -226,8 +226,8 @@ More detail: [`docs/testing/`](docs/testing/) and [`docs/frontend/TESTING_FRONTE [`dotCMS/src/main/java/com/dotcms/featureflag/FeatureFlagName.java`](dotCMS/src/main/java/com/dotcms/featureflag/FeatureFlagName.java). - **Starter site:** a **starter** is a ZIP of seed content (sites, content types, pages, assets) that dotCMS loads on first startup to give you a populated instance - instead of an empty one. Published starters live in our Artifactory: - [`repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/`](https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/). + instead of an empty one. Published starters live in our Maven repository on + BunnyCDN: [`dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/`](https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/). To pick one, set the `` property in `parent/pom.xml`, drop a renamed `starter.zip` into `dotCMS/target/starter/`, or point `DOT_STARTER_DATA_LOAD` at a starter URL. Full details in [`dotBackendOnboarding.md`](dotBackendOnboarding.md). diff --git a/core-web/libs/sdk/create-app/assets/docker-compose.yml b/core-web/libs/sdk/create-app/assets/docker-compose.yml index fd949299ecc6..16b439e66d66 100644 --- a/core-web/libs/sdk/create-app/assets/docker-compose.yml +++ b/core-web/libs/sdk/create-app/assets/docker-compose.yml @@ -55,7 +55,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: db: condition: service_healthy diff --git a/docker/dev-env/README.md b/docker/dev-env/README.md index e2a2a2a3ec03..24cf55a818c7 100644 --- a/docker/dev-env/README.md +++ b/docker/dev-env/README.md @@ -66,13 +66,13 @@ dotcms/dotcms-dev:nightly ``` #### Start a new environment by downloading a fresh starter -This will download a clean demo starter.zip from the dotCMS artifactory repo and import it into the new environment. This is useful for starting a new dev instance with a clean slate. +This will download a clean demo starter.zip from the dotCMS Maven repository (BunnyCDN) and import it into the new environment. This is useful for starting a new dev instance with a clean slate. ``` docker run --rm \ --pull always \ -p 8443:8443 \ -v $PWD/data:/data \ --e DOTCMS_STARTER_URL=https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip \ +-e DOTCMS_STARTER_URL=https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip \ dotcms/dotcms-dev:nightly ``` diff --git a/docker/docker-compose-examples/cluster-mode/README.md b/docker/docker-compose-examples/cluster-mode/README.md index e56d45fa86a1..4fafe30c759f 100644 --- a/docker/docker-compose-examples/cluster-mode/README.md +++ b/docker/docker-compose-examples/cluster-mode/README.md @@ -23,7 +23,7 @@ The license pack must contain at least two licenses (one for each node in the cl 3. A custom starter can be set through this line (uncomment and change the starter url accordingly): ``` -#"CUSTOM_STARTER_URL": 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#"CUSTOM_STARTER_URL": 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` #### Deploying nodes: diff --git a/docker/docker-compose-examples/cluster-mode/docker-compose-node-1.yml b/docker/docker-compose-examples/cluster-mode/docker-compose-node-1.yml index ce94f09ef5c7..ae45fe37686a 100644 --- a/docker/docker-compose-examples/cluster-mode/docker-compose-node-1.yml +++ b/docker/docker-compose-examples/cluster-mode/docker-compose-node-1.yml @@ -44,7 +44,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - opensearch - db diff --git a/docker/docker-compose-examples/cluster-mode/docker-compose-node-2.yml b/docker/docker-compose-examples/cluster-mode/docker-compose-node-2.yml index 449c43dc6c90..30dc88cc3e96 100644 --- a/docker/docker-compose-examples/cluster-mode/docker-compose-node-2.yml +++ b/docker/docker-compose-examples/cluster-mode/docker-compose-node-2.yml @@ -21,7 +21,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' volumes: #- {local_data_path}:/data/shared #- {license_local_path}/license.zip:/data/shared/assets/license.zip diff --git a/docker/docker-compose-examples/experiments/docker-compose.yml b/docker/docker-compose-examples/experiments/docker-compose.yml index aa8c6db817de..283aa503a715 100644 --- a/docker/docker-compose-examples/experiments/docker-compose.yml +++ b/docker/docker-compose-examples/experiments/docker-compose.yml @@ -117,7 +117,7 @@ services: GLOWROOT_ENABLED: 'true' GLOWROOT_WEB_UI_ENABLED: 'true' DOT_ALLOW_ACCESS_TO_PRIVATE_SUBNETS: 'true' - CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' # Experiments Configuration (Environment Variables Override) # Internal URLs (container-to-container communication) diff --git a/docker/docker-compose-examples/load-db-dump/README.md b/docker/docker-compose-examples/load-db-dump/README.md index a94de2a1e595..255f59706364 100644 --- a/docker/docker-compose-examples/load-db-dump/README.md +++ b/docker/docker-compose-examples/load-db-dump/README.md @@ -33,7 +33,7 @@ dotCMS loads the SQL dump via the `DB_LOAD_DUMP_SQL` environment variable, which 2. A custom starter can be set by uncommenting and updating this line (note: normally not needed when loading from a dump): ```yaml - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` 3. HTTPS is optional. To enable it, uncomment the SSL cert env vars and the `certs` volume mount (a cert can be created with the [mkcert](https://github.com/FiloSottile/mkcert) tool): diff --git a/docker/docker-compose-examples/load-db-dump/docker-compose.yml b/docker/docker-compose-examples/load-db-dump/docker-compose.yml index d8dd3b9bbe89..9bf8a219b097 100644 --- a/docker/docker-compose-examples/load-db-dump/docker-compose.yml +++ b/docker/docker-compose-examples/load-db-dump/docker-compose.yml @@ -64,7 +64,7 @@ services: GLOWROOT_WEB_UI_ENABLED: 'true' # Enable glowroot web ui on localhost. do not use in production #CMS_SSL_CERTIFICATE_FILE: '/certs/localhost.pem' # Can create cert with mkcert tool #CMS_SSL_CERTIFICATE_KEY_FILE: '/certs/localhost-key.pem' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - db - opensearch diff --git a/docker/docker-compose-examples/push-publish/README.md b/docker/docker-compose-examples/push-publish/README.md index c5501ae46fd7..0e2f373fa7b0 100644 --- a/docker/docker-compose-examples/push-publish/README.md +++ b/docker/docker-compose-examples/push-publish/README.md @@ -31,7 +31,7 @@ To reference the receiver service (`dotcms-receiver`), use the `HTTP` protocol w 3. A custom starter can be set through this line (uncomment and change the starter URL accordingly): ```yaml - #"CUSTOM_STARTER_URL": 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #"CUSTOM_STARTER_URL": 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` ### Deploying Nodes diff --git a/docker/docker-compose-examples/push-publish/docker-compose.yml b/docker/docker-compose-examples/push-publish/docker-compose.yml index 3ad244768125..9430d3c5bc3e 100644 --- a/docker/docker-compose-examples/push-publish/docker-compose.yml +++ b/docker/docker-compose-examples/push-publish/docker-compose.yml @@ -50,7 +50,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch-sender:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-sender' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - opensearch-sender - db-sender @@ -115,7 +115,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch-receiver:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-receiver' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - opensearch-receiver - db-receiver diff --git a/docker/docker-compose-examples/scripts/dotcms-get-demo-site-starter-urls.sh b/docker/docker-compose-examples/scripts/dotcms-get-demo-site-starter-urls.sh index 65b7842b73fd..3acc230e21e3 100644 --- a/docker/docker-compose-examples/scripts/dotcms-get-demo-site-starter-urls.sh +++ b/docker/docker-compose-examples/scripts/dotcms-get-demo-site-starter-urls.sh @@ -24,7 +24,7 @@ do dotcms: image: dotcms/dotcms:${version} environment: - CUSTOM_STARTER_URL: https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/${starter_date}/starter-${starter_date}.zip + CUSTOM_STARTER_URL: https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/${starter_date}/starter-${starter_date}.zip EOF done git checkout -q main diff --git a/docker/docker-compose-examples/single-node-debug-mode/README.md b/docker/docker-compose-examples/single-node-debug-mode/README.md index a217d52302b0..6f8ad5383f67 100644 --- a/docker/docker-compose-examples/single-node-debug-mode/README.md +++ b/docker/docker-compose-examples/single-node-debug-mode/README.md @@ -21,7 +21,7 @@ A single instance of dotcms running on port 8080. Database: postgres. Debug mode 3. A custom starter can be set through this line (uncomment and change the starter url accordingly): ``` -#CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` #### Run an example: diff --git a/docker/docker-compose-examples/single-node-debug-mode/docker-compose.yml b/docker/docker-compose-examples/single-node-debug-mode/docker-compose.yml index 6349c80493c8..8d96b4f2402c 100644 --- a/docker/docker-compose-examples/single-node-debug-mode/docker-compose.yml +++ b/docker/docker-compose-examples/single-node-debug-mode/docker-compose.yml @@ -57,7 +57,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - db - opensearch diff --git a/docker/docker-compose-examples/single-node-demo-site/README.md b/docker/docker-compose-examples/single-node-demo-site/README.md index 50d221056f4f..f948c102f32b 100644 --- a/docker/docker-compose-examples/single-node-demo-site/README.md +++ b/docker/docker-compose-examples/single-node-demo-site/README.md @@ -8,7 +8,7 @@ A single instance of dotcms running on port 8080 that will download and install #### Environment setup Specifiy a custom starter that will be included: ``` -CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/xxxxxxxxxx.zip' +CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/xxxxxxxxxx.zip' ``` A local path to license pack can be set here: diff --git a/docker/docker-compose-examples/single-node-demo-site/docker-compose.yml b/docker/docker-compose-examples/single-node-demo-site/docker-compose.yml index 37d94874aa86..255649141605 100644 --- a/docker/docker-compose-examples/single-node-demo-site/docker-compose.yml +++ b/docker/docker-compose-examples/single-node-demo-site/docker-compose.yml @@ -57,7 +57,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - db - opensearch diff --git a/docker/docker-compose-examples/single-node-os-migration/docker-compose.yml b/docker/docker-compose-examples/single-node-os-migration/docker-compose.yml index 4ac1531cf8ae..6e0fba18ed28 100644 --- a/docker/docker-compose-examples/single-node-os-migration/docker-compose.yml +++ b/docker/docker-compose-examples/single-node-os-migration/docker-compose.yml @@ -225,7 +225,7 @@ services: DOT_DOTCMS_CLUSTER_ID: 'dotcms-os-migration' GLOWROOT_ENABLED: 'true' GLOWROOT_WEB_UI_ENABLED: 'true' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: db: condition: service_healthy diff --git a/docker/docker-compose-examples/single-node/README.md b/docker/docker-compose-examples/single-node/README.md index 19ff22b1fafa..b1b17f7757ce 100644 --- a/docker/docker-compose-examples/single-node/README.md +++ b/docker/docker-compose-examples/single-node/README.md @@ -21,7 +21,7 @@ A single instance of dotcms running on port 8080. Database: postgres 3. A custom starter can be set through this line (uncomment and change the starter url accordingly): ``` -#CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` #### Run an example: diff --git a/docker/docker-compose-examples/single-node/docker-compose.yml b/docker/docker-compose-examples/single-node/docker-compose.yml index 9822df0f60c9..4444f3d25aee 100644 --- a/docker/docker-compose-examples/single-node/docker-compose.yml +++ b/docker/docker-compose-examples/single-node/docker-compose.yml @@ -61,7 +61,7 @@ services: GLOWROOT_WEB_UI_ENABLED: 'true' # Enable glowroot web ui on localhost. do not use in production #CMS_SSL_CERTIFICATE_FILE: '/certs/localhost.pem' # Can create cert with mkcert tool #CMS_SSL_CERTIFICATE_KEY_FILE: '/certs/localhost-key.pem' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - db - opensearch diff --git a/docker/docker-compose-examples/with-opensearch-dashboard/README.md b/docker/docker-compose-examples/with-opensearch-dashboard/README.md index d110a9ccee0c..acc329f4b8f3 100644 --- a/docker/docker-compose-examples/with-opensearch-dashboard/README.md +++ b/docker/docker-compose-examples/with-opensearch-dashboard/README.md @@ -21,7 +21,7 @@ A single instance of dotcms running on port 8080. Kibana was included for torubl 3. A custom starter can be set through this line (uncomment and change the starter url accordingly): ``` -#CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` #### Run an example: diff --git a/docker/docker-compose-examples/with-opensearch-dashboard/docker-compose.yml b/docker/docker-compose-examples/with-opensearch-dashboard/docker-compose.yml index f7edbeb37752..1e35793465c8 100644 --- a/docker/docker-compose-examples/with-opensearch-dashboard/docker-compose.yml +++ b/docker/docker-compose-examples/with-opensearch-dashboard/docker-compose.yml @@ -66,7 +66,7 @@ services: DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_DOTCMS_CLUSTER_ID: 'dotcms-production' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - db - opensearch diff --git a/docker/docker-compose-examples/with-redis-session/README.md b/docker/docker-compose-examples/with-redis-session/README.md index f7e5b411c036..715430de17b2 100644 --- a/docker/docker-compose-examples/with-redis-session/README.md +++ b/docker/docker-compose-examples/with-redis-session/README.md @@ -25,7 +25,7 @@ The license pack must contain at least two licenses (one for each node in the cl 3. A custom starter can be set through this line (uncomment and change the starter URL accordingly): ``` -#"CUSTOM_STARTER_URL": 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#"CUSTOM_STARTER_URL": 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` 4. The most important configuration parameters have already been set in both `docker-compose.yml` files. Please refer to the plugin's official repository above for additional ones. diff --git a/docker/docker-compose-examples/with-redis-session/docker-compose-node-1.yml b/docker/docker-compose-examples/with-redis-session/docker-compose-node-1.yml index 40a1d93738b3..8a9a99f3240f 100644 --- a/docker/docker-compose-examples/with-redis-session/docker-compose-node-1.yml +++ b/docker/docker-compose-examples/with-redis-session/docker-compose-node-1.yml @@ -51,7 +51,7 @@ services: DOT_ES_AUTH_BASIC_PASSWORD: 'admin' DOT_ES_ENDPOINTS: 'https://opensearch:9200' DOT_INITIAL_ADMIN_PASSWORD: 'admin' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - opensearch - db diff --git a/docker/docker-compose-examples/with-redis/README.md b/docker/docker-compose-examples/with-redis/README.md index 0aa9cf464bfc..fd1318936d56 100644 --- a/docker/docker-compose-examples/with-redis/README.md +++ b/docker/docker-compose-examples/with-redis/README.md @@ -25,7 +25,7 @@ The license pack must contain at least two licenses (one for each node in the cl 3. A custom starter can be set through this line (uncomment and change the starter url accordingly): ``` -#"CUSTOM_STARTER_URL": 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' +#"CUSTOM_STARTER_URL": 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` #### Deploying nodes: diff --git a/docker/docker-compose-examples/with-redis/docker-compose-node-1.yml b/docker/docker-compose-examples/with-redis/docker-compose-node-1.yml index 060d50710b8d..60fd17ebd699 100644 --- a/docker/docker-compose-examples/with-redis/docker-compose-node-1.yml +++ b/docker/docker-compose-examples/with-redis/docker-compose-node-1.yml @@ -48,7 +48,7 @@ services: DOT_DOT_PUBSUB_PROVIDER_OVERRIDE: 'com.dotcms.dotpubsub.RedisPubSubImpl' DOT_REDIS_LETTUCECLIENT_URLS: 'redis://MY_SECRET_P4SS@redis' DOT_CACHE_DEFAULT_CHAIN: 'com.dotmarketing.business.cache.provider.caffine.CaffineCache,com.dotcms.cache.lettuce.RedisCache' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - opensearch - db diff --git a/docker/docker-compose-examples/with-redis/docker-compose-node-2.yml b/docker/docker-compose-examples/with-redis/docker-compose-node-2.yml index bb810107b685..4636eb4c14f5 100644 --- a/docker/docker-compose-examples/with-redis/docker-compose-node-2.yml +++ b/docker/docker-compose-examples/with-redis/docker-compose-node-2.yml @@ -26,7 +26,7 @@ services: DOT_DOT_PUBSUB_PROVIDER_OVERRIDE: 'com.dotcms.dotpubsub.RedisPubSubImpl' DOT_REDIS_LETTUCECLIENT_URLS: 'redis://MY_SECRET_P4SS@redis' DOT_CACHE_DEFAULT_CHAIN: 'com.dotmarketing.business.cache.provider.caffine.CaffineCache,com.dotcms.cache.lettuce.RedisCache' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' volumes: #- {local_data_path}:/data/shared #- {license_local_path}/license.zip:/data/shared/assets/license.zip diff --git a/docs/cli/CLI_BUILD_SYSTEM.md b/docs/cli/CLI_BUILD_SYSTEM.md index 9069a6f9a6fb..1934fbcfc892 100644 --- a/docs/cli/CLI_BUILD_SYSTEM.md +++ b/docs/cli/CLI_BUILD_SYSTEM.md @@ -361,12 +361,12 @@ tools/dotcms-cli/cli/target/distributions/ ``` ### Manual JAR Download -**Repository**: `https://repo.dotcms.com/artifactory/libs-snapshot-local/com/dotcms/dotcms-cli/` +**Repository**: `https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/` **Usage**: ```bash # Download and run -wget https://repo.dotcms.com/artifactory/libs-snapshot-local/com/dotcms/dotcms-cli/latest/dotcms-cli.jar +wget https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/latest/dotcms-cli.jar java -jar dotcms-cli.jar --help ``` diff --git a/dotBackendOnboarding.md b/dotBackendOnboarding.md index b481805254bf..200bdc99b7fa 100644 --- a/dotBackendOnboarding.md +++ b/dotBackendOnboarding.md @@ -195,7 +195,7 @@ Advanced configurations allow you to customize and optimize your development env * Another way is to set up the following environment variable: ```sh - DOT_STARTER_DATA_LOAD = 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + DOT_STARTER_DATA_LOAD = 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' ``` Finally, once the change is made (using one of the previous options), remember to **recompile** the code so that the changes will take effect, running the following command: diff --git a/dotCMS/src/docker-compose/local-run/docker-compose.yml b/dotCMS/src/docker-compose/local-run/docker-compose.yml index 4097b06a947f..18f90e06e0ab 100644 --- a/dotCMS/src/docker-compose/local-run/docker-compose.yml +++ b/dotCMS/src/docker-compose/local-run/docker-compose.yml @@ -53,7 +53,7 @@ services: 'CMS_HEAP_SIZE': '1g' - # "CUSTOM_STARTER_URL": 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + # "CUSTOM_STARTER_URL": 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: db: condition: service_healthy diff --git a/parent/pom.xml b/parent/pom.xml index cac42a7c58f7..b51390d019e2 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1991,6 +1991,13 @@ + true @@ -1999,47 +2006,24 @@ false dotcms-libs - https://repo.dotcms.com/artifactory/libs-release - - - - false - - - false - - dotcms-libs-snapshot-local - IDotCMS libs Snapshots - https://repo.dotcms.com/artifactory/libs-snapshot-local + https://dotcms-repo.b-cdn.net/libs-release + + true + false dotcms-libs - https://repo.dotcms.com/artifactory/libs-release - - - - true - - dotcms-libs-snapshot - https://repo.dotcms.com/artifactory/libs-snapshot + https://dotcms-repo.b-cdn.net/libs-release - - - dotcms-libs-local - DotCMS libs Release - https://repo.dotcms.com/artifactory/libs-release-local - - - dotcms-libs-snapshot-local - IDotCMS libs Snapshots - https://repo.dotcms.com/artifactory/libs-snapshot-local - - - + diff --git a/pom.xml b/pom.xml index 5f5569400dd3..2665898d4331 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ false dotcms-libs - https://repo.dotcms.com/artifactory/libs-release + https://dotcms-repo.b-cdn.net/libs-release @@ -48,16 +48,11 @@ local-site-deployment file://${project.build.directory}/staging - - dotcms-libs-local - DotCMS libs Release - https://repo.dotcms.com/artifactory/libs-release-local - - - dotcms-libs-snapshot-local - DotCMS libs Snapshots - https://repo.dotcms.com/artifactory/libs-snapshot-local - + diff --git a/tools/dotcms-cli/README.md b/tools/dotcms-cli/README.md index 929a4b37d365..aa7d72b72596 100644 --- a/tools/dotcms-cli/README.md +++ b/tools/dotcms-cli/README.md @@ -14,7 +14,7 @@ npm install -g @dotcms/dotcli ``` ### Manual JAR Download -1. Download the CLI: The dotCMS CLI is delivered as an uber jar that can be downloaded from [here](https://repo.dotcms.com/artifactory/libs-snapshot-local/com/dotcms/dotcms-cli/). +1. Download the CLI: The dotCMS CLI is delivered as an uber jar that can be downloaded from [here](https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/). Once downloaded, you just need to run it with: ```shell script diff --git a/tools/dotcms-cli/action/.github/workflows/main.yml b/tools/dotcms-cli/action/.github/workflows/main.yml index 5cf1295be521..038f4efb409a 100644 --- a/tools/dotcms-cli/action/.github/workflows/main.yml +++ b/tools/dotcms-cli/action/.github/workflows/main.yml @@ -20,9 +20,9 @@ jobs: run: | echo "::group::Get dotCLI runner" - curl -o maven-metadata.xml "https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/dotcms-cli/maven-metadata.xml" + curl -o maven-metadata.xml "https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/maven-metadata.xml" LATEST_VERSION=$(xmllint --xpath "string(//versioning/latest)" maven-metadata.xml) - URL="https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/dotcms-cli/${LATEST_VERSION}/dotcms-cli-${LATEST_VERSION}-runner.jar" + URL="https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/${LATEST_VERSION}/dotcms-cli-${LATEST_VERSION}-runner.jar" echo "::notice::DOTCLI RUNNER: $URL" echo "url=$URL" >> "$GITHUB_OUTPUT" @@ -63,7 +63,7 @@ jobs: # Check if DOT_CLI_VERSION is set (version number only) if [ -n "${{ env.DOT_CLI_VERSION }}" ]; then VERSION="${{ env.DOT_CLI_VERSION }}" - RESOLVED_URL="https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/dotcms-cli/${VERSION}/dotcms-cli-${VERSION}-runner.jar" + RESOLVED_URL="https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/dotcms-cli/${VERSION}/dotcms-cli-${VERSION}-runner.jar" echo "::notice::Using specified version: $VERSION" echo "::notice::Resolved URL: $RESOLVED_URL" echo "resolved-url=$RESOLVED_URL" >> "$GITHUB_OUTPUT" diff --git a/tools/dotcms-cli/api-data-model/src/test/resources/docker-compose.yaml b/tools/dotcms-cli/api-data-model/src/test/resources/docker-compose.yaml index bc3cf1e68399..3ce9897e0cb9 100644 --- a/tools/dotcms-cli/api-data-model/src/test/resources/docker-compose.yaml +++ b/tools/dotcms-cli/api-data-model/src/test/resources/docker-compose.yaml @@ -49,7 +49,7 @@ services: DOT_ES_AUTH_BASIC_PASSWORD: 'admin' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_ES_ENDPOINTS: 'http://elasticsearch:9200' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - elasticsearch - postgres diff --git a/tools/dotcms-cli/cli/src/test/resources/docker-compose.yaml b/tools/dotcms-cli/cli/src/test/resources/docker-compose.yaml index 67908b54d275..0d56241caf53 100644 --- a/tools/dotcms-cli/cli/src/test/resources/docker-compose.yaml +++ b/tools/dotcms-cli/cli/src/test/resources/docker-compose.yaml @@ -49,7 +49,7 @@ services: DOT_ES_AUTH_BASIC_PASSWORD: 'admin' DOT_INITIAL_ADMIN_PASSWORD: 'admin' DOT_ES_ENDPOINTS: 'http://elasticsearch:9200' - #CUSTOM_STARTER_URL: 'https://repo.dotcms.com/artifactory/libs-release-local/com/dotcms/starter/20260630/starter-20260630.zip' + #CUSTOM_STARTER_URL: 'https://dotcms-repo.b-cdn.net/libs-release/com/dotcms/starter/20260630/starter-20260630.zip' depends_on: - elasticsearch - postgres From 87c60bd0bb102d6b3d64adc5333fcf8187229616 Mon Sep 17 00:00:00 2001 From: Will Ezell Date: Wed, 16 Sep 2026 08:51:18 -0400 Subject: [PATCH 02/12] fix(publish-to-s3): filter PRE lines when rebuilding maven-metadata.xml aws s3 ls prints file entries as '