From 17650e074137e95bac57c3de4c778d3e0b47d7d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Fri, 15 Mar 2024 09:30:15 +0100 Subject: [PATCH] Move CI to GitHub Actions Closes gh-32449 --- .github/actions/send-notification/action.yml | 33 +++++ .../workflows/build-and-deploy-snapshot.yml | 64 +++++++++ .github/workflows/ci.yml | 82 +++++++++++ README.md | 2 +- ci/README.adoc | 2 + ci/parameters.yml | 1 - ci/pipeline.yml | 130 ++---------------- ci/scripts/build-pr.sh | 8 -- ci/scripts/build-project.sh | 9 -- ci/scripts/check-project.sh | 9 -- ci/tasks/build-pr.yml | 19 --- ci/tasks/build-project.yml | 22 --- ci/tasks/check-project.yml | 24 ---- 13 files changed, 194 insertions(+), 211 deletions(-) create mode 100644 .github/actions/send-notification/action.yml create mode 100644 .github/workflows/build-and-deploy-snapshot.yml create mode 100644 .github/workflows/ci.yml delete mode 100755 ci/scripts/build-pr.sh delete mode 100755 ci/scripts/build-project.sh delete mode 100755 ci/scripts/check-project.sh delete mode 100644 ci/tasks/build-pr.yml delete mode 100644 ci/tasks/build-project.yml delete mode 100644 ci/tasks/check-project.yml diff --git a/.github/actions/send-notification/action.yml b/.github/actions/send-notification/action.yml new file mode 100644 index 000000000000..9582d44ed154 --- /dev/null +++ b/.github/actions/send-notification/action.yml @@ -0,0 +1,33 @@ +name: Send notification +description: Sends a Google Chat message as a notification of the job's outcome +inputs: + webhook-url: + description: 'Google Chat Webhook URL' + required: true + status: + description: 'Status of the job' + required: true + build-scan-url: + description: 'URL of the build scan to include in the notification' + run-name: + description: 'Name of the run to include in the notification' + default: ${{ format('{0} {1}', github.ref_name, github.job) }} +runs: + using: composite + steps: + - shell: bash + run: | + echo "BUILD_SCAN=${{ inputs.build-scan-url == '' && ' [build scan unavailable]' || format(' [<{0}|Build Scan>]', inputs.build-scan-url) }}" >> "$GITHUB_ENV" + echo "RUN_URL=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" >> "$GITHUB_ENV" + - shell: bash + if: ${{ inputs.status == 'success' }} + run: | + curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was successful ${{ env.BUILD_SCAN }}"}' || true + - shell: bash + if: ${{ inputs.status == 'failure' }} + run: | + curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: " *<${{ env.RUN_URL }}|${{ inputs.run-name }}> failed* ${{ env.BUILD_SCAN }}"}' || true + - shell: bash + if: ${{ inputs.status == 'cancelled' }} + run: | + curl -X POST '${{ inputs.webhook-url }}' -H 'Content-Type: application/json' -d '{ text: "<${{ env.RUN_URL }}|${{ inputs.run-name }}> was cancelled"}' || true diff --git a/.github/workflows/build-and-deploy-snapshot.yml b/.github/workflows/build-and-deploy-snapshot.yml new file mode 100644 index 000000000000..eb3737ae18d8 --- /dev/null +++ b/.github/workflows/build-and-deploy-snapshot.yml @@ -0,0 +1,64 @@ +name: Build and deploy snapshot +on: + push: + branches: + - 5.3.x +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} +jobs: + build-and-deploy-snapshot: + if: ${{ github.repository == 'spring-projects/spring-framework' }} + name: Build and deploy snapshot + runs-on: ubuntu-latest + steps: + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: 'liberica' + java-version: 8 + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 + with: + cache-read-only: false + - name: Configure Gradle properties + shell: bash + run: | + mkdir -p $HOME/.gradle + echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties + echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties + echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties + echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties + - name: Build and publish + id: build + env: + CI: 'true' + GRADLE_ENTERPRISE_URL: 'https://ge.spring.io' + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} + GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }} + GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} + run: ./gradlew -PdeploymentRepository=$(pwd)/deployment-repository build publishAllPublicationsToDeploymentRepository + - name: Deploy + uses: spring-io/artifactory-deploy-action@v0.0.1 + with: + uri: 'https://repo.spring.io' + username: ${{ secrets.ARTIFACTORY_USERNAME }} + password: ${{ secrets.ARTIFACTORY_PASSWORD }} + build-name: ${{ format('spring-framework-{0}', github.ref_name)}} + repository: 'libs-snapshot-local' + folder: 'deployment-repository' + signing-key: ${{ secrets.GPG_PRIVATE_KEY }} + signing-passphrase: ${{ secrets.GPG_PASSPHRASE }} + artifact-properties: | + /**/framework-api-*.zip::zip.name=spring-framework,zip.deployed=false + /**/framework-api-*-docs.zip::zip.type=docs + /**/framework-api-*-schema.zip::zip.type=schema + - name: Send notification + uses: ./.github/actions/send-notification + if: always() + with: + webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }} + status: ${{ job.status }} + build-scan-url: ${{ steps.build.outputs.build-scan-url }} + run-name: ${{ format('{0} | Linux | Java 8', github.ref_name) }} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000000..bd51897f32fe --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,82 @@ +name: CI +on: + push: + branches: + - 5.3.x +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} +jobs: + ci: + if: ${{ github.repository == 'spring-projects/spring-framework' }} + strategy: + matrix: + os: + - id: ubuntu-latest + name: Linux + java: + - version: 8 + toolchain: false + - version: 17 + toolchain: true + - version: 21 + toolchain: true + exclude: + - os: + name: Linux + java: + version: 8 + name: '${{ matrix.os.name}} | Java ${{ matrix.java.version}}' + runs-on: ${{ matrix.os.id }} + steps: + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: 'liberica' + java-version: | + ${{ matrix.java.version }} + ${{ matrix.java.toolchain && '8' || '' }} + - name: Prepare Windows runner + if: ${{ runner.os == 'Windows' }} + run: | + git config --global core.autocrlf true + git config --global core.longPaths true + Stop-Service -name Docker + - name: Check out code + uses: actions/checkout@v4 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 + with: + cache-read-only: false + - name: Configure Gradle properties + shell: bash + run: | + mkdir -p $HOME/.gradle + echo 'systemProp.user.name=spring-builds+github' >> $HOME/.gradle/gradle.properties + echo 'systemProp.org.gradle.internal.launcher.welcomeMessageEnabled=false' >> $HOME/.gradle/gradle.properties + echo 'org.gradle.daemon=false' >> $HOME/.gradle/gradle.properties + echo 'org.gradle.daemon=4' >> $HOME/.gradle/gradle.properties + - name: Configure toolchain properties + if: ${{ matrix.java.toolchain }} + shell: bash + run: | + echo toolchainVersion=${{ matrix.java.version }} >> $HOME/.gradle/gradle.properties + echo systemProp.org.gradle.java.installations.auto-detect=false >> $HOME/.gradle/gradle.properties + echo systemProp.org.gradle.java.installations.auto-download=false >> $HOME/.gradle/gradle.properties + echo systemProp.org.gradle.java.installations.paths=${{ format('$JAVA_HOME_{0}_X64', matrix.java.version) }} >> $HOME/.gradle/gradle.properties + - name: Build + id: build + env: + CI: 'true' + GRADLE_ENTERPRISE_URL: 'https://ge.spring.io' + GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} + GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USER }} + GRADLE_ENTERPRISE_CACHE_PASSWORD: ${{ secrets.GRADLE_ENTERPRISE_CACHE_PASSWORD }} + run: ./gradlew check + - name: Send notification + uses: ./.github/actions/send-notification + if: always() + with: + webhook-url: ${{ secrets.GOOGLE_CHAT_WEBHOOK_URL }} + status: ${{ job.status }} + build-scan-url: ${{ steps.build.outputs.build-scan-url }} + run-name: ${{ format('{0} | {1} | Java {2}', github.ref_name, matrix.os.name, matrix.java.version) }} \ No newline at end of file diff --git a/README.md b/README.md index 1a1cb7f6f761..f076adcd1101 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Spring Framework [![Build Status](https://ci.spring.io/api/v1/teams/spring-framework/pipelines/spring-framework-5.3.x/jobs/build/badge)](https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x?groups=Build") [![Revved up by Gradle Enterprise](https://img.shields.io/badge/Revved%20up%20by-Gradle%20Enterprise-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring) +# Spring Framework [![Build Status](https://github.com/spring-projects/spring-framework/actions/workflows/build-and-deploy-snapshot.yml/badge.svg?branch=5.3.x)](https://github.com/spring-projects/spring-framework/actions/workflows/build-and-deploy-snapshot.yml?query=branch%3A5.3.x) [![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.spring.io/scans?search.rootProjectNames=spring) This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring". diff --git a/ci/README.adoc b/ci/README.adoc index cb617637d9b4..d35c0ac8bca7 100644 --- a/ci/README.adoc +++ b/ci/README.adoc @@ -1,5 +1,7 @@ == Spring Framework Concourse pipeline +NOTE: CI is being migrated to GitHub Actions. + The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks. The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x[Spring Framework 5.3.x]. diff --git a/ci/parameters.yml b/ci/parameters.yml index 2c45862cf41e..49123fddb7d3 100644 --- a/ci/parameters.yml +++ b/ci/parameters.yml @@ -8,4 +8,3 @@ milestone: "5.3.x" build-name: "spring-framework" pipeline-name: "spring-framework" concourse-url: "https://ci.spring.io" -task-timeout: 1h00m diff --git a/ci/pipeline.yml b/ci/pipeline.yml index e722028eb7ec..ceee57b3892a 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -23,14 +23,6 @@ anchors: docker-resource-source: &docker-resource-source username: ((docker-hub-username)) password: ((docker-hub-password)) - slack-fail-params: &slack-fail-params - text: > - :concourse-failed: - [$TEXT_FILE_CONTENT] - text_file: git-repo/build/build-scan-uri.txt - silent: true - icon_emoji: ":concourse:" - username: concourse-ci changelog-task-params: &changelog-task-params name: generated-changelog/tag tag: generated-changelog/tag @@ -64,25 +56,12 @@ resource_types: <<: *docker-resource-source repository: dpb587/github-status-resource tag: master -- name: slack-notification - type: registry-image - source: - <<: *docker-resource-source - repository: cfcommunity/slack-notification-resource - tag: latest resources: - name: git-repo type: git icon: github source: <<: *git-repo-resource-source -- name: every-morning - type: time - icon: alarm - source: - start: 8:00 AM - stop: 9:00 AM - location: Europe/Vienna - name: ci-images-git-repo type: git icon: github @@ -105,27 +84,6 @@ resources: username: ((artifactory-username)) password: ((artifactory-password)) build_name: ((build-name)) -- name: repo-status-build - type: github-status-resource - icon: eye-check-outline - source: - repository: ((github-repo-name)) - access_token: ((github-ci-status-token)) - branch: ((branch)) - context: build -- name: repo-status-jdk17-build - type: github-status-resource - icon: eye-check-outline - source: - repository: ((github-repo-name)) - access_token: ((github-ci-status-token)) - branch: ((branch)) - context: jdk17-build -- name: slack-alert - type: slack-notification - icon: slack - source: - url: ((slack-webhook-url)) - name: github-pre-release type: github-release icon: briefcase-download-outline @@ -160,37 +118,23 @@ jobs: - put: ci-image params: image: ci-image/image.tar -- name: build +- name: stage-milestone serial: true - public: true plan: - get: ci-image - get: git-repo - trigger: true - - put: repo-status-build - params: { state: "pending", commit: "git-repo" } - - do: - - task: build-project - image: ci-image - file: git-repo/ci/tasks/build-project.yml - privileged: true - timeout: ((task-timeout)) - params: - <<: *build-project-task-params - on_failure: - do: - - put: repo-status-build - params: { state: "failure", commit: "git-repo" } - - put: slack-alert - params: - <<: *slack-fail-params - - put: repo-status-build - params: { state: "success", commit: "git-repo" } + trigger: false + - task: stage + image: ci-image + file: git-repo/ci/tasks/stage-version.yml + params: + RELEASE_TYPE: M + <<: *gradle-enterprise-task-params - put: artifactory-repo params: &artifactory-params signing_key: ((signing-key)) signing_passphrase: ((signing-passphrase)) - repo: libs-snapshot-local + repo: libs-staging-local folder: distribution-repository build_uri: "https://ci.spring.io/teams/${BUILD_TEAM_NAME}/pipelines/${BUILD_PIPELINE_NAME}/jobs/${BUILD_JOB_NAME}/builds/${BUILD_NAME}" build_number: "${BUILD_PIPELINE_NAME}-${BUILD_JOB_NAME}-${BUILD_NAME}" @@ -215,55 +159,9 @@ jobs: - "/**/spring-*-schema.zip" properties: "zip.type": "schema" - get_params: - threads: 8 -- name: jdk17-build - serial: true - public: true - plan: - - get: ci-image - - get: git-repo - - get: every-morning - trigger: true - - put: repo-status-jdk17-build - params: { state: "pending", commit: "git-repo" } - - do: - - task: check-project - image: ci-image - file: git-repo/ci/tasks/check-project.yml - privileged: true - timeout: ((task-timeout)) - params: - TEST_TOOLCHAIN: 17 - <<: *build-project-task-params - on_failure: - do: - - put: repo-status-jdk17-build - params: { state: "failure", commit: "git-repo" } - - put: slack-alert - params: - <<: *slack-fail-params - - put: repo-status-jdk17-build - params: { state: "success", commit: "git-repo" } -- name: stage-milestone - serial: true - plan: - - get: ci-image - - get: git-repo - trigger: false - - task: stage - image: ci-image - file: git-repo/ci/tasks/stage-version.yml - params: - RELEASE_TYPE: M - <<: *gradle-enterprise-task-params - - put: artifactory-repo - params: - <<: *artifactory-params - repo: libs-staging-local - - put: git-repo - params: - repository: stage-git-repo + - put: git-repo + params: + repository: stage-git-repo - name: promote-milestone serial: true plan: @@ -304,7 +202,6 @@ jobs: - put: artifactory-repo params: <<: *artifactory-params - repo: libs-staging-local - put: git-repo params: repository: stage-git-repo @@ -348,7 +245,6 @@ jobs: - put: artifactory-repo params: <<: *artifactory-params - repo: libs-staging-local - put: git-repo params: repository: stage-git-repo @@ -391,8 +287,6 @@ jobs: <<: *changelog-task-params groups: -- name: "builds" - jobs: ["build", "jdk17-build"] - name: "releases" jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"] - name: "ci-images" diff --git a/ci/scripts/build-pr.sh b/ci/scripts/build-pr.sh deleted file mode 100755 index 94c4e8df65b4..000000000000 --- a/ci/scripts/build-pr.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -set -e - -source $(dirname $0)/common.sh - -pushd git-repo > /dev/null -./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 check -popd > /dev/null diff --git a/ci/scripts/build-project.sh b/ci/scripts/build-project.sh deleted file mode 100755 index 3844d1a3ddb4..000000000000 --- a/ci/scripts/build-project.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -source $(dirname $0)/common.sh -repository=$(pwd)/distribution-repository - -pushd git-repo > /dev/null -./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false --no-daemon --max-workers=4 -PdeploymentRepository=${repository} build publishAllPublicationsToDeploymentRepository -popd > /dev/null diff --git a/ci/scripts/check-project.sh b/ci/scripts/check-project.sh deleted file mode 100755 index 0620dc17164d..000000000000 --- a/ci/scripts/check-project.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -source $(dirname $0)/common.sh - -pushd git-repo > /dev/null -./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17 \ - -PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check -popd > /dev/null diff --git a/ci/tasks/build-pr.yml b/ci/tasks/build-pr.yml deleted file mode 100644 index dbf6e9c0cf60..000000000000 --- a/ci/tasks/build-pr.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- -platform: linux -inputs: -- name: git-repo -caches: -- path: gradle -params: - BRANCH: - CI: true - GRADLE_ENTERPRISE_ACCESS_KEY: - GRADLE_ENTERPRISE_CACHE_USERNAME: - GRADLE_ENTERPRISE_CACHE_PASSWORD: - GRADLE_ENTERPRISE_URL: https://ge.spring.io -run: - path: bash - args: - - -ec - - | - ${PWD}/git-repo/ci/scripts/build-pr.sh diff --git a/ci/tasks/build-project.yml b/ci/tasks/build-project.yml deleted file mode 100644 index 759749ef433f..000000000000 --- a/ci/tasks/build-project.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -platform: linux -inputs: -- name: git-repo -outputs: -- name: distribution-repository -- name: git-repo -caches: -- path: gradle -params: - BRANCH: - CI: true - GRADLE_ENTERPRISE_ACCESS_KEY: - GRADLE_ENTERPRISE_CACHE_USERNAME: - GRADLE_ENTERPRISE_CACHE_PASSWORD: - GRADLE_ENTERPRISE_URL: https://ge.spring.io -run: - path: bash - args: - - -ec - - | - ${PWD}/git-repo/ci/scripts/build-project.sh diff --git a/ci/tasks/check-project.yml b/ci/tasks/check-project.yml deleted file mode 100644 index bea1185231b9..000000000000 --- a/ci/tasks/check-project.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -platform: linux -inputs: -- name: git-repo -outputs: -- name: distribution-repository -- name: git-repo -caches: -- path: gradle -params: - BRANCH: - CI: true - MAIN_TOOLCHAIN: - TEST_TOOLCHAIN: - GRADLE_ENTERPRISE_ACCESS_KEY: - GRADLE_ENTERPRISE_CACHE_USERNAME: - GRADLE_ENTERPRISE_CACHE_PASSWORD: - GRADLE_ENTERPRISE_URL: https://ge.spring.io -run: - path: bash - args: - - -ec - - | - ${PWD}/git-repo/ci/scripts/check-project.sh