diff --git a/.github/scripts/release.sh b/.github/scripts/release.sh new file mode 100755 index 00000000..3076cd2b --- /dev/null +++ b/.github/scripts/release.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Releases artifactory-java-client to Artifactory (releases repo), JFrog Distribution and Maven +# Central, then bumps the dev branch to the next development version. +# +# Runnable from GitHub Actions (.github/workflows/release.yml) or directly on a developer machine. +# Expected environment variables: +# NEXT_VERSION - version to release (e.g. 2.21.0) +# NEXT_DEVELOPMENT_VERSION - next development version to bump to after release (e.g. 2.22.x-SNAPSHOT) +# AUDIT_FAIL - "true"/"false", fail the build if `jf audit` finds violations (default: false) +# IL_AUTOMATION_TOKEN - GitHub token used to push commits/tags to origin +# ARTIFACTORY_URL - Artifactory base URL +# ARTIFACTORY_USER - Artifactory username +# ARTIFACTORY_APIKEY - Artifactory API key/password +# MVN_CENTRAL_SIGNING_KEY - base64-encoded GPG signing key for Maven Central artifacts +# ORG_GRADLE_PROJECT_signingPassword - passphrase for the GPG signing key +# ORG_GRADLE_PROJECT_sonatypeUsername - Sonatype (Maven Central) username +# ORG_GRADLE_PROJECT_sonatypePassword - Sonatype (Maven Central) password +# JFROG_CLI_BUILD_NAME, JFROG_CLI_BUILD_NUMBER, JFROG_CLI_BUILD_PROJECT +# - build-info coordinates consumed by `jf rt` commands + +# Configure git +git config user.name "jfrog-ecosystem-integration" +git config user.email "jfrog-ecosystem-integration@jfrog.com" +git checkout master +git remote set-url origin https://${IL_AUTOMATION_TOKEN}@github.com/jfrog/artifactory-client-java.git + +# Check required versions +echo "Checking variables" +test -n "$NEXT_VERSION" -a "$NEXT_VERSION" != "0.0.0" +test -n "$NEXT_DEVELOPMENT_VERSION" -a "$NEXT_DEVELOPMENT_VERSION" != "0.0.x-SNAPSHOT" + +# Configure JFrog CLI +jf c rm --quiet +jf c add internal --url=$ARTIFACTORY_URL --access-token=$ARTIFACTORY_APIKEY +jf gradlec --use-wrapper --deploy-ivy-desc=false --deploy-maven-desc --uses-plugin --repo-resolve ecosys-maven-remote --repo-deploy ecosys-oss-release-local + +# Sync changes with dev +git merge origin/dev + +# Run audit +# `|| true` ignores SAST scanner infrastructure failures, matching the original pipeline's comment +# that GLIBC_2.34 was not available on the pipeline node. +jf audit --fail=${AUDIT_FAIL:-false} || true + +# Update version +sed -i "s/\(currentVersion=\).*\$/\1${NEXT_VERSION}/" gradle.properties + +# Commit and tag release +git commit -am "[artifactory-release] Release version ${NEXT_VERSION} [skipRun]" --allow-empty +git tag ${NEXT_VERSION} +git push +git push --tags + +# Build and publish to Artifactory +export ORG_GRADLE_PROJECT_signingKey=$(echo "${MVN_CENTRAL_SIGNING_KEY}" | base64 -d) +jf gradle clean aP -x test +jf rt bag && jf rt bce +jf rt bp + +# Distribute release bundle +jf ds rbc ecosystem-artifactory-client-java $NEXT_VERSION --spec=./release/specs/prod-rbc-filespec.json --spec-vars="version=$NEXT_VERSION" --sign +jf ds rbd ecosystem-artifactory-client-java $NEXT_VERSION --site="releases.jfrog.io" --sync + +# Publish to Maven Central +export ORG_GRADLE_PROJECT_signingKey=$(echo "${MVN_CENTRAL_SIGNING_KEY}" | base64 -d) +./gradlew clean build publishToSonatype closeAndReleaseSonatypeStagingRepository -x test + +# Update next development version +git clean -fd +git checkout dev -f +git merge origin/master +sed -i "s/\(currentVersion=\).*\$/\1${NEXT_DEVELOPMENT_VERSION}/" gradle.properties +git commit -am "[artifactory-release] Next development version [skipRun]" +git push diff --git a/.github/scripts/snapshot.sh b/.github/scripts/snapshot.sh new file mode 100755 index 00000000..914dca0d --- /dev/null +++ b/.github/scripts/snapshot.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Publishes a snapshot build of artifactory-java-client to Artifactory and JFrog Distribution. +# +# Runnable from GitHub Actions (.github/workflows/snapshot.yml) or directly on a developer machine. +# Expected environment variables: +# ARTIFACTORY_URL - Artifactory base URL +# ARTIFACTORY_USER - Artifactory username +# ARTIFACTORY_APIKEY - Artifactory API key/password +# RUN_NUMBER - unique build number, used for build-info and as the distributed release +# bundle version (e.g. the GitHub Actions run number) +# JFROG_CLI_BUILD_NAME, JFROG_CLI_BUILD_NUMBER, JFROG_CLI_BUILD_PROJECT +# - build-info coordinates consumed by `jf rt` commands + +# Configure JFrog CLI +jf c rm --quiet +jf c add internal --url=$ARTIFACTORY_URL --access-token=$ARTIFACTORY_APIKEY +jf gradlec --use-wrapper --deploy-ivy-desc=false --deploy-maven-desc --uses-plugin --repo-resolve ecosys-maven-remote --repo-deploy ecosys-oss-snapshot-local + +# Run audit +jf audit + +# Delete former snapshots +# Ensures the release bundle will not contain stale artifacts from a previous snapshot. +jf rt del "ecosys-oss-snapshot-local/org/jfrog/artifactory/client/artifactory-java-client-api/*" --quiet +jf rt del "ecosys-oss-snapshot-local/org/jfrog/artifactory/client/artifactory-java-client-services/*" --quiet +jf rt del "ecosys-oss-snapshot-local/org/jfrog/artifactory/client/artifactory-java-client-httpClient/*" --quiet + +# Run install and publish +jf gradle clean aP -x test +jf rt bag && jf rt bce +jf rt bp + +# Distribute release bundle +jf ds rbc ecosystem-artifactory-java-client-snapshot $RUN_NUMBER --spec=./release/specs/dev-rbc-filespec.json --sign +jf ds rbd ecosystem-artifactory-java-client-snapshot $RUN_NUMBER --site="releases.jfrog.io" --sync diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..780fcca0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,65 @@ +name: Release + +# Manual release of artifactory-java-client to Artifactory (releases repo), JFrog Distribution and Maven Central. +# Ported from the JFrog Pipelines `release_java_client` pipeline (release/pipelines.release.yml), now EOL. +on: + workflow_dispatch: + inputs: + next_version: + description: "Version to release (e.g. 2.21.0)" + required: true + next_development_version: + description: "Next development version to bump to after release (e.g. 2.22.x-SNAPSHOT)" + required: true + audit_fail: + description: "Fail the build if `jf audit` finds violations" + required: false + default: "false" + +env: + CI: true + JFROG_BUILD_STATUS: PASS + JFROG_CLI_BUILD_NAME: ecosystem-artifactory-client-java-release + JFROG_CLI_BUILD_NUMBER: ${{ github.run_number }} + JFROG_CLI_BUILD_PROJECT: ecosys + GRADLE_OPTS: -Dorg.gradle.daemon=false + NEXT_VERSION: ${{ github.event.inputs.next_version }} + NEXT_DEVELOPMENT_VERSION: ${{ github.event.inputs.next_development_version }} + AUDIT_FAIL: ${{ github.event.inputs.audit_fail }} + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: master + fetch-depth: 0 + + - name: Install Java + uses: actions/setup-java@v4 + with: + java-version: "8" + distribution: "zulu" + + - name: Setup JFrog CLI + uses: jfrog/setup-jfrog-cli@v4 + # Deliberate behavior change from the original pipeline: the pipeline bootstrapped the CLI via + # `curl -fL https://install-cli.jfrog.io | sh`; here we use the official setup action instead. + + # Runs the full release: configures git and the JFrog CLI, syncs with dev, audits, bumps the + # version, tags and pushes the release commit, builds and publishes to Artifactory, distributes + # the release bundle, publishes to Maven Central, then bumps dev to the next development version. + # See .github/scripts/release.sh - the same script can be run locally by exporting the env vars below. + - name: Run release + env: + IL_AUTOMATION_TOKEN: ${{ secrets.IL_AUTOMATION_TOKEN }} + ARTIFACTORY_URL: ${{ secrets.ARTIFACTORY_URL }} + ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }} + ARTIFACTORY_APIKEY: ${{ secrets.ARTIFACTORY_APIKEY }} + MVN_CENTRAL_SIGNING_KEY: ${{ secrets.MVN_CENTRAL_SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.MVN_CENTRAL_SIGNING_PASSWORD }} + ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.MVN_CENTRAL_USER }} + ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.MVN_CENTRAL_PASSWORD }} + run: .github/scripts/release.sh diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 00000000..589d2982 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,58 @@ +name: Snapshot + +# Publishes a snapshot build of artifactory-java-client to Artifactory and JFrog Distribution on every push to dev. +# Ported from the JFrog Pipelines `create_artifactory_java_client_snapshot` pipeline +# (release/pipelines.snapshot.yml), now EOL. The pipeline's GitRepo resource (javaClientSnapshotGit, +# see release/pipelines.resources.yml) tracked the `dev` branch, so that's what triggers this workflow. +on: + push: + branches: + - dev + workflow_dispatch: {} + +env: + CI: true + JFROG_BUILD_STATUS: PASS + JFROG_CLI_BUILD_NAME: ecosystem-artifactory-client-java-dev + JFROG_CLI_BUILD_NUMBER: ${{ github.run_number }} + JFROG_CLI_BUILD_PROJECT: ecosys + GRADLE_OPTS: -Dorg.gradle.daemon=false + +jobs: + snapshot: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: dev + + - name: Install Java + uses: actions/setup-java@v4 + with: + java-version: "8" + distribution: "zulu" + + - name: Cache Gradle files + uses: actions/cache@v4 + with: + path: .gradle + key: ${{ runner.os }}-gradle-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Setup JFrog CLI + uses: jfrog/setup-jfrog-cli@v4 + # Deliberate behavior change from the original pipeline: the pipeline bootstrapped the CLI via + # `curl -fL https://install-cli.jfrog.io | sh`; here we use the official setup action instead. + + # Configures the JFrog CLI, audits, deletes stale snapshot artifacts, builds and publishes to + # Artifactory, then distributes the release bundle. + # See .github/scripts/snapshot.sh - the same script can be run locally by exporting the env vars below. + - name: Run snapshot + env: + ARTIFACTORY_URL: ${{ secrets.ARTIFACTORY_URL }} + ARTIFACTORY_USER: ${{ secrets.ARTIFACTORY_USER }} + ARTIFACTORY_APIKEY: ${{ secrets.ARTIFACTORY_APIKEY }} + RUN_NUMBER: ${{ github.run_number }} + run: .github/scripts/snapshot.sh