diff --git a/.github/workflows/release-codegen-3.yml b/.github/workflows/release-codegen-3.yml new file mode 100644 index 00000000000..aca0ebcb2fd --- /dev/null +++ b/.github/workflows/release-codegen-3.yml @@ -0,0 +1,534 @@ +name: Release Codegen 3.0 + +# Manual release workflow for codegen 3.0.0, with optional generators release. +on: + workflow_dispatch: + inputs: + release_generators: + description: 'Release swagger-codegen-generators together with codegen' + required: true + default: 'false' + type: choice + options: + - 'false' + - 'true' + skip_maven_deploy: + description: 'Skip Maven deploy for recovery when artifacts are already published' + required: true + default: 'false' + type: choice + options: + - 'false' + - 'true' + skip_docker_push: + description: 'Skip Docker build and push' + required: true + default: 'false' + type: choice + options: + - 'false' + - 'true' + skip_rancher_deploy: + description: 'Skip Swagger online generator deployment' + required: true + default: 'false' + type: choice + options: + - 'false' + - 'true' + previous_generators_version: + description: 'Generator release or snapshot version used to bootstrap the first codegen build when releasing generators' + required: false + type: string + codegen_generators_bootstrap_version: + description: 'Codegen release or snapshot version used to build generators' + required: false + type: string + dry_run: + description: 'Run validation and builds without deploy, Docker push, or Rancher deploy (post-release PR is still created)' + required: true + default: 'true' + type: choice + options: + - 'true' + - 'false' + +permissions: + contents: read + +jobs: + validate-branch: + if: github.ref_name != '3.0.0' + runs-on: ubuntu-latest + steps: + - name: Require 3.0.0 branch + run: | + echo "This workflow can run only from branch 3.0.0 (current: ${GITHUB_REF_NAME})." + exit 1 + + validate: + # Single source of truth for resolved versions and release-mode decisions. + if: github.ref_name == '3.0.0' + runs-on: ubuntu-latest + outputs: + codegen_version: ${{ steps.resolve.outputs.codegen_version }} + generators_version: ${{ steps.resolve.outputs.generators_version }} + codegen_build_generators_version: ${{ steps.resolve.outputs.codegen_build_generators_version }} + bootstrap_generators_version: ${{ steps.resolve.outputs.bootstrap_generators_version }} + bootstrap_codegen_version: ${{ steps.resolve.outputs.bootstrap_codegen_version }} + next_codegen_snapshot_version: ${{ steps.resolve.outputs.next_codegen_snapshot_version }} + generators_deploy_needed: ${{ steps.resolve.outputs.generators_deploy_needed }} + steps: + - name: Checkout swagger-codegen 3.0.0 + uses: actions/checkout@v6 + with: + ref: 3.0.0 + + - name: Checkout swagger-codegen-generators + if: inputs.release_generators == 'true' + uses: actions/checkout@v6 + with: + repository: swagger-api/swagger-codegen-generators + ref: master + path: generators-repo + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_PRIVATE_PASSPHRASE }} + with: + java-version: '17' + distribution: temurin + server-id: central + cache: maven + overwrite-settings: false + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Add Central Portal snapshot repository + uses: s4u/maven-settings-action@v4.0.0 + with: + repositories: '[{"id":"central-portal-snapshots","name":"Sonatype Central Portal snapshots","url":"https://central.sonatype.com/repository/maven-snapshots/","releases":{"enabled":false},"snapshots":{"enabled":true}}]' + servers: '[{"id":"central","username":"${{ secrets.MAVEN_CENTRAL_USERNAME }}","password":"${{ secrets.MAVEN_CENTRAL_PASSWORD }}"}]' + + - name: Validate and resolve versions + id: resolve + # Computes build/deploy coordinates and enforces safe release preconditions. + env: + RELEASE_GENERATORS: ${{ inputs.release_generators }} + PREVIOUS_GENERATORS_VERSION: ${{ inputs.previous_generators_version }} + CODEGEN_GENERATORS_BOOTSTRAP_VERSION: ${{ inputs.codegen_generators_bootstrap_version }} + SKIP_MAVEN_DEPLOY: ${{ inputs.skip_maven_deploy }} + DRY_RUN: ${{ inputs.dry_run }} + run: bash CI/release/resolve-release-versions.sh + + bootstrap_codegen: + # Break circular dependency: build codegen first with previous generators version. + runs-on: ubuntu-latest + needs: validate + if: inputs.release_generators == 'true' && needs.validate.outputs.generators_deploy_needed == 'true' + steps: + - name: Checkout swagger-codegen 3.0.0 + uses: actions/checkout@v6 + with: + ref: 3.0.0 + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + with: + java-version: '17' + distribution: temurin + server-id: central + cache: maven + overwrite-settings: false + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: Add Central Portal snapshot repository + uses: s4u/maven-settings-action@v4.0.0 + with: + repositories: '[{"id":"central-portal-snapshots","name":"Sonatype Central Portal snapshots","url":"https://central.sonatype.com/repository/maven-snapshots/","releases":{"enabled":false},"snapshots":{"enabled":true}}]' + servers: '[{"id":"central","username":"${{ secrets.MAVEN_CENTRAL_USERNAME }}","password":"${{ secrets.MAVEN_CENTRAL_PASSWORD }}"}]' + + - name: Build codegen with bootstrap generators + run: | + bash CI/release/build-codegen-with-generators.sh "${{ needs.validate.outputs.bootstrap_generators_version }}" + + generators: + # Build/deploy generators only when this run is responsible for publishing them. + runs-on: ubuntu-latest + needs: + - validate + - bootstrap_codegen + if: inputs.release_generators == 'true' && needs.validate.outputs.generators_deploy_needed == 'true' + steps: + - name: Checkout swagger-codegen-generators + uses: actions/checkout@v6 + with: + repository: swagger-api/swagger-codegen-generators + ref: master + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_PRIVATE_PASSPHRASE }} + with: + java-version: '17' + distribution: temurin + server-id: central + cache: maven + overwrite-settings: false + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Add Central Portal snapshot repository + uses: s4u/maven-settings-action@v4.0.0 + with: + repositories: '[{"id":"central-portal-snapshots","name":"Sonatype Central Portal snapshots","url":"https://central.sonatype.com/repository/maven-snapshots/","releases":{"enabled":false},"snapshots":{"enabled":true}}]' + servers: '[{"id":"central","username":"${{ secrets.MAVEN_CENTRAL_USERNAME }}","password":"${{ secrets.MAVEN_CENTRAL_PASSWORD }}"}]' + + - name: Build swagger-codegen-generators + run: | + mvn -B -U clean install \ + -Dswagger-codegen-version="${{ needs.validate.outputs.bootstrap_codegen_version }}" + + - name: Deploy swagger-codegen-generators + # Recovery controls: deploy can be skipped with dry_run/skip_maven_deploy. + if: inputs.skip_maven_deploy != 'true' && inputs.dry_run != 'true' + run: mvn --no-transfer-progress -B -Prelease deploy + + - name: Skip swagger-codegen-generators deploy + if: inputs.skip_maven_deploy == 'true' || inputs.dry_run == 'true' + run: | + echo "Generator deploy skipped." + echo "skip_maven_deploy=${{ inputs.skip_maven_deploy }}" + echo "dry_run=${{ inputs.dry_run }}" + + codegen: + # Main codegen build and Maven release deploy. + runs-on: ubuntu-latest + permissions: + contents: write + needs: + - validate + - generators + if: always() && needs.validate.result == 'success' && (needs.generators.result == 'success' || needs.generators.result == 'skipped') + outputs: + codegen_version: ${{ steps.expose.outputs.codegen_version }} + generators_version: ${{ steps.expose.outputs.generators_version }} + next_codegen_snapshot_version: ${{ steps.expose.outputs.next_codegen_snapshot_version }} + steps: + - name: Checkout swagger-codegen 3.0.0 + uses: actions/checkout@v6 + with: + ref: 3.0.0 + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_PRIVATE_PASSPHRASE }} + with: + java-version: '17' + distribution: temurin + server-id: central + cache: maven + overwrite-settings: false + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Add Central Portal snapshot repository + uses: s4u/maven-settings-action@v4.0.0 + with: + repositories: '[{"id":"central-portal-snapshots","name":"Sonatype Central Portal snapshots","url":"https://central.sonatype.com/repository/maven-snapshots/","releases":{"enabled":false},"snapshots":{"enabled":true}}]' + servers: '[{"id":"central","username":"${{ secrets.MAVEN_CENTRAL_USERNAME }}","password":"${{ secrets.MAVEN_CENTRAL_PASSWORD }}"}]' + + - name: Build swagger-codegen + run: | + bash CI/release/build-codegen-with-generators.sh "${{ needs.validate.outputs.codegen_build_generators_version }}" + + - name: Deploy swagger-codegen + # Intended for final release run; disabled in dry_run/recovery skip mode. + if: inputs.skip_maven_deploy != 'true' && inputs.dry_run != 'true' + run: | + mvn --no-transfer-progress -B -Prelease deploy \ + -Dswagger-codegen-generators-version="${{ needs.validate.outputs.codegen_build_generators_version }}" + + - name: Skip swagger-codegen deploy + if: inputs.skip_maven_deploy == 'true' || inputs.dry_run == 'true' + run: | + echo "Codegen Maven deploy skipped." + echo "skip_maven_deploy=${{ inputs.skip_maven_deploy }}" + echo "dry_run=${{ inputs.dry_run }}" + + - name: Expose release outputs + id: expose + run: | + echo "codegen_version=${{ needs.validate.outputs.codegen_version }}" >> "${GITHUB_OUTPUT}" + echo "generators_version=${{ needs.validate.outputs.generators_version }}" >> "${GITHUB_OUTPUT}" + echo "next_codegen_snapshot_version=${{ needs.validate.outputs.next_codegen_snapshot_version }}" >> "${GITHUB_OUTPUT}" + + - name: Publish prepared draft release notes + # Publishes the draft release created in prepare-release workflow. + if: inputs.dry_run != 'true' + uses: actions/github-script@v8 + with: + script: | + const tag = `v${{ needs.validate.outputs.codegen_version }}`; + const owner = context.repo.owner; + const repo = context.repo.repo; + + let release; + try { + const { data } = await github.rest.repos.getReleaseByTag({ owner, repo, tag }); + release = data; + } catch (error) { + core.setFailed(`Expected prepared draft release for tag ${tag}, but it was not found.`); + return; + } + + if (!release.draft) { + core.info(`Release ${tag} is already published.`); + return; + } + + await github.rest.repos.updateRelease({ + owner, + repo, + release_id: release.id, + draft: false + }); + core.info(`Published draft release ${tag}.`); + + docker: + # Optional container publication stage; can be disabled independently. + runs-on: ubuntu-latest + needs: codegen + if: inputs.skip_docker_push != 'true' && inputs.dry_run != 'true' + steps: + - name: Checkout swagger-codegen 3.0.0 + uses: actions/checkout@v6 + with: + ref: 3.0.0 + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: temurin + cache: maven + + - name: Build Docker inputs + run: | + mvn -B -U clean install -Pdocker \ + -Dswagger-codegen-generators-version="${{ needs.codegen.outputs.generators_version }}" \ + -DJETTY_TEST_HTTP_PORT=8090 \ + -DJETTY_TEST_STOP_PORT=8089 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Docker login + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_SB_USERNAME }} + password: ${{ secrets.DOCKERHUB_SB_PASSWORD }} + + - name: Build and push swagger-generator-v3 + uses: docker/build-push-action@v5 + with: + context: ./modules/swagger-generator + file: ./modules/swagger-generator/Dockerfile + push: true + platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + provenance: false + build-args: | + HIDDEN_OPTIONS_DEFAULT_PATH=hiddenOptions.yaml + JAVA_MEM=1024m + HTTP_PORT=8080 + tags: swaggerapi/swagger-generator-v3:${{ needs.codegen.outputs.codegen_version }},swaggerapi/swagger-generator-v3:latest + + - name: Build and push swagger-generator-v3-root + uses: docker/build-push-action@v5 + with: + context: ./modules/swagger-generator + file: ./modules/swagger-generator/Dockerfile_root + push: true + platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + provenance: false + build-args: | + HIDDEN_OPTIONS_DEFAULT_PATH=hiddenOptions.yaml + JAVA_MEM=1024m + HTTP_PORT=8080 + tags: swaggerapi/swagger-generator-v3-root:${{ needs.codegen.outputs.codegen_version }},swaggerapi/swagger-generator-v3-root:latest + + - name: Build and push swagger-codegen-cli-v3 + uses: docker/build-push-action@v5 + with: + context: ./modules/swagger-codegen-cli + file: ./modules/swagger-codegen-cli/Dockerfile + push: true + platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x + provenance: false + tags: swaggerapi/swagger-codegen-cli-v3:${{ needs.codegen.outputs.codegen_version }},swaggerapi/swagger-codegen-cli-v3:latest + + - name: Build and push swagger-generator-v3-minimal + uses: docker/build-push-action@v5 + with: + context: ./modules/swagger-generator + file: ./modules/swagger-generator/Dockerfile_minimal + push: true + platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x + provenance: false + tags: swaggerapi/swagger-generator-v3-minimal:${{ needs.codegen.outputs.codegen_version }},swaggerapi/swagger-generator-v3-minimal:latest + + online_deploy: + # Optional Swagger online deployment with rollback on readiness failure. + runs-on: ubuntu-latest + needs: + - codegen + - docker + if: inputs.skip_rancher_deploy != 'true' && inputs.skip_docker_push != 'true' && inputs.dry_run != 'true' + steps: + - name: Deploy Swagger online generator with rollback + env: + SC_VERSION: ${{ needs.codegen.outputs.codegen_version }} + TOKEN: ${{ secrets.RANCHER2_BEARER_TOKEN }} + RANCHER_HOST: rancher.tools.swagger.io + CLUSTER_ID: c-n8zp2 + NAMESPACE_NAME: swagger-oss + K8S_OBJECT_TYPE: daemonsets + K8S_OBJECT_NAME: swagger-generator-v3 + run: | + set -euo pipefail + + DEPLOY_IMAGE="swaggerapi/swagger-generator-v3:${SC_VERSION}" + workloadStatus="" + + getStatus() { + echo "Getting ${K8S_OBJECT_NAME} status..." + workloadStatus="$(curl --fail --silent --show-error -X GET \ + -H "Authorization: Bearer ${TOKEN}" \ + -H 'Content-Type: application/json' \ + "https://${RANCHER_HOST}/k8s/clusters/${CLUSTER_ID}/apis/apps/v1/namespaces/${NAMESPACE_NAME}/${K8S_OBJECT_TYPE}/${K8S_OBJECT_NAME}/status")" + } + + updateObject() { + local image="${1}" + echo "Updating ${K8S_OBJECT_NAME} to ${image}" + curl --fail --silent --show-error -X PATCH \ + -H "Authorization: Bearer ${TOKEN}" \ + -H 'Content-Type: application/json-patch+json' \ + "https://${RANCHER_HOST}/k8s/clusters/${CLUSTER_ID}/apis/apps/v1/namespaces/${NAMESPACE_NAME}/${K8S_OBJECT_TYPE}/${K8S_OBJECT_NAME}" \ + -d "[{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/image\",\"value\":\"${image}\"}]" + } + + [[ "${SC_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { + echo "::error::Invalid release version ${SC_VERSION}" + exit 1 + } + + getStatus + ROLLBACK_IMAGE="$(echo "${workloadStatus}" | jq -r '.spec.template.spec.containers[0].image')" + echo "Current image: ${ROLLBACK_IMAGE}" + + updateObject "${DEPLOY_IMAGE}" + sleep 60s + + getStatus + status="$(echo "${workloadStatus}" | jq '.status')" + numberDesired="$(echo "${status}" | jq -r '.desiredNumberScheduled')" + numberReady="$(echo "${status}" | jq -r '.numberReady')" + + if (( numberReady == numberDesired )); then + echo "${K8S_OBJECT_NAME} upgraded to ${DEPLOY_IMAGE}" + exit 0 + fi + + echo "::error::Deployment did not become ready; rolling back to ${ROLLBACK_IMAGE}" + updateObject "${ROLLBACK_IMAGE}" + sleep 60s + + getStatus + status="$(echo "${workloadStatus}" | jq '.status')" + numberDesired="$(echo "${status}" | jq -r '.desiredNumberScheduled')" + numberReady="$(echo "${status}" | jq -r '.numberReady')" + + if (( numberReady == numberDesired )); then + echo "Rollback to ${ROLLBACK_IMAGE} completed." + else + echo "::error::Rollback to ${ROLLBACK_IMAGE} failed." + fi + + exit 1 + + post_release_pr: + # Prepares and opens next snapshot PR after successful release pipeline. + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + needs: + - codegen + - docker + - online_deploy + if: always() && needs.codegen.result == 'success' && (needs.docker.result == 'success' || needs.docker.result == 'skipped') && (needs.online_deploy.result == 'success' || needs.online_deploy.result == 'skipped') + env: + NEXT_CODEGEN_SNAPSHOT_VERSION: ${{ needs.codegen.outputs.next_codegen_snapshot_version }} + GENERATORS_VERSION: ${{ needs.codegen.outputs.generators_version }} + steps: + - name: Checkout swagger-codegen 3.0.0 + uses: actions/checkout@v6 + with: + ref: 3.0.0 + + - uses: actions/create-github-app-token@v3 + id: generate-token + with: + app-id: ${{ secrets.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Set up Java and Maven + uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: temurin + cache: maven + + - name: Prepare next snapshot changes + id: next-snapshot + # Moves repo from release version to next -SNAPSHOT and updates docs/poms. + run: bash CI/release/post-codegen-snapshot.sh + + - name: Create next snapshot pull request + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ steps.generate-token.outputs.token }} + commit-message: bump snapshot ${{ steps.next-snapshot.outputs.next_codegen_snapshot_version }} + title: bump snapshot ${{ steps.next-snapshot.outputs.next_codegen_snapshot_version }} + branch: bump-snap-${{ steps.next-snapshot.outputs.next_codegen_snapshot_version }} + base: 3.0.0 + body: | + Bump Swagger Codegen to ${{ steps.next-snapshot.outputs.next_codegen_snapshot_version }} after release. + + release_generators: ${{ inputs.release_generators }} + swagger-codegen-generators dependency retained as: ${{ needs.codegen.outputs.generators_version }} diff --git a/.github/workflows/release-full-3.yml b/.github/workflows/release-full-3.yml deleted file mode 100644 index 423e860b459..00000000000 --- a/.github/workflows/release-full-3.yml +++ /dev/null @@ -1,283 +0,0 @@ -name: Release Codegen 3.0 and Generators - -on: - workflow_dispatch: - branches: [ "3.0.0" ] - -jobs: - release: - runs-on: ubuntu-latest - steps: - - name: Checkout swagger-codegen (3.0.0) - uses: actions/checkout@v6 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ref: 3.0.0 - - - name: Checkout swagger-codegen-generators - uses: actions/checkout@v6 - with: - repository: swagger-api/swagger-codegen-generators - token: ${{ secrets.GITHUB_TOKEN }} - ref: master - path: generators-repo - - name: Set up Java and Maven - uses: actions/setup-java@v5 - with: - java-version: '17' - distribution: 'temurin' - server-id: central - server-username: ${{ secrets.MAVEN_CENTRAL_USERNAME }} - server-password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} - gpg-private-key: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} - - name: Cache Maven repository - uses: actions/cache@v5 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - - name: configure git user email - run: | - git config --global user.email "action@github.com" - git config --global user.name "GitHub Action" - git config --global hub.protocol https - git remote set-url origin https://\${{ secrets.GITHUB_TOKEN }}:x-oauth-basic@github.com/swagger-api/swagger-codegen.git - - name: Check Release Version codegen - id: preRelease - run: | - # export GPG_TTY=$(tty) - export MY_POM_VERSION=`mvn -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` - if [[ $MY_POM_VERSION =~ ^.*SNAPSHOT$ ]]; - then - echo "not releasing snapshot version: " ${MY_POM_VERSION} - echo "RELEASE_OK=no" >> $GITHUB_ENV - else - echo "RELEASE_OK=yes" >> $GITHUB_ENV - fi - echo "SC_VERSION=$MY_POM_VERSION" >> $GITHUB_ENV - - name: Check Release Version codegen-generators - id: preReleaseGenerators - if: env.RELEASE_OK == 'yes' - working-directory: generators-repo - run: | - # export GPG_TTY=$(tty) - export MY_POM_VERSION_GENERATORS=`mvn -q -Dexec.executable="echo" -Dexec.args='${projects.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec` - if [[ $MY_POM_VERSION_GENERATORS =~ ^.*SNAPSHOT$ ]]; - then - echo "not releasing snapshot version: " ${MY_POM_VERSION_GENERATORS} - echo "RELEASE_OK=no" >> $GITHUB_ENV - else - echo "RELEASE_OK=yes" >> $GITHUB_ENV - fi - echo "SC_VERSION_GENERATORS=$MY_POM_VERSION_GENERATORS" >> $GITHUB_ENV - - name: Run maven install for codegen-generators - if: env.RELEASE_OK == 'yes' - working-directory: generators-repo - run: | - SNAP_API="https://central.sonatype.com/repository/maven-snapshots" - ARTIFACT_PATH="io/swagger/codegen/v3/swagger-codegen" - ROOT_META="${SNAP_API}/${ARTIFACT_PATH}/maven-metadata.xml" - export LAST_SNAP=$(curl -s "$ROOT_META" | grep -oP '(?<=)3\.[^<]+' | sort -V | tail -n1) - echo "LAST_SNAP $LAST_SNAP" - export CODEGEN_VERSION_PROPERTY=-Dswagger-codegen-version=$LAST_SNAP - mvn clean install -U ${CODEGEN_VERSION_PROPERTY} - - name: Run maven install for codegen - if: env.RELEASE_OK == 'yes' - run: | - SNAP_API="https://central.sonatype.com/repository/maven-snapshots" - ARTIFACT_PATH="io/swagger/codegen/v3/swagger-codegen-generators" - ROOT_META="${SNAP_API}/${ARTIFACT_PATH}/maven-metadata.xml" - export LAST_SNAP=$(curl -s "$ROOT_META" | grep -oP '(?<=)1\.[^<]+' | sort -V | tail -n1) - echo "LAST_SNAP $LAST_SNAP" - export GENERATORS_VERSION_PROPERTY=-Dswagger-codegen-generators-version=$LAST_SNAP - mvn clean install -U -Pdocker -DJETTY_TEST_HTTP_PORT=8090 -DJETTY_TEST_STOP_PORT=8089 ${GENERATORS_VERSION_PROPERTY} - - name: Run maven deploy/release for codegen-generators - if: env.RELEASE_OK == 'yes' - working-directory: generators-repo - run: | - mvn --no-transfer-progress -B -Prelease deploy - - name: Run maven deploy/release for codegen - if: env.RELEASE_OK == 'yes' - run: | - mvn --no-transfer-progress -B -Prelease deploy - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: preliminary checks - run: | - docker login --username=${{ secrets.DOCKERHUB_SB_USERNAME }} --password=${{ secrets.DOCKERHUB_SB_PASSWORD }} - set -e - - name: Build with Maven - run: | - mvn clean install -U -Pdocker -DJETTY_TEST_HTTP_PORT=8090 -DJETTY_TEST_STOP_PORT=8089 - - name: docker generator build and push - if: env.RELEASE_OK == 'yes' - uses: docker/build-push-action@v5 - with: - context: ./modules/swagger-generator - file: ./modules/swagger-generator/Dockerfile - push: true - platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x - provenance: false - build-args: | - HIDDEN_OPTIONS_DEFAULT_PATH=hiddenOptions.yaml - JAVA_MEM=1024m - HTTP_PORT=8080 - tags: swaggerapi/swagger-generator-v3:${{ env.SC_VERSION }},swaggerapi/swagger-generator-v3:latest - - name: docker generator root build and push - if: env.RELEASE_OK == 'yes' - uses: docker/build-push-action@v5 - with: - context: ./modules/swagger-generator - file: ./modules/swagger-generator/Dockerfile_root - push: true - platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x - provenance: false - build-args: | - HIDDEN_OPTIONS_DEFAULT_PATH=hiddenOptions.yaml - JAVA_MEM=1024m - HTTP_PORT=8080 - tags: swaggerapi/swagger-generator-v3-root:${{ env.SC_VERSION }},swaggerapi/swagger-generator-v3-root:latest - - name: docker cli build and push - if: env.RELEASE_OK == 'yes' - uses: docker/build-push-action@v5 - with: - context: ./modules/swagger-generator - file: ./modules/swagger-generator/Dockerfile_minimal - push: true - platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x - provenance: false - tags: swaggerapi/swagger-codegen-cli-v3:${{ env.SC_VERSION }},swaggerapi/swagger-codegen-cli-v3:latest - - name: docker minimal build and push - if: env.RELEASE_OK == 'yes' - uses: docker/build-push-action@v5 - with: - context: ./modules/swagger-generator - file: ./modules/swagger-generator/Dockerfile_minimal - push: true - platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x - provenance: false - tags: swaggerapi/swagger-generator-v3-minimal:${{ env.SC_VERSION }},swaggerapi/swagger-generator-v3-minimal:latest - - name: deploy - run: | - echo "${{ env.SC_VERSION }}" - - TOKEN="${{ secrets.RANCHER2_BEARER_TOKEN }}" - RANCHER_HOST="rancher.tools.swagger.io" - CLUSTER_ID="c-n8zp2" - NAMESPACE_NAME="swagger-oss" - K8S_OBJECT_TYPE="daemonsets" - K8S_OBJECT_NAME="swagger-generator-v3" - DEPLOY_IMAGE="swaggerapi/swagger-generator-v3:${{ env.SC_VERSION }}" - - workloadStatus="" - getStatus() { - echo "Getting update status..." - if ! workloadStatus="$(curl -s -X GET \ - -H "Authorization: Bearer ${TOKEN}" \ - -H 'Content-Type: application/json' \ - "https://${RANCHER_HOST}/k8s/clusters/${CLUSTER_ID}/apis/apps/v1/namespaces/${NAMESPACE_NAME}/${K8S_OBJECT_TYPE}/${K8S_OBJECT_NAME}/status")" - then - echo 'ERROR - get status k8s API call failed!' - echo "Exiting build"... - exit 1 - fi - } - - # $1 = image to deploy - updateObject() { - local image="${1}" - echo "Updating image value..." - - if ! curl -s -X PATCH \ - -H "Authorization: Bearer ${TOKEN}" \ - -H 'Content-Type: application/json-patch+json' \ - "https://${RANCHER_HOST}/k8s/clusters/${CLUSTER_ID}/apis/apps/v1/namespaces/${NAMESPACE_NAME}/${K8S_OBJECT_TYPE}/${K8S_OBJECT_NAME}" \ - -d "[{\"op\": \"replace\", \"path\": \"/spec/template/spec/containers/0/image\", \"value\": \"${image}\"}]" - then - echo 'ERROR - image update k8s API call failed!' - echo "Exiting build..." - exit 1 - fi - } - - - # Check that the TAG is valid - if [[ ${{ env.SC_VERSION }} =~ ^[vV]?[0-9]*\.[0-9]*\.[0-9]*$ ]]; then - echo "" - echo "This is a Valid TAG..." - - # Get current image/tag in case we need to rollback - getStatus - ROLLBACK_IMAGE="$(echo "${workloadStatus}" | jq -r '.spec.template.spec.containers[0].image')" - echo "" - echo "Current image: ${ROLLBACK_IMAGE}" - - # Update image and validate response - echo "" - updateObject "${DEPLOY_IMAGE}" - echo "" - - echo "" - echo "Waiting for pods to start..." - echo "" - sleep 60s - - # Get state of the k8s object. If numberReady == desiredNumberScheduled, consider the upgrade successful. Else raise error - getStatus - status="$(echo "${workloadStatus}" | jq '.status')" - echo "" - echo "${status}" - echo "" - - numberDesired="$(echo "${status}" | jq -r '.desiredNumberScheduled')" - numberReady="$(echo "${status}" | jq -r '.numberReady')" - - if (( numberReady == numberDesired )); then - echo "${K8S_OBJECT_NAME} has been upgraded to ${DEPLOY_IMAGE}" - - # If pods are not starting, rollback the upgrade and exit the build with error - else - echo "state = error...rolling back upgrade" - updateObject "${ROLLBACK_IMAGE}" - echo "" - - echo "" - echo "Waiting for rollback pods to start..." - echo "" - sleep 60s - - getStatus - status="$(echo "${workloadStatus}" | jq '.status')" - echo "" - echo "${status}" - echo "" - - numberDesired="$(echo "${status}" | jq -r '.desiredNumberScheduled')" - numberReady="$(echo "${status}" | jq -r '.numberReady')" - - if (( numberReady == numberDesired )); then - echo "Rollback to ${ROLLBACK_IMAGE} completed." - else - echo "FATAL - rollback failed" - fi - echo "Exiting Build..." - exit 1 - fi - - else - echo "This TAG is not in a valid format..." - echo "Exiting Build..." - exit 0 - fi - echo "Exiting Build..." - exit 0 - env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: true - MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SC_VERSION: - SC_VERSION_GENERATORS: - GPG_PRIVATE_KEY: ${{ secrets.OSSRH_GPG_PRIVATE_KEY }} - GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_PRIVATE_PASSPHRASE }} diff --git a/CI/release/build-codegen-with-generators.sh b/CI/release/build-codegen-with-generators.sh new file mode 100644 index 00000000000..9cb430fa961 --- /dev/null +++ b/CI/release/build-codegen-with-generators.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/common.sh" + +generators_version="${1:-}" +[[ -n "${generators_version}" ]] || fail "Usage: build-codegen-with-generators.sh " + +# Standardized codegen build command with explicit generators coordinate. +mvn -B -U clean install -Pdocker \ + -Dswagger-codegen-generators-version="${generators_version}" \ + -DJETTY_TEST_HTTP_PORT=8090 \ + -DJETTY_TEST_STOP_PORT=8089 diff --git a/CI/release/common.sh b/CI/release/common.sh index 5603b8ef9c9..3f94da15e43 100644 --- a/CI/release/common.sh +++ b/CI/release/common.sh @@ -6,12 +6,17 @@ RELEASED_MAVEN_BASE="${RELEASED_MAVEN_BASE:-https://repo1.maven.org/maven2}" SNAPSHOT_MAVEN_BASE="${SNAPSHOT_MAVEN_BASE:-https://central.sonatype.com/repository/maven-snapshots}" CODEGEN_GROUP_PATH="io/swagger/codegen/v3" GENERATORS_ARTIFACT="swagger-codegen-generators" +CODEGEN_ARTIFACT="swagger-codegen" fail() { echo "::error::$*" exit 1 } +notice() { + echo "::notice::$*" +} + require_release_version() { local name="$1" local version="$2" @@ -58,6 +63,11 @@ maven_project_version() { mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec } +maven_property_value() { + local property_name="$1" + mvn -q -Dexec.executable="echo" -Dexec.args="\${${property_name}}" --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec +} + ## Shared curl wrapper for metadata fetch with retries and hard timeouts. curl_metadata() { local url="$1" @@ -88,6 +98,10 @@ latest_snapshot_generators_version() { latest_matching_version "${SNAPSHOT_MAVEN_BASE}/${CODEGEN_GROUP_PATH}/${GENERATORS_ARTIFACT}/maven-metadata.xml" '^1\.[0-9]+\.[0-9]+-SNAPSHOT$' } +latest_snapshot_codegen_version() { + latest_matching_version "${SNAPSHOT_MAVEN_BASE}/${CODEGEN_GROUP_PATH}/${CODEGEN_ARTIFACT}/maven-metadata.xml" '^3\.[0-9]+\.[0-9]+-SNAPSHOT$' +} + ## Build canonical artifact URLs and probe existence without downloading payloads. release_artifact_url() { local artifact="$1" @@ -123,3 +137,22 @@ assert_snapshot_metadata_exists() { fail "Required SNAPSHOT ${CODEGEN_GROUP_PATH}:${artifact}:${version} cannot be resolved from ${metadata_url}. Sonatype snapshots can expire. Recovery: publish that exact snapshot version, then rerun this workflow." fi } + +## Fast local Maven resolve check to fail early before long release stages. +assert_maven_resolves() { + local coordinates="$1" + + if ! mvn -B -q dependency:get -Dartifact="${coordinates}" >/tmp/maven-resolve.log 2>&1; then + cat /tmp/maven-resolve.log + fail "Maven could not resolve ${coordinates}. If this is a SNAPSHOT, publish the required snapshot before retrying." + fi +} + +## Write outputs for both step outputs and downstream environment reuse. +set_output() { + local name="$1" + local value="$2" + + echo "${name}=${value}" >> "${GITHUB_OUTPUT}" + echo "${name}=${value}" >> "${GITHUB_ENV}" +} diff --git a/CI/release/post-codegen-snapshot.sh b/CI/release/post-codegen-snapshot.sh new file mode 100644 index 00000000000..5f860cbd666 --- /dev/null +++ b/CI/release/post-codegen-snapshot.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/common.sh" + +next_codegen_snapshot_version="${NEXT_CODEGEN_SNAPSHOT_VERSION:-}" +generators_version="${GENERATORS_VERSION:-}" + +# If not provided by workflow input, derive next snapshot from current release. +if [[ -z "${next_codegen_snapshot_version}" ]]; then + current_version="$(maven_project_version)" + require_release_version "current codegen POM version" "${current_version}" + next_codegen_snapshot_version="$(next_snapshot_from_release_version "${current_version}")" +fi +require_snapshot_version "NEXT_CODEGEN_SNAPSHOT_VERSION" "${next_codegen_snapshot_version}" +[[ -n "${generators_version}" ]] || fail "GENERATORS_VERSION is required" + +# Expose resolved snapshot version to subsequent workflow steps. +if [[ -n "${GITHUB_ENV:-}" ]]; then + echo "NEXT_CODEGEN_SNAPSHOT_VERSION=${next_codegen_snapshot_version}" >> "${GITHUB_ENV}" +fi + +if [[ -n "${GITHUB_OUTPUT:-}" ]]; then + echo "next_codegen_snapshot_version=${next_codegen_snapshot_version}" >> "${GITHUB_OUTPUT}" +fi + +## Return project to snapshot line after release completion. +mvn -B versions:set -DnewVersion="${next_codegen_snapshot_version}" +mvn -B versions:commit + +update_codegen_release_files_script="CI/release/update-codegen-release-files.py" +[[ -f "${update_codegen_release_files_script}" ]] || fail "Missing ${update_codegen_release_files_script}" + +## Synchronize docs/poms/openapi snapshot references. +python3 "${update_codegen_release_files_script}" post \ + "${next_codegen_snapshot_version}" \ + "${generators_version}" + +echo "Prepared next snapshot file updates for ${next_codegen_snapshot_version}" diff --git a/CI/release/resolve-release-versions.sh b/CI/release/resolve-release-versions.sh new file mode 100644 index 00000000000..5e6325eb2ed --- /dev/null +++ b/CI/release/resolve-release-versions.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "${SCRIPT_DIR}/common.sh" + +release_generators="${RELEASE_GENERATORS:-false}" +generators_version_override="${GENERATORS_VERSION_OVERRIDE:-}" +previous_generators_version="${PREVIOUS_GENERATORS_VERSION:-}" +bootstrap_codegen_version="${CODEGEN_GENERATORS_BOOTSTRAP_VERSION:-}" +generators_existing_behavior="${GENERATORS_EXISTING_BEHAVIOR:-skip}" +skip_maven_deploy="${SKIP_MAVEN_DEPLOY:-false}" +dry_run="${DRY_RUN:-false}" +next_codegen_snapshot_version="${NEXT_CODEGEN_SNAPSHOT_VERSION:-}" + +# Guard critical feature flags early to fail fast on bad inputs. +[[ "${release_generators}" == "true" || "${release_generators}" == "false" ]] || fail "RELEASE_GENERATORS must be true or false" +[[ "${generators_existing_behavior}" == "skip" || "${generators_existing_behavior}" == "fail" ]] || fail "GENERATORS_EXISTING_BEHAVIOR must be skip or fail" + +# Release workflow expects prepare PR already merged (non-SNAPSHOT project version). +codegen_version="$(maven_project_version)" +require_release_version "codegen POM version" "${codegen_version}" + +if [[ -z "${next_codegen_snapshot_version}" ]]; then + next_codegen_snapshot_version="$(next_snapshot_from_release_version "${codegen_version}")" +fi +require_snapshot_version "NEXT_CODEGEN_SNAPSHOT_VERSION" "${next_codegen_snapshot_version}" + +codegen_exists="false" +# Protect against accidental redeploy of existing releases. +if release_artifact_exists "${CODEGEN_ARTIFACT}" "${codegen_version}"; then + codegen_exists="true" + if [[ "${dry_run}" == "true" ]]; then + notice "Codegen artifact ${CODEGEN_ARTIFACT}:${codegen_version} already exists; continuing because DRY_RUN=true." + elif [[ "${skip_maven_deploy}" != "true" ]]; then + fail "Codegen artifact ${CODEGEN_ARTIFACT}:${codegen_version} already exists in Maven Central. Rerun with skip_maven_deploy=true only for recovery." + fi +fi + +generators_version="" +generators_deploy_needed="false" +codegen_build_generators_version="" +bootstrap_generators_version="" + +if [[ "${release_generators}" == "true" ]]; then + # Generators release path: determine if generators must be published this run. + [[ -d generators-repo ]] || fail "generators-repo checkout is required when release_generators=true" + if [[ -n "${bootstrap_codegen_version}" ]]; then + require_release_or_snapshot_version "codegen_generators_bootstrap_version" "${bootstrap_codegen_version}" + else + bootstrap_codegen_version="$(latest_snapshot_codegen_version)" + fi + generators_version="$( + cd generators-repo && \ + mvn -q -Dswagger-codegen-version="${bootstrap_codegen_version}" \ + -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive \ + org.codehaus.mojo:exec-maven-plugin:1.3.1:exec + )" + require_release_version "swagger-codegen-generators POM version" "${generators_version}" + + if release_artifact_exists "${GENERATORS_ARTIFACT}" "${generators_version}"; then + if [[ "${generators_existing_behavior}" == "fail" && "${skip_maven_deploy}" != "true" ]]; then + fail "Generator artifact ${GENERATORS_ARTIFACT}:${generators_version} already exists in Maven Central" + fi + generators_deploy_needed="false" + notice "Generator artifact ${generators_version} already exists; generator deploy will be skipped." + else + generators_deploy_needed="true" + notice "Generator artifact ${generators_version} does not exist; generator deploy is required." + fi + + if [[ "${generators_deploy_needed}" == "true" && "${skip_maven_deploy}" == "true" && "${dry_run}" != "true" ]]; then + fail "Generator artifact ${generators_version} does not exist, but skip_maven_deploy=true would skip publishing it. Publish generators first or rerun without skip_maven_deploy." + fi + + if [[ "${generators_deploy_needed}" == "true" ]]; then + # Circular dependency bootstrap checks: codegen <-> generators. + require_release_or_snapshot_version "codegen_generators_bootstrap_version" "${bootstrap_codegen_version}" + + if [[ "${bootstrap_codegen_version}" =~ SNAPSHOT$ ]]; then + assert_snapshot_metadata_exists "${CODEGEN_ARTIFACT}" "${bootstrap_codegen_version}" + elif ! release_artifact_exists "${CODEGEN_ARTIFACT}" "${bootstrap_codegen_version}"; then + fail "Bootstrap codegen release ${bootstrap_codegen_version} does not exist in Maven Central" + fi + + if [[ -n "${previous_generators_version}" ]]; then + bootstrap_generators_version="${previous_generators_version}" + else + bootstrap_generators_version="$(latest_snapshot_generators_version)" + fi + require_release_or_snapshot_version "previous_generators_version" "${bootstrap_generators_version}" + + if [[ "${bootstrap_generators_version}" =~ SNAPSHOT$ ]]; then + assert_snapshot_metadata_exists "${GENERATORS_ARTIFACT}" "${bootstrap_generators_version}" + elif ! release_artifact_exists "${GENERATORS_ARTIFACT}" "${bootstrap_generators_version}"; then + fail "Bootstrap generators release ${bootstrap_generators_version} does not exist in Maven Central" + fi + assert_maven_resolves "io.swagger.codegen.v3:${GENERATORS_ARTIFACT}:${bootstrap_generators_version}" + else + bootstrap_codegen_version="" + bootstrap_generators_version="${generators_version}" + fi + + if [[ "${generators_deploy_needed}" == "true" && "${dry_run}" == "true" ]]; then + # Dry run cannot use not-yet-published generators release. + codegen_build_generators_version="${bootstrap_generators_version}" + notice "Dry run will build codegen with bootstrap generators ${codegen_build_generators_version}; release deploy will use ${generators_version} after generators are published." + else + codegen_build_generators_version="${generators_version}" + fi +else + # Codegen-only path: generators must already be a resolvable release. + if [[ -n "${generators_version_override}" ]]; then + generators_version="${generators_version_override}" + require_release_version "generators_version_override" "${generators_version}" + else + generators_version="$(maven_property_value "swagger-codegen-generators-version")" + require_release_version "swagger-codegen-generators-version from pom.xml" "${generators_version}" + fi + bootstrap_generators_version="${generators_version}" + + if ! release_artifact_exists "${GENERATORS_ARTIFACT}" "${generators_version}"; then + fail "Resolved generator release ${generators_version} does not exist in Maven Central" + fi +fi + +if [[ "${generators_deploy_needed}" == "true" ]]; then + notice "Skipping Maven resolve check for ${GENERATORS_ARTIFACT}:${generators_version} because this workflow will publish it before codegen deploy." +else + assert_maven_resolves "io.swagger.codegen.v3:${GENERATORS_ARTIFACT}:${generators_version}" +fi + +# Normalize fallback to avoid empty output in edge branches. +if [[ -z "${codegen_build_generators_version}" ]]; then + codegen_build_generators_version="${generators_version}" +fi + +notice "Resolved codegen_version=${codegen_version}" +notice "Resolved generators_version=${generators_version}" +notice "Resolved codegen_build_generators_version=${codegen_build_generators_version}" +notice "Resolved bootstrap_generators_version=${bootstrap_generators_version}" +notice "Resolved bootstrap_codegen_version=${bootstrap_codegen_version:-none}" +notice "Resolved next_codegen_snapshot_version=${next_codegen_snapshot_version}" +notice "Resolved codegen_exists=${codegen_exists}" +notice "Resolved generators_deploy_needed=${generators_deploy_needed}" + +## Export one canonical set of resolved versions to all downstream jobs. +set_output codegen_version "${codegen_version}" +set_output generators_version "${generators_version}" +set_output codegen_build_generators_version "${codegen_build_generators_version}" +set_output bootstrap_generators_version "${bootstrap_generators_version}" +set_output bootstrap_codegen_version "${bootstrap_codegen_version}" +set_output next_codegen_snapshot_version "${next_codegen_snapshot_version}" +set_output codegen_exists "${codegen_exists}" +set_output generators_deploy_needed "${generators_deploy_needed}" diff --git a/CI/release/update-codegen-release-files.py b/CI/release/update-codegen-release-files.py index 13eb4bfcbd8..e928a3ab114 100644 --- a/CI/release/update-codegen-release-files.py +++ b/CI/release/update-codegen-release-files.py @@ -9,7 +9,7 @@ # Regex patterns intentionally target release tables/examples used in public docs. SNAPSHOT_ROW_PATTERN = ( - r"\| [0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT \(current 3\.0\.0, upcoming minor release\).*?\| Minor release\s*\|" + r"\|?\s*[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT \(current 3\.0\.0, upcoming minor release\).*?\|\s*Minor release\s*\|?" ) RELEASE_ROW_PATTERN = ( r"\| \[[0-9]+\.[0-9]+\.[0-9]+\]\(https://github\.com/swagger-api/swagger-codegen/releases/tag/v[0-9]+\.[0-9]+\.[0-9]+\) " @@ -18,7 +18,11 @@ RELEASE_JAR_PATTERN = ( r"io/swagger/codegen/v3/swagger-codegen-cli/[0-9]+\.[0-9]+\.[0-9]+/swagger-codegen-cli-[0-9]+\.[0-9]+\.[0-9]+\.jar" ) +SNAPSHOT_JAR_PATTERN = ( + r"io/swagger/codegen/v3/swagger-codegen-cli/[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT/swagger-codegen-cli-[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT\.jar" +) RELEASE_VERSION_PATTERN = r"3\.0\.[0-9]+" +SNAPSHOT_VERSION_PATTERN = r"3\.0\.[0-9]+-SNAPSHOT" def replace_text(path: str, replacements: list[tuple[str, str]]) -> None: @@ -93,9 +97,9 @@ def update_openapi_version(version: str) -> None: def update_snapshot_rows(next_snapshot: str) -> None: # Update "current upcoming snapshot" row in compatibility docs. snapshot_row = ( - f"| {next_snapshot} (current 3.0.0, upcoming minor release) " + f"{next_snapshot} (current 3.0.0, upcoming minor release) " "[SNAPSHOT](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/" - f"io/swagger/codegen/v3/swagger-codegen-cli/{next_snapshot}/) | TBD | 1.0, 1.1, 1.2, 2.0, 3.0 | Minor release |" + f"io/swagger/codegen/v3/swagger-codegen-cli/{next_snapshot}/)| TBD | 1.0, 1.1, 1.2, 2.0, 3.0 | Minor release" ) replace_text_in_docs(COMPATIBILITY_DOCS, [(SNAPSHOT_ROW_PATTERN, snapshot_row)], require_match=True) @@ -124,9 +128,23 @@ def update_release_docs(codegen_version: str) -> None: ) +def update_snapshot_docs(next_snapshot: str) -> None: + # Point snapshot examples to next development CLI coordinates. + replace_text_in_docs( + RELEASE_DOCS, + [ + ( + SNAPSHOT_JAR_PATTERN, + f"io/swagger/codegen/v3/swagger-codegen-cli/{next_snapshot}/swagger-codegen-cli-{next_snapshot}.jar", + ), + (SNAPSHOT_VERSION_PATTERN, f"{next_snapshot}"), + ], + ) + + def main() -> int: if len(sys.argv) < 2: - print("usage: update-codegen-release-files.py prepare ", file=sys.stderr) + print("usage: update-codegen-release-files.py [...]", file=sys.stderr) return 2 mode = sys.argv[1] @@ -145,6 +163,18 @@ def main() -> int: update_release_docs(codegen_version) return 0 + if mode == "post": + # Post mode: move docs/content back to next snapshot development state. + if len(sys.argv) != 4: + print("usage: ... post ", file=sys.stderr) + return 2 + next_snapshot, generators_version = sys.argv[2:4] + update_generators_poms(generators_version) + update_openapi_version(next_snapshot) + update_snapshot_rows(next_snapshot) + update_snapshot_docs(next_snapshot) + return 0 + print(f"unknown mode: {mode}", file=sys.stderr) return 2