From 10e41eacaa4b817ce68ee25c7d5e1c2ca1eb2c8e Mon Sep 17 00:00:00 2001 From: Arturo Zarazua Delgadillo Date: Thu, 29 Oct 2026 17:01:25 +0000 Subject: [PATCH] chore: add Kokoro release config and script for OSS Exit Gate --- .kokoro/release.cfg | 13 +++++ .kokoro/release.sh | 129 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 .kokoro/release.cfg create mode 100755 .kokoro/release.sh diff --git a/.kokoro/release.cfg b/.kokoro/release.cfg new file mode 100644 index 0000000000..c725d48b91 --- /dev/null +++ b/.kokoro/release.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +build_file: "github/googleads-java-lib/.kokoro/release.sh" + +# Default to DRY_RUN=true for safety; can be overridden via API or UI +env_vars: { + key: "DRY_RUN" + value: "true" +} + +container_properties { + docker_image: "us-central1-docker.pkg.dev/kokoro-container-bakery/kokoro/ubuntu/ubuntu2204/full:current" +} diff --git a/.kokoro/release.sh b/.kokoro/release.sh new file mode 100755 index 0000000000..bd59209e37 --- /dev/null +++ b/.kokoro/release.sh @@ -0,0 +1,129 @@ +#!/bin/bash +set -euo pipefail + +# ============================================================================== +# SECURITY NOTICE: DO NOT ADD 'set -x' TO THIS SCRIPT! +# This script handles PGP signing keys and passphrases from Secret Manager. +# ============================================================================== +set +x + +DRY_RUN="${DRY_RUN:-true}" +if [[ "${DRY_RUN}" != "true" && "${DRY_RUN}" != "false" ]]; then + echo "ERROR: DRY_RUN must be 'true' or 'false' (got '${DRY_RUN}')." >&2 + exit 1 +fi + +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "${REPO_DIR}" + +echo "=== Building and Releasing from: ${REPO_DIR} (DRY_RUN=${DRY_RUN}) ===" + +if [[ ! -d "/usr/lib/jvm/java-17-openjdk-amd64" ]]; then + echo "ERROR: Kokoro worker missing expected OpenJDK 17 at /usr/lib/jvm/java-17-openjdk-amd64" >&2 + exit 1 +fi +export PATH="/usr/lib/jvm/java-17-openjdk-amd64/bin:${PATH}" +unset JAVA_HOME + +EXIT_GATE_PROJECT="oss-exit-gate-prod" +EXIT_GATE_LOCATION="us" +EXIT_GATE_REPOSITORY="googleads-java-lib--mavencentral" + +PACKAGES=( + "client-libs-parent" + "ads-lib" + "ads-lib-appengine" + "ads-lib-axis" + "dfp-appengine" + "dfp-axis" +) + +for pkg in "${PACKAGES[@]}"; do + full_pkg="com.google.api-ads:${pkg}" + if gcloud artifacts packages describe "${full_pkg}" \ + --project="${EXIT_GATE_PROJECT}" \ + --location="${EXIT_GATE_LOCATION}" \ + --repository="${EXIT_GATE_REPOSITORY}" &>/dev/null; then + echo "=== Deleting existing package '${full_pkg}' from Exit Gate staging repository ===" + gcloud artifacts packages delete "${full_pkg}" \ + --project="${EXIT_GATE_PROJECT}" \ + --location="${EXIT_GATE_LOCATION}" \ + --repository="${EXIT_GATE_REPOSITORY}" \ + --quiet + fi +done + +if [[ -z "${SIGNING_KEY:-}" ]]; then + export SIGNING_KEY="$(gcloud secrets versions access latest \ + --secret="bam-devrel-maven-gpg-key" \ + --project="bam-devrel-releases" 2>/dev/null || \ + gcloud secrets versions access latest \ + --secret="google_ads_java_gpg_secring" \ + --project="bam-devrel-releases")" +fi + +if [[ -z "${SIGNING_PASSWORD:-}" ]]; then + export SIGNING_PASSWORD="$(gcloud secrets versions access latest \ + --secret="bam-devrel-maven-gpg-password" \ + --project="bam-devrel-releases" 2>/dev/null || \ + gcloud secrets versions access latest \ + --secret="google_ads_java_gpg_passphrase" \ + --project="bam-devrel-releases" 2>/dev/null || true)" +fi + +export GNUPGHOME="$(mktemp -d)" +chmod 700 "${GNUPGHOME}" +SETTINGS_XML="$(mktemp --suffix=.xml)" +trap 'rm -rf "${GNUPGHOME}" "${SETTINGS_XML}"' EXIT + +printf '%s' "${SIGNING_KEY}" | gpg --batch --import + +ACCESS_TOKEN="$(gcloud auth print-access-token)" +cat < "${SETTINGS_XML}" + + + + exit-gate + oauth2accesstoken + ${ACCESS_TOKEN} + + + +EOF +unset ACCESS_TOKEN + +mvn clean org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy \ + --settings "${SETTINGS_XML}" \ + -DperformRelease=true \ + -Dgpg.passphrase="${SIGNING_PASSWORD}" \ + -DaltDeploymentRepository="exit-gate::default::https://us-maven.pkg.dev/${EXIT_GATE_PROJECT}/${EXIT_GATE_REPOSITORY}" + +if [[ "${DRY_RUN}" == "true" ]]; then + echo "=== DRY_RUN is enabled. Artifacts staged in Artifact Registry. ===" + exit 0 +fi + +cat < manifest.json +{ + "publish_all": false, + "publishing_groups": [ + { + "namespace": "com.google.api-ads", + "packages": [ + { "name": "client-libs-parent" }, + { "name": "ads-lib" }, + { "name": "ads-lib-appengine" }, + { "name": "ads-lib-axis" }, + { "name": "dfp-appengine" }, + { "name": "dfp-axis" } + ] + } + ] +} +EOF + +EXIT_GATE_BUCKET="gs://oss-exit-gate-prod-projects-bucket/googleads-java-lib/mavencentral/manifests" +MANIFEST_NAME="manifest-$(date --utc +%Y%m%d%H%M%S'UTC').json" + +echo "=== Uploading manifest to ${EXIT_GATE_BUCKET}/${MANIFEST_NAME} ===" +gcloud storage cp manifest.json "${EXIT_GATE_BUCKET}/${MANIFEST_NAME}"