diff --git a/.github/workflows/presto-release-publish.yml b/.github/workflows/presto-release-publish.yml new file mode 100644 index 0000000000000..30825b5bd54f0 --- /dev/null +++ b/.github/workflows/presto-release-publish.yml @@ -0,0 +1,454 @@ +name: Presto Stable Release - Publish + +on: + workflow_dispatch: + inputs: + RELEASE_VERSION: + description: 'Release version (e.g., 0.292)' + required: true + publish_release_tag: + description: 'Publish release tag' + type: boolean + default: true + required: false + release-notes-commit: + description: 'Commit SHA of release notes(required when publish_release_tag is checked)' + required: false + publish_maven: + description: 'Publish maven artifacts' + type: boolean + default: true + required: false + publish_image: + description: 'Publish presto docker image' + type: boolean + default: true + required: false + publish_native_image: + description: 'Publish prestissimo docker image' + type: boolean + default: true + required: false + dependency_image: + description: 'prestissimo dependency image(e.g., prestodb/presto-native-dependency:latest)' + required: false + default: '' + publish_native_dep_image: + description: 'Publish prestissimo dependency docker image' + type: boolean + default: true + required: false + tag_image_as_latest: + description: 'Tag the published images as latest' + type: boolean + default: true + required: false + publish_docs: + description: 'Publish docs' + type: boolean + default: true + required: false + +env: + DOCKER_REPO: ${{ github.repository }} + ORG_NAME: ${{ github.repository_owner }} + IMAGE_NAME: presto-native + RELEASE_BRANCH: release-${{ inputs.RELEASE_VERSION }} + RELEASE_TAG: ${{ inputs.RELEASE_VERSION }} + RELEASE_NOTES_COMMIT: ${{ inputs.release-notes-commit }} + +jobs: + publish-release-tag: + if: github.event.inputs.publish_release_tag == 'true' + runs-on: ubuntu-latest + environment: release + steps: + - name: Validate release notes commit + if: ${{ github.event.inputs.release-notes-commit == '' }} + run: | + echo "Error: release-notes-commit is required when publish_release_tag is true" + exit 1 + + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ env.RELEASE_BRANCH }} + token: ${{ secrets.PRESTODB_CI_TOKEN }} + fetch-depth: 0 + fetch-tags: true + show-progress: false + + - name: Configure Git + run: | + git config --global user.email "ci@lists.prestodb.io" + git config --global user.name "prestodb-ci" + git config pull.rebase false + + - name: Cherry-pick release notes + run: | + git cherry-pick ${{ env.RELEASE_NOTES_COMMIT }} + + - name: Delete existing release tag + run: | + git push --delete origin ${{ env.RELEASE_TAG }} || true + git tag -d ${{ env.RELEASE_TAG }} || true + + - name: Create new release tag + run: | + git tag -a ${{ env.RELEASE_TAG }} -m "release ${{ env.RELEASE_TAG }}" + git push origin ${{ env.RELEASE_BRANCH }} --tags + + publish-maven-artifacts: + needs: publish-release-tag + if: | + (!failure() &&!cancelled()) && + (github.event.inputs.publish_maven == 'true' || github.event.inputs.publish_image == 'true' || github.event.inputs.publish_docs == 'true') + runs-on: ubuntu-latest + environment: release + timeout-minutes: 60 + + env: + NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }} + NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} + + steps: + - name: Setup JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + overwrite-settings: true + gpg-private-key: ${{ secrets.GPG_SECRET }} + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential git gpg python3 python3-venv + + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ env.RELEASE_TAG }} + token: ${{ secrets.PRESTODB_CI_TOKEN }} + fetch-depth: 0 + fetch-tags: true + + - name: Configure Git + run: | + git config --global user.email "ci@lists.prestodb.io" + git config --global user.name "prestodb-ci" + git config pull.rebase false + + - name: Create Maven Settings + run: | + cat > ${{ github.workspace }}/settings.xml << 'EOL' + + + + sonatype-nexus-snapshots + ${env.NEXUS_USERNAME} + ${env.NEXUS_PASSWORD} + + + sonatype.snapshots + ${env.NEXUS_USERNAME} + ${env.NEXUS_PASSWORD} + + + ossrh + ${env.NEXUS_USERNAME} + ${env.NEXUS_PASSWORD} + + + + + nexus + + + + nexus + + + EOL + + - name: Maven build + run: mvn clean install -DskipTests + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: presto-artifacts-${{ env.RELEASE_TAG }} + retention-days: 1 + path: | + presto-server/target/presto-server-*.tar.gz + presto-cli/target/presto-cli-*-executable.jar + presto-docs/target/presto-docs-*.zip + + - name: Set up GPG key + env: + GPG_TTY: $(tty) + GPG_PASSPHRASE: "${{ secrets.GPG_PASSPHRASE }}" + GPG_KEY_FILE: /tmp/gpg-key.txt + run: | + echo "${{ secrets.GPG_SECRET }}" > ${{ env.GPG_KEY_FILE }} + chmod 600 ${{ env.GPG_KEY_FILE }} + gpg --import --batch ${{ env.GPG_KEY_FILE }} + gpg --batch --yes --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --sign ${{ env.GPG_KEY_FILE }} + + - name: Release Maven Artifacts + if: ${{ github.event.inputs.publish_maven == 'true' }} + env: + GPG_TTY: $(tty) + GPG_PASSPHRASE: "${{ secrets.GPG_PASSPHRASE }}" + run: | + unset MAVEN_CONFIG + ./mvnw -s ${{ github.workspace }}/settings.xml -V -B -U -e -T1C deploy \ + -Dgpg.passphrase="${{ secrets.GPG_PASSPHRASE }}" \ + -Dmaven.wagon.http.retryHandler.count=8 \ + -DskipTests \ + -DstagingProfileId="${{ secrets.MAVEN_STAGING_PROFILE_ID }}" \ + -DkeepStagingRepositoryOnFailure=true \ + -DkeepStagingRepositoryOnCloseRuleFailure=true \ + -DautoReleaseAfterClose=true \ + -DstagingProgressTimeoutMinutes=60 \ + -Poss-release \ + -Pdeploy-to-ossrh \ + -pl '!presto-test-coverage' + + publish-docker-image: + needs: publish-maven-artifacts + if: (!failure() && !cancelled()) && github.event.inputs.publish_image == 'true' + runs-on: ubuntu-latest + environment: release + timeout-minutes: 150 + permissions: + packages: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ env.RELEASE_TAG}} + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: presto-artifacts-${{ env.RELEASE_TAG }} + path: ./ + + - name: Login to dockerhub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up qemu + uses: docker/setup-qemu-action@v3 + + - name: Set up docker buildx + uses: docker/setup-buildx-action@v3 + + - name: Create and use builder + run: | + docker buildx create --name container --use + docker buildx inspect --bootstrap + + - name: Move artifacts to docker directory + run: | + mv ./presto-server/target/presto-server-*.tar.gz docker/ + mv ./presto-cli/target/presto-cli-*-executable.jar docker/ + + - name: Build docker image and publish + uses: docker/build-push-action@v6 + with: + context: docker + platforms: linux/amd64,linux/arm64,linux/ppc64le + file: docker/Dockerfile + push: true + build-args: | + PRESTO_VERSION=${{ env.RELEASE_TAG }} + JMX_PROMETHEUS_JAVAAGENT_VERSION=0.20.0 + tags: | + ${{ env.DOCKER_REPO }}:${{ env.RELEASE_TAG }} + ${{ github.event.inputs.tag_image_as_latest == 'true' && format('{0}:latest', env.DOCKER_REPO) || '' }} + + publish-native-image: + needs: publish-release-tag + if: (!failure() && !cancelled()) && github.event.inputs.publish_native_image == 'true' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + environment: release + timeout-minutes: 300 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ env.RELEASE_TAG }} + submodules: true + + - name: Initialize Prestissimo submodules + run: | + cd presto-native-execution && make submodules + echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set dependency image tag + run: | + if [[ -n "${{ github.event.inputs.dependency_image }}" ]]; then + echo "DEPENDENCY_IMAGE=${{ github.event.inputs.dependency_image }}" >> $GITHUB_ENV + else + echo "DEPENDENCY_IMAGE=${{ github.repository_owner }}/presto-native-dependency:${{ env.RELEASE_TAG }}-${{ env.COMMIT_SHA }}" >> $GITHUB_ENV + fi + + - name: Build Dependency Image + working-directory: presto-native-execution + run: | + if docker pull ${{ env.DEPENDENCY_IMAGE }}; then + echo "Using dependency image ${{ env.DEPENDENCY_IMAGE }}" + docker tag ${{ env.DEPENDENCY_IMAGE }} presto/prestissimo-dependency:centos9 + else + echo "Building new depedency image" + docker compose build centos-native-dependency + if [[ "${{ github.event.inputs.publish_native_dep_image }}" == "true" ]]; then + docker tag presto/prestissimo-dependency:centos9 ${{ github.repository_owner }}/presto-native-dependency:${{ env.RELEASE_TAG }}-${{ env.COMMIT_SHA }} + docker push ${{ github.repository_owner }}/presto-native-dependency:${{ env.RELEASE_TAG }}-${{ env.COMMIT_SHA }} + + if [[ "${{ github.event.inputs.tag_image_as_latest }}" == "true" ]]; then + docker tag presto/prestissimo-dependency:centos9 ${{ github.repository_owner }}/presto-native-dependency:latest + docker push ${{ github.repository_owner }}/presto-native-dependency:latest + fi + fi + fi + docker images + + - name: Build Runtime Image + working-directory: presto-native-execution + run: | + docker compose build centos-native-runtime + + - name: Add release tag + working-directory: presto-native-execution + run: | + docker tag presto/prestissimo-runtime:centos9 ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_TAG }} + if [[ "${{ github.event.inputs.tag_image_as_latest }}" == "true" ]]; then + docker tag presto/prestissimo-runtime:centos9 ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:latest + fi + + - name: Push to DockerHub + run: | + docker push ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_TAG }} + if [[ "${{ github.event.inputs.tag_image_as_latest }}" == "true" ]]; then + docker tag ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_TAG }} ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:latest + docker push ${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}:latest + fi + + publish-docs: + needs: publish-maven-artifacts + if: (!failure() && !cancelled()) && github.event.inputs.publish_docs == 'true' + runs-on: ubuntu-latest + environment: release + + steps: + - name: Checkout presto + uses: actions/checkout@v4 + with: + repository: ${{ github.repository_owner }}/presto + path: presto + ref: master + fetch-depth: 0 + fetch-tags: true + show-progress: false + + - name: Checkout prestodb.github.io + uses: actions/checkout@v4 + with: + repository: ${{ github.repository_owner }}/prestodb.github.io + path: prestodb.github.io + ref: source + token: ${{ secrets.PRESTODB_CI_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18.x' + + - name: Configure Git + run: | + cd ${{ github.workspace }}/prestodb.github.io + git config --global --add safe.directory ${{ github.workspace }}/prestodb.github.io + git config --global user.email "ci@lists.prestodb.io" + git config --global user.name "prestodb-ci" + git config --global alias.ls 'log --pretty=format:"%cd %h %ce: %s" --date=short --no-merges' + git ls -5 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: presto-artifacts-${{ env.RELEASE_TAG }} + path: ${{ github.workspace }}/build + + - name: Update Docs + run: | + cd ${{ github.workspace }}/prestodb.github.io + ls -al + + cd website && yarn install && cd .. + LAST_RELEASE_VERSION="0.$((${RELEASE_TAG#0.} - 1))" + echo "Last release version: ${LAST_RELEASE_VERSION}" + + TARGET=website/static/docs/${RELEASE_TAG} + CURRENT=website/static/docs/current + + if [[ -e ${TARGET} ]]; then + echo "Error: ${TARGET} already exists" + exit 1 + fi + + mv ${{ github.workspace }}/build/presto-docs/target/presto-docs-${RELEASE_TAG}.zip . + unzip presto-docs-${RELEASE_TAG}.zip | head -n 5 + mv html ${TARGET} + unlink ${CURRENT} + ln -sf ${RELEASE_TAG} ${CURRENT} + git add ${TARGET} ${CURRENT} + git status | head -n 5 + + DATE=$(TZ=America/Los_Angeles date '+%B %d, %Y') + echo "Update the version number and stats in javascript for rendering across the site" + VERSION_JS=website/static/static/js/version.js + + echo "const presto_latest_presto_version = '${RELEASE_TAG}';" > ${VERSION_JS} + GIT_LOG="git -C ../presto log --use-mailmap ${LAST_RELEASE_VERSION}..${RELEASE_TAG}" + NUM_COMMITS=$(${GIT_LOG} --format='%aE' | wc -l | awk '{$1=$1;print}') + NUM_CONTRIBUTORS=$(${GIT_LOG} --format='%aE' | sort | uniq | wc -l | awk '{$1=$1;print}') + NUM_COMMITTERS=$(${GIT_LOG} --format='%cE' | sort | uniq | wc -l | awk '{$1=$1;print}') + echo "const presto_latest_num_commits = ${NUM_COMMITS};" >> ${VERSION_JS} + echo "const presto_latest_num_contributors = ${NUM_CONTRIBUTORS};" >> ${VERSION_JS} + echo "const presto_latest_num_committers = ${NUM_COMMITTERS};" >> ${VERSION_JS} + echo "const presto_latest_date = '${DATE}';" >> ${VERSION_JS} + cat ${VERSION_JS} + git add ${VERSION_JS} + git status | head -n 5 + + - name: Push Updates + run: | + cd ${{ github.workspace }}/prestodb.github.io + git status | head -n 5 + git commit -m "Add ${RELEASE_TAG} docs" | head -n 5 + git checkout -b "${RELEASE_TAG}-docs" + git push origin "${RELEASE_TAG}-docs" + + - name: Create pull request + env: + GH_TOKEN: ${{ secrets.PRESTODB_CI_TOKEN }} + run: | + cd ${{ github.workspace }}/prestodb.github.io + gh pr create --title "Add ${RELEASE_TAG} docs" --body "Add ${RELEASE_TAG} docs" --base source --head "${RELEASE_TAG}-docs"