This is an automated email from the ASF dual-hosted git repository. Kusuma04-dev pushed a commit to branch test_10.3.x in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
commit d865c8d49189c620eff8c4fa1f923217b251e87d Author: Kusuma <[email protected]> AuthorDate: Mon Oct 12 19:52:31 2026 +0530 tset --- .ci/incubator-kie-tools-ci-build.Dockerfile | 4 +- .ci/jenkins/Jenkinsfile.103xplus.release-candidate | 305 ++++++++ .ci/jenkins/Jenkinsfile.103xplus.release-publish | 249 +++++++ .ci/jenkins/shared-scripts/pipelineVars.groovy | 1 + scripts/release/CHROME_STORE_SETUP.md | 190 +++++ scripts/release/README.md | 160 +++++ scripts/release/create-source-tarball.sh | 93 +++ scripts/release/release-all.sh | 773 +++++++++++++++++++++ 8 files changed, 1773 insertions(+), 2 deletions(-) diff --git a/.ci/incubator-kie-tools-ci-build.Dockerfile b/.ci/incubator-kie-tools-ci-build.Dockerfile index 7dcb5d47329..730758348a8 100644 --- a/.ci/incubator-kie-tools-ci-build.Dockerfile +++ b/.ci/incubator-kie-tools-ci-build.Dockerfile @@ -100,8 +100,8 @@ RUN curl -s "https://get.sdkman.io" | bash && \ sdk flush # Golang setup -RUN wget https://go.dev/dl/go1.26.7.linux-amd64.tar.gz -P /tmp && \ - sudo tar xzf /tmp/go1.26.7.linux-amd64.tar.gz -C /opt && rm /tmp/go1.26.7.linux-amd64.tar.gz && \ +RUN wget https://go.dev/dl/go1.26.5.linux-amd64.tar.gz -P /tmp && \ + sudo tar xzf /tmp/go1.26.5.linux-amd64.tar.gz -C /opt && rm /tmp/go1.26.5.linux-amd64.tar.gz && \ echo 'export GOPATH=${HOME}/go' | sudo tee /etc/profile.d/go.sh && \ echo 'export PATH=${PATH}:/opt/go/bin:${GOPATH}/bin' | sudo tee -a /etc/profile.d/go.sh && \ echo "source /etc/profile.d/go.sh" >> $HOME/.bashrc && \ diff --git a/.ci/jenkins/Jenkinsfile.103xplus.release-candidate b/.ci/jenkins/Jenkinsfile.103xplus.release-candidate new file mode 100644 index 00000000000..c2281d53db7 --- /dev/null +++ b/.ci/jenkins/Jenkinsfile.103xplus.release-candidate @@ -0,0 +1,305 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Library('jenkins-pipeline-shared-libraries')_ + +// PHASE 1: Create Release Candidate for Apache Voting +// This job builds artifacts, signs them, and publishes to Apache SVN for community vote +// Does NOT publish to npm, VSCode Marketplace, or Chrome Web Store +// +// NOTE: kogito-data-index-ephemeral is NOT included in this pipeline because the +// packages/kogito-data-index-ephemeral-image package no longer exists in this repo. +// Its presence in older Jenkinsfiles (Jenkinsfile.release-candidate RUNNERS list and +// release-jobs/Jenkinsfile.kogito-data-index-ephemeral-image) is a historical artifact +// from pre-10.3 automation and can be cleaned up in a follow-up PR. + +pipeline { + agent { + docker { + image 'docker.io/apache/incubator-kie-tools-ci-build:main' + args '--shm-size=2g --privileged --group-add docker' + label util.avoidFaultyNodes() + } + } + + options { + timeout(time: 480, unit: 'MINUTES') + } + + parameters { + string( + name: 'RELEASE_VERSION', + description: 'Release version (e.g., 1.0.0)', + defaultValue: '0.0.0' + ) + string( + name: 'RELEASE_CANDIDATE_VERSION', + description: 'Release candidate version (e.g., 10.3.0-rc1)', + defaultValue: '0.0.0-rc1' + ) + string( + name: 'BASE_REF', + description: 'Git branch or tag to release from', + defaultValue: 'main' + ) + } + + environment { + KIE_TOOLS_BUILD__runLinters = 'false' + KIE_TOOLS_BUILD__runTests = 'false' + KIE_TOOLS_BUILD__runEndToEndTests = 'false' + KIE_TOOLS_BUILD__buildContainerImages = 'true' + + CHROME_EXTENSION__routerTargetOrigin = 'https://apache.github.io' + CHROME_EXTENSION__routerRelativePath = "incubator-kie-kogito-online/chrome-extension/${params.RELEASE_VERSION}" + CHROME_EXTENSION__manifestFile = 'manifest.prod.json' + CHROME_EXTENSION__onlineEditorUrl = 'https://apache.github.io/incubator-kie-kogito-online' + + ONLINE_EDITOR__corsProxyUrl = 'https://cors-proxy-kie-sandbox.rhba-0ad6762cc85bcef5745bb684498c2436-0000.us-south.containers.appdomain.cloud' + ONLINE_EDITOR__buildInfo = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__extendedServicesCompatibleVersion = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentBaseImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentBaseImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentBaseImageName = 'incubator-kie-sandbox-dev-deployment-base' + ONLINE_EDITOR__devDeploymentBaseImageTag = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageName = 'incubator-kie-sandbox-dev-deployment-dmn-form-webapp' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName = 'incubator-kie-sandbox-dev-deployment-quarkus-blank-app' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag = "${params.RELEASE_VERSION}" + } + + stages { + stage('Load local shared scripts') { + steps { + script { + pipelineVars = load '.ci/jenkins/shared-scripts/pipelineVars.groovy' + buildUtils = load '.ci/jenkins/shared-scripts/buildUtils.groovy' + githubUtils = load '.ci/jenkins/shared-scripts/githubUtils.groovy' + releaseUtils = load '.ci/jenkins/shared-scripts/releaseUtils.groovy' + } + } + } + + stage('Start required services') { + steps { + script { + buildUtils.startRequiredServices() + } + } + } + + stage('Clean workspace') { + steps { + cleanWs(deleteDirs: true, disableDeferredWipeout: true) + } + } + + stage('Checkout kie-tools') { + steps { + dir('kie-tools') { + script { + githubUtils.checkoutRepo( + "http://github.com/${pipelineVars.githubRepositorySlug}.git", + "${params.BASE_REF}", + "${pipelineVars.kieToolsBotGithubCredentialsId}" + ) + } + } + } + } + + stage('Setup PNPM') { + steps { + dir('kie-tools') { + script { + buildUtils.setupPnpm("${pipelineVars.mavenSettingsReleaseConfigFileId}") + } + } + } + } + + stage('Setup Git repository') { + steps { + dir('kie-tools') { + script { + sh """#!/bin/bash -el + git config user.email [email protected] + git config user.name asf-ci-kie + git checkout ${params.BASE_REF} + """.trim() + } + } + } + } + + stage('Bootstrap') { + steps { + dir('kie-tools') { + sh '''#!/bin/bash -el + pnpm bootstrap + ''' + } + } + } + + stage('Update versions') { + steps { + dir('kie-tools') { + sh """#!/bin/bash -el + pnpm update-version-to ${params.RELEASE_VERSION} + pnpm update-kogito-version-to --maven ${params.RELEASE_VERSION} + pnpm update-stream-name-to ${params.RELEASE_VERSION} + """ + } + } + } + + stage('Commit changes') { + steps { + dir('kie-tools') { + script { + sh """#!/bin/bash -el + git add . + git commit --allow-empty -am "Apache KIE ${params.RELEASE_VERSION} release candidate ${params.RELEASE_CANDIDATE_VERSION}" + """.trim() + } + } + } + } + + stage('Check release version against package.json') { + steps { + dir('kie-tools') { + script { + def packageVersion = sh( + returnStdout: true, + script: "#!/bin/bash -el \n node -p \"require('./package.json').version\"" + ).trim() + if (packageVersion != params.RELEASE_VERSION) { + error("Version mismatch! package.json has ${packageVersion} but RELEASE_VERSION is ${params.RELEASE_VERSION}") + } + } + } + } + } + + stage('Create and push RC tag') { + steps { + dir('kie-tools') { + script { + githubUtils.createTag("${params.RELEASE_CANDIDATE_VERSION}") + githubUtils.pushObject('origin', "${params.RELEASE_CANDIDATE_VERSION}", "${pipelineVars.asfGithubPushCredentialsId}") + sleep(time: 1, unit: 'MINUTES') + } + } + } + } + + stage('Build Release Candidate Artifacts') { + steps { + dir('kie-tools') { + script { + echo "Building release candidate artifacts..." + echo "Version: ${params.RELEASE_VERSION}" + echo "RC: ${params.RELEASE_CANDIDATE_VERSION}" + + // Build artifacts WITHOUT publishing (no --publish flag) + // The --rc flag creates artifacts for Apache SVN + sh """#!/bin/bash -el + ./scripts/release/release-all.sh ${params.RELEASE_VERSION} --rc --git-ref ${params.RELEASE_CANDIDATE_VERSION} + """ + } + } + } + } + + stage('Sign Release Candidate Artifacts') { + steps { + dir('kie-tools/release-artifacts') { + script { + releaseUtils.setupSigningKey("${pipelineVars.asfReleaseGPGKeyCredentialsId}") + + sh """#!/bin/bash -el + echo "Signing all artifacts..." + for file in *.zip *.vsix *.tar.gz; do + if [ -f "\$file" ]; then + echo "Signing \$file" + gpg --no-tty --batch --sign --pinentry-mode loopback --output "\$file.asc" --detach-sig "\$file" + shasum -a 512 "\$file" > "\$file.sha512" + fi + done + + echo "Artifacts signed:" + ls -lh + """ + } + } + } + } + + stage('Publish to Apache SVN (for voting)') { + steps { + dir('kie-tools/release-artifacts') { + script { + echo "Publishing to Apache SVN staging repository..." + echo "Repository: ${pipelineVars.asfReleaseStagingRepository}" + echo "RC Version: ${params.RELEASE_CANDIDATE_VERSION}" + + releaseUtils.publishArtifacts( + "${WORKSPACE}/kie-tools/release-artifacts", + "${pipelineVars.asfReleaseStagingRepository}", + "${params.RELEASE_CANDIDATE_VERSION}", + "${pipelineVars.asfReleaseSVNStagingCredentialsId}" + ) + + echo "✅ Release candidate published to:" + echo " ${pipelineVars.asfReleaseStagingRepository}/${params.RELEASE_CANDIDATE_VERSION}/" + } + } + } + } + } + + post { + success { + echo "==========================================" + echo "✅ Release Candidate Created Successfully!" + echo "==========================================" + echo "Version: ${params.RELEASE_VERSION}" + echo "RC: ${params.RELEASE_CANDIDATE_VERSION}" + echo "" + echo "Artifacts published to:" + echo "${pipelineVars.asfReleaseStagingRepository}/${params.RELEASE_CANDIDATE_VERSION}/" + echo "" + echo "Next steps:" + echo "1. Start a vote thread on [email protected]" + echo "2. Wait for vote to pass (72 hours, 3 +1 votes)" + echo "3. Run Jenkinsfile.103xplus.release-publish to publish to registries" + echo "==========================================" + } + failure { + echo "❌ Release candidate creation failed!" + } + always { + cleanWs(deleteDirs: true) + } + } +} \ No newline at end of file diff --git a/.ci/jenkins/Jenkinsfile.103xplus.release-publish b/.ci/jenkins/Jenkinsfile.103xplus.release-publish new file mode 100644 index 00000000000..3b992d0eb1b --- /dev/null +++ b/.ci/jenkins/Jenkinsfile.103xplus.release-publish @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Library('jenkins-pipeline-shared-libraries')_ + +// PHASE 2: Publish Release After Vote Passes +// This job publishes the approved release candidate to public registries +// Publishes to: npm, VSCode Marketplace, Chrome Web Store, GitHub Releases +// +// NOTE: kogito-data-index-ephemeral is NOT included in this pipeline because the +// packages/kogito-data-index-ephemeral-image package no longer exists in this repo. +// Its presence in older Jenkinsfiles (Jenkinsfile.release-candidate RUNNERS list and +// release-jobs/Jenkinsfile.kogito-data-index-ephemeral-image) is a historical artifact +// from pre-10.3 automation and can be cleaned up in a follow-up PR. + +pipeline { + agent { + docker { + image 'docker.io/apache/incubator-kie-tools-ci-build:main' + args '--shm-size=2g --privileged --group-add docker' + label util.avoidFaultyNodes() + } + } + + options { + timeout(time: 480, unit: 'MINUTES') + } + + parameters { + string( + name: 'RELEASE_VERSION', + description: 'Release version (e.g., 1.0.0) - must match the voted RC', + defaultValue: '0.0.0' + ) + string( + name: 'BASE_REF', + description: 'Git tag to release from (should be the RC tag)', + defaultValue: '0.0.0-rc1' + ) + string( + name: 'GITHUB_RELEASE_TAG', + description: 'GitHub release tag (for uploading assets to the GitHub Release)', + defaultValue: '' + ) + } + + environment { + KIE_TOOLS_BUILD__runLinters = 'false' + KIE_TOOLS_BUILD__runTests = 'false' + KIE_TOOLS_BUILD__runEndToEndTests = 'false' + KIE_TOOLS_BUILD__buildContainerImages = 'true' + + CHROME_EXTENSION__routerTargetOrigin = 'https://apache.github.io' + CHROME_EXTENSION__routerRelativePath = "incubator-kie-kogito-online/chrome-extension/${params.RELEASE_VERSION}" + CHROME_EXTENSION__manifestFile = 'manifest.prod.json' + CHROME_EXTENSION__onlineEditorUrl = 'https://apache.github.io/incubator-kie-kogito-online' + + ONLINE_EDITOR__corsProxyUrl = 'https://cors-proxy-kie-sandbox.rhba-0ad6762cc85bcef5745bb684498c2436-0000.us-south.containers.appdomain.cloud' + ONLINE_EDITOR__buildInfo = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__extendedServicesCompatibleVersion = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentBaseImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentBaseImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentBaseImageName = 'incubator-kie-sandbox-dev-deployment-base' + ONLINE_EDITOR__devDeploymentBaseImageTag = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageName = 'incubator-kie-sandbox-dev-deployment-dmn-form-webapp' + ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag = "${params.RELEASE_VERSION}" + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry = 'docker.io' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount = 'apache' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName = 'incubator-kie-sandbox-dev-deployment-quarkus-blank-app' + ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag = "${params.RELEASE_VERSION}" + + DOCKER_CONFIG = "${WORKSPACE}/.docker" + HELM_REGISTRY = 'docker.io/apache' + } + + stages { + stage('Load local shared scripts') { + steps { + script { + pipelineVars = load '.ci/jenkins/shared-scripts/pipelineVars.groovy' + buildUtils = load '.ci/jenkins/shared-scripts/buildUtils.groovy' + githubUtils = load '.ci/jenkins/shared-scripts/githubUtils.groovy' + } + } + } + + stage('Start required services') { + steps { + script { + buildUtils.startRequiredServices() + } + } + } + + stage('Clean workspace') { + steps { + cleanWs(deleteDirs: true, disableDeferredWipeout: true) + } + } + + stage('Checkout kie-tools') { + steps { + dir('kie-tools') { + script { + githubUtils.checkoutRepo( + "http://github.com/${pipelineVars.githubRepositorySlug}.git", + "${params.BASE_REF}", + "${pipelineVars.kieToolsBotGithubCredentialsId}" + ) + } + } + } + } + + stage('Verify version') { + steps { + dir('kie-tools') { + script { + def packageVersion = sh( + returnStdout: true, + script: "node -p \"require('./package.json').version\"" + ).trim() + + if (packageVersion != params.RELEASE_VERSION) { + error("Version mismatch! package.json has ${packageVersion} but RELEASE_VERSION is ${params.RELEASE_VERSION}") + } + + echo "✅ Version verified: ${packageVersion}" + } + } + } + } + + stage('Setup PNPM') { + steps { + dir('kie-tools') { + script { + buildUtils.setupPnpm("${pipelineVars.mavenSettingsReleaseConfigFileId}") + } + } + } + } + + stage('Bootstrap') { + steps { + dir('kie-tools') { + sh '''#!/bin/bash -el + pnpm bootstrap + ''' + } + } + } + + stage('Build and Publish to Registries') { + steps { + dir('kie-tools') { + script { + echo "Publishing release to public registries..." + echo "Version: ${params.RELEASE_VERSION}" + + withCredentials([ + string(credentialsId: "${pipelineVars.npmTokenCredentialsId}", variable: 'NPM_TOKEN'), + string(credentialsId: "${pipelineVars.vscePatCredentialsId}", variable: 'VSCE_PAT'), + usernamePassword(credentialsId: "${pipelineVars.chromeStoreCredentialsId}", + usernameVariable: 'CHROME_CLIENT_ID', + passwordVariable: 'CHROME_CLIENT_SECRET'), + string(credentialsId: "${pipelineVars.chromeStoreRefreshTokenCredentialsId}", variable: 'CHROME_REFRESH_TOKEN'), + string(credentialsId: "${pipelineVars.chromeExtensionIdCredentialsId}", variable: 'CHROME_KIE_EDITORS_EXTENSION_ID'), + string(credentialsId: "${pipelineVars.dockerHubUserCredentialsId}", variable: 'DOCKER_USERNAME'), + string(credentialsId: "${pipelineVars.dockerHubTokenCredentialsId}", variable: 'DOCKER_PASSWORD'), + // Helm charts use the same Docker Hub credentials as the old helm jobs + string(credentialsId: "${pipelineVars.dockerHubUserCredentialsId}", variable: 'HELM_USERNAME'), + string(credentialsId: "${pipelineVars.dockerHubTokenCredentialsId}", variable: 'HELM_PASSWORD'), + string(credentialsId: "${pipelineVars.kieToolsBotGithubTokenCredentialsId}", variable: 'GITHUB_TOKEN') + ]) { + script { + def uploadUrlFlag = '' + if (params.GITHUB_RELEASE_TAG != '') { + def releaseJson = sh( + returnStdout: true, + script: """ + curl -sSf -H "Authorization: token \${GITHUB_TOKEN}" \ + "https://api.github.com/repos/${pipelineVars.githubRepositorySlug}/releases/tags/${params.GITHUB_RELEASE_TAG}" + """ + ).trim() + def releaseInfo = readJSON text: releaseJson + uploadUrlFlag = "--upload-url '${releaseInfo.upload_url.replaceAll('\\{.*\\}', '')}'" + } + + sh """#!/bin/bash -el + ./scripts/release/release-all.sh ${params.RELEASE_VERSION} --publish ${uploadUrlFlag} + """ + } + } + } + } + } + } + } + + post { + success { + echo "==========================================" + echo "✅ Release Published Successfully!" + echo "==========================================" + echo "Version: ${params.RELEASE_VERSION}" + echo "" + echo "Published to:" + echo " ✅ npm registry" + echo " ✅ VSCode Marketplace" + echo " ✅ Chrome Web Store" + echo " ✅ Container registry" + echo " ✅ Helm registry" + echo " ✅ GitHub Pages" + if (params.GITHUB_RELEASE_TAG != '') { + echo " ✅ GitHub Release: ${params.GITHUB_RELEASE_TAG}" + } + echo "" + echo "Next steps:" + echo "1. Verify packages are available in registries" + echo "2. Move artifacts from dev/ to release/ in Apache SVN" + echo "3. Announce the release" + echo "==========================================" + } + failure { + echo "❌ Release publishing failed!" + echo "Check logs above for details" + } + always { + cleanWs(deleteDirs: true) + } + } +} \ No newline at end of file diff --git a/.ci/jenkins/shared-scripts/pipelineVars.groovy b/.ci/jenkins/shared-scripts/pipelineVars.groovy index d83f6327b78..71171345877 100644 --- a/.ci/jenkins/shared-scripts/pipelineVars.groovy +++ b/.ci/jenkins/shared-scripts/pipelineVars.groovy @@ -22,6 +22,7 @@ class PipelineVars implements Serializable { String quayPushCredentialsId = 'quay-io-kie-tools-token' String dockerHubUserCredentialsId = 'DOCKERHUB_USER' String dockerHubTokenCredentialsId = 'DOCKERHUB_TOKEN' + String vscePatCredentialsId = 'kie-tools-vsce-pat' String openshiftCredentialsId = 'openshift-kie-tools-token' String kieToolsBotGithubCredentialsId = 'kie-tools-bot-gh' String kieToolsBotGithubTokenCredentialsId = 'kie-tools-bot-gh-token' diff --git a/scripts/release/CHROME_STORE_SETUP.md b/scripts/release/CHROME_STORE_SETUP.md new file mode 100644 index 00000000000..b9445290e92 --- /dev/null +++ b/scripts/release/CHROME_STORE_SETUP.md @@ -0,0 +1,190 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +# Chrome Web Store Publishing Setup + +## Overview + +The `release-all.sh` script publishes Chrome extensions to the Chrome Web Store using the Chrome Web Store API. + +## Required Credentials + +You need 4 environment variables: + +### 1. OAuth Credentials + +Get these from Google Cloud Console: + +1. Go to https://console.cloud.google.com/ +2. Create a project (or use existing) +3. Enable "Chrome Web Store API" +4. Create OAuth 2.0 credentials: + - Application type: "Web application" + - Add authorized redirect URI: `http://localhost` +5. Note the **Client ID** and **Client Secret** + +### 2. Refresh Token + +Generate a refresh token: + +```bash +# 1. Get authorization code +# Open this URL in browser (replace CLIENT_ID): +https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost + +# 2. After authorizing, you'll be redirected to: +# http://localhost/?code=AUTHORIZATION_CODE +# Copy the AUTHORIZATION_CODE + +# 3. Exchange code for refresh token: +curl -X POST https://oauth2.googleapis.com/token \ + -d "client_id=YOUR_CLIENT_ID" \ + -d "client_secret=YOUR_CLIENT_SECRET" \ + -d "code=AUTHORIZATION_CODE" \ + -d "grant_type=authorization_code" \ + -d "redirect_uri=http://localhost" + +# Response will include "refresh_token" - save this! +``` + +### 3. Extension IDs + +Get this from Chrome Web Store Developer Dashboard: + +1. Go to https://chrome.google.com/webstore/devconsole +2. Find the KIE Editors extension +3. Copy the extension ID from the URL + +## Environment Variables + +Set these before running the release script with `--publish`: + +```bash +export CHROME_CLIENT_ID="your-client-id.apps.googleusercontent.com" +export CHROME_CLIENT_SECRET="your-client-secret" +export CHROME_REFRESH_TOKEN="your-refresh-token" +export CHROME_KIE_EDITORS_EXTENSION_ID="kie-editors-extension-id" +``` + +## Usage + +### Test Build (No Publishing) + +```bash +./scripts/release/release-all.sh 10.3.0 +``` + +### Publish to Chrome Web Store + +```bash +# Set credentials +export CHROME_CLIENT_ID="..." +export CHROME_CLIENT_SECRET="..." +export CHROME_REFRESH_TOKEN="..." +export CHROME_KIE_EDITORS_EXTENSION_ID="..." + +# Publish +./scripts/release/release-all.sh 10.3.0 --publish +``` + +## Jenkins Setup + +In Jenkins, credentials are configured in `.ci/jenkins/Jenkinsfile.103xplus.release-publish` using: + +- `CHROME_CLIENT_ID` / `CHROME_CLIENT_SECRET`: `chromeStoreCredentialsId` +- `CHROME_REFRESH_TOKEN`: `chromeStoreRefreshTokenCredentialsId` +- `CHROME_KIE_EDITORS_EXTENSION_ID`: `chromeExtensionIdCredentialsId` + +## How It Works + +The script: + +1. **Gets OAuth Token**: Exchanges refresh token for access token via `https://oauth2.googleapis.com/token` +2. **Uploads Extension**: Uploads the `.zip` file to Chrome Web Store API +3. **Publishes Extension**: Publishes the uploaded item and validates API response status (`OK` or `PUBLISHED_WITH_FRICTION_WARNING`) + +## API Endpoints Used + +- **Token**: `https://oauth2.googleapis.com/token` +- **Upload**: `https://www.googleapis.com/upload/chromewebstore/v1.1/items/{extensionId}` +- **Publish**: `https://www.googleapis.com/chromewebstore/v1.1/items/{extensionId}/publish` + +## Error Handling + +The script will: + +- ✅ Check for required credentials before starting +- ✅ Validate upload success before publishing +- ✅ Show detailed error messages +- ✅ Exit with error code if anything fails + +## Testing + +### Test with Dry Run + +```bash +# Build only (safe) — builds Chrome extension without publishing +./scripts/release/release-all.sh 0.0.0-test +``` + +### Test with Test Extension + +1. Create a test extension in Chrome Web Store +2. Get its extension ID +3. Use test credentials +4. Publish to test extension + +```bash +export CHROME_CLIENT_ID="test-client-id" +export CHROME_CLIENT_SECRET="test-secret" +export CHROME_REFRESH_TOKEN="test-token" +export CHROME_KIE_EDITORS_EXTENSION_ID="test-extension-id" + +./scripts/release/release-all.sh 0.0.0-test --publish +``` + +## Troubleshooting + +### "Failed to get access token" + +- Check CLIENT_ID and CLIENT_SECRET are correct +- Check REFRESH_TOKEN is valid (they can expire) +- Regenerate refresh token if needed + +### "Upload failed" + +- Check extension ID is correct +- Check you have permission to upload to this extension +- Check the .zip file is valid + +### "Publish status: ITEM_NOT_UPDATABLE" + +- Extension might be in review +- Wait for previous version to be published +- Check Chrome Web Store dashboard + +## Security Notes + +- ⚠️ Never commit credentials to git +- ✅ Use Jenkins credentials manager +- ✅ Rotate tokens regularly +- ✅ Use separate credentials for test/production + +## References + +- [Chrome Web Store API Documentation](https://developer.chrome.com/docs/webstore/api_index/) +- [OAuth 2.0 for Web Server Applications](https://developers.google.com/identity/protocols/oauth2/web-server) diff --git a/scripts/release/README.md b/scripts/release/README.md new file mode 100644 index 00000000000..1f26431dcf3 --- /dev/null +++ b/scripts/release/README.md @@ -0,0 +1,160 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +# Release Scripts + +Local-first scripts for releasing Apache KIE Tools. All components are released together under a single unified build. + +## Available Scripts + +| Script | What it does | +| -------------------------- | ---------------------------------------------------------------------------- | +| `release-all.sh` | **The** release script — builds all components and optionally publishes them | +| `create-source-tarball.sh` | Utility: creates an Apache-compliant source zip from the current `HEAD` | + +## Usage + +```bash +./scripts/release/release-all.sh <version> # build all components (dry run — nothing published) +./scripts/release/release-all.sh <version> --rc # build + collect Apache RC artifacts +./scripts/release/release-all.sh <version> --publish # build + publish to all public registries +``` + +### Optional flags + +| Flag | Effect | +| -------------------- | ------------------------------------------------------------------------------- | +| _(none)_ | Build everything locally — nothing is published or uploaded | +| `--rc` | Build and collect all artifacts into `release-artifacts/` for an Apache RC vote | +| `--publish` | Build and push/publish to all public registries and services | +| `--skip-build` | Skip `pnpm build:prod` (use existing `dist/` output) | +| `--upload-url <url>` | GitHub Release upload URL (required by `--publish` for binary assets) | +| `--registry <url>` | Container registry (default: `docker.io/apache`) | + +## What is released + +`release-all.sh` covers all KIE Tools components in one build: + +1. **NPM packages** — all public packages under `packages/` +2. **Chrome extensions** — `chrome-extension-pack-kogito-kie-editors` +3. **VSCode extensions** — all `.vsix` packages +4. **Container images** — all Kogito / sandbox images +5. **Helm charts** — sandbox and runtime-tools-consoles charts +6. **GitHub Pages / webapp** — online-editor, standalone editors, Quarkus accelerator +7. **dev-deployment-upload-service** — cross-platform binaries +8. **Source tarball** — Apache-compliant source zip + +## Prerequisites + +- Node.js 22, pnpm, Go, Helm 3, Docker — depending on which components you need +- Repository bootstrapped: `pnpm bootstrap` +- Credentials set as environment variables (only needed for `--publish`) + +## Local Testing + +### Full RC dry-run from a fresh clone + +```bash +# 1. Bootstrap once +pnpm bootstrap + +# 2. Build and collect all RC artifacts (linters/tests/e2e suppressed automatically) +./scripts/release/release-all.sh 10.3.0 --rc + +# 3. Inspect +ls -lh release-artifacts/ +``` + +### Fast iteration (repo already built) + +If you have already run a full build and just want to re-collect artifacts: + +```bash +rm -rf release-artifacts/ +./scripts/release/release-all.sh 10.3.0 --rc --skip-build +``` + +`--skip-build` skips the `pnpm build:prod` step and goes straight to zipping/copying +from the existing `dist/` folders. Artifact collection is identical to a full run. + +## RC Artifact Names + +All artifacts produced by `--rc` follow the Apache incubator convention: +`apache-kie-<version>-incubating-<artifact-name>.<ext>` + +``` +apache-kie-<version>-incubating-tools-npm-packages.zip +apache-kie-<version>-incubating-business-automation-chrome-extension.zip +apache-kie-<version>-incubating-business-automation-chrome-extension-editors.zip +apache-kie-<version>-incubating-bpmn-vscode-extension.vsix +apache-kie-<version>-incubating-dmn-vscode-extension.vsix +apache-kie-<version>-incubating-drl-vscode-extension.vsix +apache-kie-<version>-incubating-pmml-vscode-extension.vsix +apache-kie-<version>-incubating-kogito-bundle-vscode-extension.vsix +apache-kie-<version>-incubating-business-automation-bundle-vscode-extension.vsix +apache-kie-<version>-incubating-extended-services-vscode-extension.vsix +apache-kie-<version>-incubating-sandbox-webapp.zip +apache-kie-<version>-incubating-business-automation-standalone-editors.zip +apache-kie-<version>-incubating-sandbox-accelerator-quarkus.zip +apache-kie-<version>-incubating-sandbox-helm-chart.tar.gz +apache-kie-<version>-incubating-runtime-tools-console-helm-chart.tar.gz +apache-kie-<version>-incubating-<image-name>-image.tar.gz (one per container image) +apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-macOS-arm64.tar.gz +apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-macOS-x86.tar.gz +apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-linux-x86.tar.gz +apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-windows-x86.tar.gz +apache-kie-<version>-incubating-sources.zip (source zip — always created) +``` + +Container image names (`<image-name>`): +`cors-proxy`, `sandbox-webapp`, `sandbox-extended-services`, +`sandbox-dev-deployment-base`, `sandbox-dev-deployment-dmn-form-webapp`, +`sandbox-dev-deployment-quarkus-blank-app`, `kogito-management-console` + +## Credentials (for `--publish`) + +| Component | Required environment variables | +| ----------------------------- | ----------------------------------------------------------------------------------------------------- | +| NPM packages | `NPM_TOKEN` | +| VSCode extensions | `VSCE_PAT` | +| Chrome extensions | `CHROME_CLIENT_ID`, `CHROME_CLIENT_SECRET`, `CHROME_REFRESH_TOKEN`, `CHROME_KIE_EDITORS_EXTENSION_ID` | +| Container images | `DOCKER_USERNAME`, `DOCKER_PASSWORD` | +| Helm charts | `HELM_REGISTRY` (default: `docker.io/apache`), optionally `HELM_USERNAME` / `HELM_PASSWORD` | +| GitHub Pages / webapp | `GITHUB_TOKEN` | +| dev-deployment-upload-service | `GITHUB_TOKEN`, `--upload-url` | + +See [`CHROME_STORE_SETUP.md`](CHROME_STORE_SETUP.md) for Chrome Web Store credential setup. + +## Version Management + +Before running the release script, update the version throughout the repo: + +```bash +pnpm update-version-to 10.3.0 +pnpm update-kogito-version-to --maven 10.3.0 +pnpm update-stream-name-to 10.3.0 +``` + +## Troubleshooting + +**Permission denied** — `chmod +x scripts/release/release-all.sh` + +**pnpm not found** — `npm install -g pnpm` + +**Build fails** — run `pnpm bootstrap` first + +**NPM publish fails** — verify `NPM_TOKEN` is set and you have publish rights to `@kie-tools` packages diff --git a/scripts/release/create-source-tarball.sh b/scripts/release/create-source-tarball.sh new file mode 100755 index 00000000000..d8e005e9bbb --- /dev/null +++ b/scripts/release/create-source-tarball.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +usage() { + echo "Usage: $0 <version> [--git-ref <ref>] [--output-dir <dir>]" + echo "" + echo "Arguments:" + echo " version Release or RC version (e.g., 10.2.0 or 10.2.0-rc1)" + echo "" + echo "Options:" + echo " --git-ref <ref> Git reference to archive (default: HEAD)" + echo " --output-dir <d> Output directory (default: ./release-artifacts)" + echo " --help" + exit 1 +} + +VERSION="" +GIT_REF="HEAD" +OUTPUT_DIR="$REPO_ROOT/release-artifacts" + +while [[ $# -gt 0 ]]; do + case $1 in + --git-ref) GIT_REF="$2"; shift 2 ;; + --output-dir) OUTPUT_DIR="$2"; shift 2 ;; + --help) usage ;; + *) + if [[ -z "$VERSION" ]]; then VERSION="$1"; else echo "Unknown argument: $1"; usage; fi + shift ;; + esac +done + +[[ -z "$VERSION" ]] && { echo "ERROR: version is required"; usage; } + +echo "==========================================" +echo "Source Tarball" +echo "Version: $VERSION" +echo "Git ref: $GIT_REF" +echo "Output: $OUTPUT_DIR" +echo "==========================================" + +mkdir -p "$OUTPUT_DIR" +ZIPFILE="$OUTPUT_DIR/apache-kie-$VERSION-incubating-sources.zip" + +cd "$REPO_ROOT" +local_archive_ref="$GIT_REF" +if [[ "$local_archive_ref" == "HEAD" ]] && ! git diff --quiet HEAD 2>/dev/null; then + stash_sha=$(git stash create 2>/dev/null || true) + if [[ -n "$stash_sha" ]]; then + local_archive_ref="$stash_sha" + fi +fi + +echo "Creating git archive from ref $local_archive_ref..." +git archive --format=zip --prefix="apache-kie-$VERSION-incubating/" "$local_archive_ref" > "$ZIPFILE" + +if ! unzip -t "$ZIPFILE" > /dev/null 2>&1; then + echo "ERROR: zip verification failed" + exit 1 +fi + +SIZE=$(du -h "$ZIPFILE" | cut -f1) +echo "Created: $ZIPFILE ($SIZE)" + +zip_contents=$(unzip -l "$ZIPFILE") +for required in LICENSE NOTICE DISCLAIMER-WIP; do + if ! echo "$zip_contents" | grep -q "apache-kie-$VERSION-incubating/$required"; then + echo "WARN: $required not found in zip" + fi +done + +echo "==========================================" +echo "DONE" +echo "==========================================" \ No newline at end of file diff --git a/scripts/release/release-all.sh b/scripts/release/release-all.sh new file mode 100755 index 00000000000..af8ff40d8b4 --- /dev/null +++ b/scripts/release/release-all.sh @@ -0,0 +1,773 @@ +#!/usr/bin/env bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -euo pipefail + +# Release script for Apache KIE Tools — builds and optionally releases all components +# under a single unified build. +# +# Usage: +# ./release-all.sh <version> # dry run (build only, nothing published) +# ./release-all.sh <version> --rc # build + collect Apache RC artifacts +# ./release-all.sh <version> --publish # build + publish to all public registries +# +# Optional flags: +# --skip-build Skip pnpm build:prod (use existing dist/ output) +# --upload-url <url> GitHub Release upload URL (required by --publish for binary assets) +# --registry <url> Container registry (default: docker.io/apache) +# --git-ref <ref> Git reference for source tarball (default: HEAD) +# +# Credentials (required only for --publish, sourced from env): +# NPM_TOKEN, VSCE_PAT, +# CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, CHROME_REFRESH_TOKEN, CHROME_KIE_EDITORS_EXTENSION_ID, +# DOCKER_USERNAME, DOCKER_PASSWORD, +# HELM_REGISTRY (default: docker.io/apache), HELM_USERNAME (optional), HELM_PASSWORD (optional), +# GITHUB_TOKEN + +export KIE_TOOLS_BUILD__runLinters=false +export KIE_TOOLS_BUILD__runTests=false +export KIE_TOOLS_BUILD__runEndToEndTests=false + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" + +# --------------------------------------------------------------------------- +# Argument parsing +# --------------------------------------------------------------------------- +VERSION="${1:-}" +PUBLISH=false +RC_MODE=false +SKIP_BUILD=false +UPLOAD_URL="" +REGISTRY="docker.io/apache" +GIT_REF="HEAD" + +shift || true +while [[ $# -gt 0 ]]; do + case $1 in + --publish) PUBLISH=true; shift ;; + --rc) RC_MODE=true; shift ;; + --skip-build) SKIP_BUILD=true; shift ;; + --upload-url) UPLOAD_URL="${2:-}"; shift 2 ;; + --registry) REGISTRY="${2:-}"; shift 2 ;; + --git-ref) GIT_REF="${2:-}"; shift 2 ;; + *) + echo "Unknown option: $1" + echo "Usage: $0 <version> [--publish] [--rc] [--skip-build] [--upload-url <url>] [--registry <url>] [--git-ref <ref>]" + exit 1 + ;; + esac +done + +if [[ -z "${VERSION}" ]]; then + echo "Usage: $0 <version> [--publish] [--rc] [--skip-build] [--upload-url <url>] [--registry <url>]" + echo "Example: $0 10.2.0 --rc" + echo "Example: $0 10.2.0 --publish" + exit 1 +fi + +ARTIFACTS_DIR="${REPO_ROOT}/release-artifacts" + +echo "==========================================" +echo "KIE Tools Release" +echo "Version: ${VERSION}" +echo "RC mode: ${RC_MODE}" +echo "Publish: ${PUBLISH}" +echo "Skip build: ${SKIP_BUILD}" +echo "Registry: ${REGISTRY}" +echo "==========================================" + +cd "${REPO_ROOT}" +if [[ "${SKIP_BUILD}" == "false" ]]; then + echo "" + echo "--- Bumping workspace version to ${VERSION} ---" + pnpm update-version-to "${VERSION}" + pnpm update-kogito-version-to --maven "${VERSION}" + pnpm update-stream-name-to "${VERSION}" +fi + +# --------------------------------------------------------------------------- +# Helper: sign and upload a single asset to a GitHub Release +# --------------------------------------------------------------------------- +upload_github_asset() { + local file="$1" + local asset_name="$2" + local content_type="${3:-application/octet-stream}" + if [[ ! -f "${file}" ]]; then + echo " SKIP ${asset_name} (file not found)" + return + fi + echo " UPLOAD ${asset_name}" + curl -sSf \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Content-Type: ${content_type}" \ + --data-binary "@${file}" \ + "${UPLOAD_URL}?name=${asset_name}" +} + +# --------------------------------------------------------------------------- +# 1. NPM packages +# --------------------------------------------------------------------------- +release_npm_packages() { + echo "" + echo "--- NPM packages ---" + + if [[ "${SKIP_BUILD}" == "false" ]]; then + echo "Building public NPM packages..." + local filter + filter=$(pnpm -r exec bash -c \ + 'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo "-F $(jq -r ".name" package.json)..."; fi') + pnpm ${filter} build:prod + fi + + if [[ "${RC_MODE}" == "true" ]]; then + local tmp_dir="${ARTIFACTS_DIR}/npm-packages-tmp" + local zip_file="apache-kie-${VERSION}-incubating-tools-npm-packages.zip" + mkdir -p "${tmp_dir}" "${ARTIFACTS_DIR}" + local pub_filter + pub_filter=$(pnpm -r exec bash -c \ + 'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo "-F $(jq -r ".name" package.json)"; fi') + pnpm ${pub_filter} exec bash -c "pnpm pack --pack-destination ${tmp_dir}" + (cd "${tmp_dir}" && zip -r "${ARTIFACTS_DIR}/${zip_file}" .) + rm -rf "${tmp_dir}" + echo "RC artifact: ${ARTIFACTS_DIR}/${zip_file}" + fi + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${NPM_TOKEN:-}" ]]; then + echo "ERROR: NPM_TOKEN is required for publishing npm packages" + return 1 + fi + local npmrc_tmp + npmrc_tmp=$(mktemp) + trap "rm -f '${npmrc_tmp}'" EXIT + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "${npmrc_tmp}" + export NPM_CONFIG_USERCONFIG="${npmrc_tmp}" + + local pub_filter + pub_filter=$(pnpm -r exec bash -c \ + 'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo "-F $(jq -r ".name" package.json)"; fi') + pnpm ${pub_filter} exec bash -c ' + PKG_NAME=$(jq -r ".name" package.json) + if ! npm view ${PKG_NAME}@'"${VERSION}"' name --userconfig "'"${npmrc_tmp}"'" &>/dev/null; then + echo "Publishing ${PKG_NAME}@'"${VERSION}"'" + pnpm publish --no-git-checks --access public --userconfig "'"${npmrc_tmp}"'" + else + echo "Skipping ${PKG_NAME}@'"${VERSION}"' (already published)" + fi + ' + rm -f "${npmrc_tmp}" + trap - EXIT + echo "NPM packages published." + fi +} + +# --------------------------------------------------------------------------- +# 2. Chrome extensions +# --------------------------------------------------------------------------- +release_chrome_extensions() { + echo "" + echo "--- Chrome extensions ---" + + if [[ "${SKIP_BUILD}" == "false" ]]; then + echo "Building Chrome extensions..." + pnpm -F "chrome-extension-pack-kogito-kie-editors..." build:prod + fi + + local kie_editors_zip + kie_editors_zip=$(find "packages/chrome-extension-pack-kogito-kie-editors/dist" \ + -maxdepth 1 -name "chrome_extension_kogito_kie_editors_*.zip" 2>/dev/null | head -1) + if [[ -z "${kie_editors_zip}" ]]; then + echo "ERROR: chrome_extension_kogito_kie_editors_*.zip not found — was the build successful?" + return 1 + fi + + if [[ "${RC_MODE}" == "true" ]]; then + mkdir -p "${ARTIFACTS_DIR}" + cp "${kie_editors_zip}" \ + "${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-business-automation-chrome-extension.zip" + + local tmp_kie="${ARTIFACTS_DIR}/kie-editors-tmp" + mkdir -p "${tmp_kie}" + cp -r packages/chrome-extension-pack-kogito-kie-editors/dist/{fonts,*-envelope.*} "${tmp_kie}/" + (cd "${tmp_kie}" && zip -r \ + "${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-business-automation-chrome-extension-editors.zip" .) + rm -rf "${tmp_kie}" + echo "RC artifacts created in: ${ARTIFACTS_DIR}" + fi + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${CHROME_CLIENT_ID:-}" || -z "${CHROME_CLIENT_SECRET:-}" || -z "${CHROME_REFRESH_TOKEN:-}" ]]; then + echo "ERROR: CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, and CHROME_REFRESH_TOKEN are required" + return 1 + fi + + local token_res + token_res=$(curl -sSf -X POST "https://oauth2.googleapis.com/token" \ + -d "client_id=${CHROME_CLIENT_ID}" \ + -d "client_secret=${CHROME_CLIENT_SECRET}" \ + -d "refresh_token=${CHROME_REFRESH_TOKEN}" \ + -d "grant_type=refresh_token") + local access_token + access_token=$(echo "${token_res}" | jq -r '.access_token // empty') + + if [[ -z "${access_token}" ]]; then + echo "ERROR: Failed to obtain Chrome Web Store OAuth token: ${token_res}" + return 1 + fi + + _chrome_upload() { + local ext_id="$1" zip="$2" + local res state + res=$(curl -sSf -X PUT \ + "https://www.googleapis.com/upload/chromewebstore/v1.1/items/${ext_id}" \ + -H "Authorization: Bearer ${access_token}" \ + -H "x-goog-api-version:2" \ + -T "${zip}") + state=$(echo "${res}" | jq -r '.uploadState // empty') + if [[ "${state}" != "SUCCESS" ]]; then + echo "ERROR: Chrome Web Store upload failed for ${ext_id}: ${res}" + return 1 + fi + } + _chrome_publish() { + local ext_id="$1" + local res pub_status + res=$(curl -sSf -X POST \ + "https://www.googleapis.com/chromewebstore/v1.1/items/${ext_id}/publish" \ + -H "Authorization: Bearer ${access_token}" \ + -H "x-goog-api-version:2" \ + -H "Content-Length: 0") + pub_status=$(echo "${res}" | jq -r '.status[0] // .status // empty') + if [[ "${pub_status}" != "OK" && "${pub_status}" != "PUBLISHED_WITH_FRICTION_WARNING" ]]; then + echo "ERROR: Chrome Web Store publish failed for ${ext_id}: ${res}" + return 1 + fi + } + + if [[ -n "${CHROME_KIE_EDITORS_EXTENSION_ID:-}" ]]; then + _chrome_upload "${CHROME_KIE_EDITORS_EXTENSION_ID}" "${kie_editors_zip}" + _chrome_publish "${CHROME_KIE_EDITORS_EXTENSION_ID}" + echo "Chrome extension published." + else + echo "WARN: CHROME_KIE_EDITORS_EXTENSION_ID not set — skipping Chrome publish" + fi + fi +} + +# --------------------------------------------------------------------------- +# 3. VSCode extensions +# --------------------------------------------------------------------------- +release_vscode() { + echo "" + echo "--- VSCode extensions ---" + + declare -A EXTENSIONS=( + ["bpmn-vscode-extension"]="bpmn-vscode-extension" + ["dmn-vscode-extension"]="dmn-vscode-extension" + ["drl-vscode-extension"]="drl-vscode-extension" + ["pmml-vscode-extension"]="pmml-vscode-extension" + ["vscode-extension-kogito-bundle"]="kogito-bundle-vscode-extension" + ["vscode-extension-kie-ba-bundle"]="business-automation-bundle-vscode-extension" + ["extended-services-vscode-extension"]="extended-services-vscode-extension" + ) + + if [[ "${SKIP_BUILD}" == "false" ]]; then + local filter="" + for ext in "${!EXTENSIONS[@]}"; do filter="${filter} -F ${ext}..."; done + echo "Building VSCode extensions..." + pnpm ${filter} build:prod + fi + + if [[ "${RC_MODE}" == "true" ]]; then + mkdir -p "${ARTIFACTS_DIR}" + for ext in "${!EXTENSIONS[@]}"; do + local suffix="${EXTENSIONS[$ext]}" + local vsix + vsix=$(find "packages/${ext}" -maxdepth 2 -name "*.vsix" 2>/dev/null | head -1) + if [[ -n "${vsix}" ]]; then + local dest="${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-${suffix}.vsix" + echo " COPY $(basename "${dest}")" + cp "${vsix}" "${dest}" + else + echo " SKIP ${ext} (no .vsix found)" + fi + done + echo "VSIX files in: ${ARTIFACTS_DIR}/" + fi + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${VSCE_PAT:-}" ]]; then + echo "ERROR: VSCE_PAT is required for publishing VSCode extensions" + return 1 + fi + echo "Publishing to VSCode Marketplace..." + for ext in "${!EXTENSIONS[@]}"; do + find "packages/${ext}" -maxdepth 2 -name "*.vsix" | while read -r vsix; do + echo " Publishing: ${vsix}" + npx vsce publish --packagePath "${vsix}" --pat "${VSCE_PAT}" + done + done + echo "VSCode extensions published." + fi + + if [[ "${PUBLISH}" == "true" && -n "${UPLOAD_URL:-}" && -n "${GITHUB_TOKEN:-}" ]]; then + echo "Uploading .vsix files to GitHub Release..." + for ext in "${!EXTENSIONS[@]}"; do + find "packages/${ext}" -maxdepth 2 -name "*.vsix" | while read -r vsix; do + upload_github_asset "${vsix}" "$(basename "${vsix}")" "application/zip" + done + done + fi +} + +# --------------------------------------------------------------------------- +# 4. Container images +# --------------------------------------------------------------------------- +release_container_images() { + echo "" + echo "--- Container images ---" + + declare -A IMAGES=( + ["cors-proxy"]="packages/cors-proxy-image:incubator-kie-cors-proxy" + ["sandbox-webapp"]="packages/kie-sandbox-webapp-image:incubator-kie-sandbox-webapp" + ["sandbox-extended-services"]="packages/kie-sandbox-extended-services-image:incubator-kie-sandbox-extended-services" + ["sandbox-dev-deployment-base"]="packages/dev-deployment-base-image:incubator-kie-sandbox-dev-deployment-base" + ["sandbox-dev-deployment-dmn-form-webapp"]="packages/dev-deployment-dmn-form-webapp-image:incubator-kie-sandbox-dev-deployment-dmn-form-webapp" + ["sandbox-dev-deployment-quarkus-blank-app"]="packages/dev-deployment-quarkus-blank-app-image:incubator-kie-sandbox-dev-deployment-quarkus-blank-app" + ["kogito-management-console"]="packages/kogito-management-console:incubator-kie-kogito-management-console" + ) + + export KIE_TOOLS_BUILD__buildContainerImages=true + + if [[ "${SKIP_BUILD}" == "false" ]]; then + if ! docker info &>/dev/null; then + echo "WARN: Docker is not running — skipping container image build" + return 0 + fi + echo "Building container images..." + for artifact_name in "${!IMAGES[@]}"; do + local mapping="${IMAGES[$artifact_name]}" + local pkg_path="${mapping%%:*}" + if [[ ! -d "${pkg_path}" ]]; then + echo "ERROR: Image package directory ${pkg_path} not found" + return 1 + fi + local pkg_name + pkg_name=$(node -p "require('./${pkg_path}/package.json').name" 2>/dev/null || basename "${pkg_path}") + echo " BUILD ${artifact_name} (${pkg_name})" + pnpm --filter "${pkg_name}..." build:prod + done + else + if ! docker info &>/dev/null; then + echo "SKIP: Docker is not running — cannot save container image tarballs with --skip-build" + return 0 + fi + fi + + local output_dir="${ARTIFACTS_DIR}" + [[ "${RC_MODE}" == "true" ]] && mkdir -p "${output_dir}" + + echo "Tagging images..." + for artifact_name in "${!IMAGES[@]}"; do + local mapping="${IMAGES[$artifact_name]}" + local pkg_path="${mapping%%:*}" + local image_name="${mapping##*:}" + if [[ ! -d "${pkg_path}" ]]; then + echo "ERROR: Image package directory ${pkg_path} not found" + return 1 + fi + local target_image="${REGISTRY}/${image_name}:${VERSION}" + + # Resolve built image from local docker daemon + local source_image="" + for candidate in \ + "docker.io/apache/${image_name}:${VERSION}" \ + "apache/${image_name}:${VERSION}" \ + "${image_name}:${VERSION}" \ + "docker.io/apache/${image_name}:latest" \ + "apache/${image_name}:latest" \ + "${image_name}:latest"; do + if docker image inspect "${candidate}" &>/dev/null; then + source_image="${candidate}" + break + fi + done + + if [[ -n "${source_image}" ]]; then + docker tag "${source_image}" "${target_image}" + else + echo " WARN could not find local image for ${artifact_name} (${image_name})" + fi + + if [[ "${RC_MODE}" == "true" ]]; then + if docker image inspect "${target_image}" &>/dev/null; then + local tarball="${output_dir}/apache-kie-${VERSION}-incubating-${artifact_name}-image.tar.gz" + echo " SAVE ${tarball}" + docker save "${target_image}" | gzip > "${tarball}" + else + echo "ERROR: Image ${target_image} not found locally for RC export" + return 1 + fi + fi + done + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${DOCKER_USERNAME:-}" || -z "${DOCKER_PASSWORD:-}" ]]; then + echo "ERROR: DOCKER_USERNAME and DOCKER_PASSWORD are required for publishing container images" + return 1 + fi + echo "Pushing images to ${REGISTRY}..." + echo "${DOCKER_PASSWORD}" | docker login "$(echo "${REGISTRY}" | cut -d/ -f1)" \ + -u "${DOCKER_USERNAME}" --password-stdin + for artifact_name in "${!IMAGES[@]}"; do + local mapping="${IMAGES[$artifact_name]}" + local image_name="${mapping##*:}" + local full_image="${REGISTRY}/${image_name}:${VERSION}" + echo " PUSH ${full_image}" + docker push "${full_image}" + done + docker logout "$(echo "${REGISTRY}" | cut -d/ -f1)" + echo "Container images pushed." + fi +} + +# --------------------------------------------------------------------------- +# 5. Helm charts +# --------------------------------------------------------------------------- +release_helm_charts() { + echo "" + echo "--- Helm charts ---" + + if ! command -v helm &>/dev/null; then + echo "WARN: helm not found — skipping Helm chart release" + return 0 + fi + + declare -A CHARTS=( + ["sandbox-helm-chart"]="packages/kie-sandbox-helm-chart" + ["runtime-tools-console-helm-chart"]="packages/runtime-tools-consoles-helm-chart" + ) + + local output_dir="${ARTIFACTS_DIR}" + mkdir -p "${output_dir}" + + local helm_tmp_pkg + helm_tmp_pkg=$(mktemp -d) + trap "rm -rf ${helm_tmp_pkg}" EXIT + + echo "Packaging Helm charts..." + for slug in "${!CHARTS[@]}"; do + local chart_pkg="${CHARTS[$slug]}" + [[ -d "${chart_pkg}" ]] || { echo "ERROR: Helm chart directory ${chart_pkg} not found"; return 1; } + + local chart_yaml="" + for candidate in "${chart_pkg}/src/Chart.yaml" "${chart_pkg}/Chart.yaml"; do + [[ -f "${candidate}" ]] && { chart_yaml="${candidate}"; break; } + done + [[ -z "${chart_yaml}" ]] && { echo "ERROR: Chart.yaml not found in ${chart_pkg}"; return 1; } + + local chart_dir + chart_dir="$(dirname "${chart_yaml}")" + local tmp_dir + tmp_dir=$(mktemp -d) + cp -r "${chart_dir}/." "${tmp_dir}/chart" + sed -i.bak "s/^version:.*/version: ${VERSION}/" "${tmp_dir}/chart/Chart.yaml" + sed -i.bak "s/^appVersion:.*/appVersion: \"${VERSION}\"/" "${tmp_dir}/chart/Chart.yaml" + rm -f "${tmp_dir}/chart/Chart.yaml.bak" + helm package "${tmp_dir}/chart" --destination "${helm_tmp_pkg}" + rm -rf "${tmp_dir}" + + local found + found=$(find "${helm_tmp_pkg}" -maxdepth 1 -name "*-${VERSION}.tgz" | head -1) + if [[ -n "${found}" ]]; then + cp "${found}" "${output_dir}/apache-kie-${VERSION}-incubating-${slug}.tar.gz" + echo " DONE ${output_dir}/apache-kie-${VERSION}-incubating-${slug}.tar.gz" + else + echo "ERROR: Failed to package helm chart for ${slug}" + return 1 + fi + done + + if [[ "${PUBLISH}" == "true" ]]; then + local helm_reg="${HELM_REGISTRY:-docker.io/apache}" + if [[ -z "${helm_reg}" ]]; then + echo "ERROR: HELM_REGISTRY is required for publishing Helm charts" + return 1 + fi + if [[ -n "${HELM_USERNAME:-}" && -n "${HELM_PASSWORD:-}" ]]; then + echo "${HELM_PASSWORD}" | helm registry login "$(echo "${helm_reg}" | cut -d/ -f1)" \ + --username "${HELM_USERNAME}" --password-stdin + fi + for tgz in "${helm_tmp_pkg}"/*-"${VERSION}".tgz; do + if [[ -f "${tgz}" ]]; then + echo " PUSH ${tgz} -> oci://${helm_reg}" + helm push "${tgz}" "oci://${helm_reg}" + fi + done + echo "Helm charts pushed." + fi + rm -rf "${helm_tmp_pkg}" + trap - EXIT +} + +# --------------------------------------------------------------------------- +# 6. GitHub Pages / webapp / accelerator +# --------------------------------------------------------------------------- +release_github_pages() { + echo "" + echo "--- GitHub Pages / webapp / accelerator ---" + + if [[ "${SKIP_BUILD}" == "false" ]]; then + echo "Building online-editor, kie-editors-standalone, chrome-extension-pack-kogito-kie-editors, kie-sandbox-accelerator-quarkus..." + export ONLINE_EDITOR__buildInfo="${VERSION}" + export ONLINE_EDITOR__extendedServicesCompatibleVersion="${VERSION}" + export ONLINE_EDITOR__devDeploymentBaseImageRegistry="docker.io" + export ONLINE_EDITOR__devDeploymentBaseImageAccount="apache" + export ONLINE_EDITOR__devDeploymentBaseImageName="incubator-kie-sandbox-dev-deployment-base" + export ONLINE_EDITOR__devDeploymentBaseImageTag="${VERSION}" + export ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry="docker.io" + export ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount="apache" + export ONLINE_EDITOR__devDeploymentDmnFormWebappImageName="incubator-kie-sandbox-dev-deployment-dmn-form-webapp" + export ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag="${VERSION}" + export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry="docker.io" + export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount="apache" + export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName="incubator-kie-sandbox-dev-deployment-quarkus-blank-app" + export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag="${VERSION}" + pnpm \ + -F "@kie-tools/online-editor..." \ + -F "@kie-tools/kie-editors-standalone..." \ + -F "@kie-tools/chrome-extension-pack-kogito-kie-editors..." \ + -F "@kie-tools/kie-sandbox-accelerator-quarkus..." \ + build:prod + fi + + if [[ "${RC_MODE}" == "true" ]]; then + mkdir -p "${ARTIFACTS_DIR}" + for src_path_suffix in \ + "packages/online-editor/dist:apache-kie-${VERSION}-incubating-sandbox-webapp.zip" \ + "packages/kie-editors-standalone/dist:apache-kie-${VERSION}-incubating-business-automation-standalone-editors.zip" \ + "packages/kie-sandbox-accelerator-quarkus/dist:apache-kie-${VERSION}-incubating-sandbox-accelerator-quarkus.zip" + do + local src="${REPO_ROOT}/${src_path_suffix%%:*}" + local zip_name="${src_path_suffix##*:}" + if [[ -d "${src}" ]]; then + echo " ZIP ${zip_name}" + (cd "${src}" && zip -r "${ARTIFACTS_DIR}/${zip_name}" .) + else + echo " SKIP ${zip_name} (${src} not found)" + fi + done + echo "RC artifacts in: ${ARTIFACTS_DIR}" + fi + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${GITHUB_TOKEN:-}" ]]; then + echo "ERROR: GITHUB_TOKEN is required for publishing to GitHub Pages" + return 1 + fi + + local kogito_online_repo="https://github.com/apache/incubator-kie-kogito-online.git" + local accelerator_repo="https://github.com/apache/incubator-kie-sandbox-quarkus-accelerator.git" + local tmp_dir + tmp_dir=$(mktemp -d) + trap "rm -rf ${tmp_dir}" EXIT + + local auth_url="${kogito_online_repo/https:\/\//https://${GITHUB_TOKEN}@}" + git clone --branch gh-pages --depth 1 "${auth_url}" "${tmp_dir}/kogito-online" + ( + cd "${tmp_dir}/kogito-online" + git config user.email "[email protected]" + git config user.name "Apache KIE Release Bot" + find . -maxdepth 1 ! -name '.' ! -name 'dev' ! -name 'editors' ! -name 'standalone' \ + ! -name 'chrome-extension' ! -name '.nojekyll' ! -name 'CNAME' -exec rm -rf {} + + + local online_dist="${REPO_ROOT}/packages/online-editor/dist" + if [[ -d "${online_dist}" ]]; then + local editors_dir="editors/${VERSION}" + rm -rf "${editors_dir}" && mkdir -p "${editors_dir}" + rm -rf editors/latest && ln -s "${VERSION}" editors/latest + cp -r "${online_dist}/." . + fi + local standalone_dist="${REPO_ROOT}/packages/kie-editors-standalone/dist" + [[ -d "${standalone_dist}" ]] && cp -r "${standalone_dist}/." "editors/${VERSION}/" + local chrome_dist="${REPO_ROOT}/packages/chrome-extension-pack-kogito-kie-editors/dist" + if [[ -d "${chrome_dist}" ]]; then + local chrome_dir="chrome-extension/${VERSION}" + rm -rf "${chrome_dir}" && mkdir -p "${chrome_dir}" + cp -r "${chrome_dist}/fonts" "${chrome_dir}/" 2>/dev/null || true + cp "${chrome_dist}"/*-envelope.* "${chrome_dir}/" 2>/dev/null || true + fi + git add . + git commit -m "Deploy ${VERSION} (Online Editor + Standalone Editors + Chrome Extension editors)" \ + || echo " (nothing to commit)" + git push origin gh-pages + ) + echo "Pushed to GitHub Pages." + + local accel_content="${REPO_ROOT}/packages/kie-sandbox-accelerator-quarkus/dist/git-repo-content" + if [[ -d "${accel_content}" ]]; then + local auth_accel="${accelerator_repo/https:\/\//https://${GITHUB_TOKEN}@}" + git clone --depth 1 "${auth_accel}" "${tmp_dir}/accelerator" + ( + cd "${tmp_dir}/accelerator" + git config user.email "[email protected]" + git config user.name "Apache KIE Release Bot" + git checkout --orphan "${VERSION}" + cp -r "${accel_content}/." . + git add . + git commit -m "Apache KIE Sandbox Quarkus Accelerator ${VERSION}" + git tag "${VERSION}" + git push origin "refs/heads/${VERSION}:refs/heads/${VERSION}" "refs/tags/${VERSION}:refs/tags/${VERSION}" + ) + echo "Pushed accelerator to tag ${VERSION}." + fi + fi +} + +# --------------------------------------------------------------------------- +# 7. dev-deployment-upload-service +# --------------------------------------------------------------------------- +release_dev_deployment_upload_service() { + echo "" + echo "--- dev-deployment-upload-service ---" + + if [[ "${SKIP_BUILD}" == "false" ]]; then + echo "Building dev-deployment-upload-service..." + DDUS_VERSION="${VERSION}" pnpm -F "@kie-tools/dev-deployment-upload-service..." build:prod + fi + + local dist="${REPO_ROOT}/packages/dev-deployment-upload-service/dist" + if [[ ! -d "${dist}" ]]; then + echo "ERROR: packages/dev-deployment-upload-service/dist not found" + return 1 + fi + + declare -A PLATFORM_MAP=( + ["dev-deployment-upload-service-darwin-arm64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-macOS-arm64.tar.gz" + ["dev-deployment-upload-service-darwin-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-macOS-x86.tar.gz" + ["dev-deployment-upload-service-linux-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-linux-x86.tar.gz" + ["dev-deployment-upload-service-windows-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-windows-x86.tar.gz" + ) + + if [[ "${RC_MODE}" == "true" ]]; then + mkdir -p "${ARTIFACTS_DIR}" + for src_name in "${!PLATFORM_MAP[@]}"; do + local rc_name="${PLATFORM_MAP[$src_name]}" + if [[ -f "${dist}/${src_name}" ]]; then + cp "${dist}/${src_name}" "${ARTIFACTS_DIR}/${rc_name}" + echo " COPY ${rc_name}" + else + echo "ERROR: Artifact ${dist}/${src_name} not found" + return 1 + fi + done + echo "RC artifacts in: ${ARTIFACTS_DIR}" + fi + + if [[ "${PUBLISH}" == "true" ]]; then + if [[ -z "${GITHUB_TOKEN:-}" || -z "${UPLOAD_URL:-}" ]]; then + echo "ERROR: GITHUB_TOKEN and --upload-url are required for publishing dev-deployment-upload-service" + return 1 + fi + for src_name in "${!PLATFORM_MAP[@]}"; do + upload_github_asset "${dist}/${src_name}" "${src_name}" "application/gzip" + done + echo "dev-deployment-upload-service binaries uploaded." + fi +} + +# --------------------------------------------------------------------------- +# 8. Source tarball (always created; no --publish step) +# --------------------------------------------------------------------------- +release_source_tarball() { + echo "" + echo "--- Source tarball ---" + mkdir -p "${ARTIFACTS_DIR}" + local zipfile="${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-sources.zip" + local archive_ref="${GIT_REF}" + + # If archiving HEAD and there are uncommitted working tree modifications (e.g. local version bumps), + # create a stash commit to ensure the working tree state is preserved in the archive. + if [[ "${archive_ref}" == "HEAD" ]] && ! git diff --quiet HEAD 2>/dev/null; then + local stash_sha + stash_sha=$(git stash create 2>/dev/null || true) + if [[ -n "${stash_sha}" ]]; then + archive_ref="${stash_sha}" + fi + fi + + echo "Creating git archive from ref ${archive_ref}..." + git archive --format=zip --prefix="apache-kie-${VERSION}-incubating/" "${archive_ref}" > "${zipfile}" + if ! unzip -t "${zipfile}" > /dev/null 2>&1; then + echo "ERROR: Source zip verification failed" + return 1 + fi + local size + size=$(du -h "${zipfile}" | cut -f1) + echo "Created: ${zipfile} (${size})" + local zip_contents + zip_contents=$(unzip -l "${zipfile}") + for required in LICENSE NOTICE DISCLAIMER-WIP; do + echo "${zip_contents}" | grep -q "apache-kie-${VERSION}-incubating/${required}" \ + || echo "WARN: ${required} not found in source zip" + done +} + +# --------------------------------------------------------------------------- +# Run all release steps +# --------------------------------------------------------------------------- +FAILED=() +run_step() { + local name="$1" fn="$2" + local status=0 + ( + set -euo pipefail + "${fn}" + ) || status=$? + + if [[ ${status} -eq 0 ]]; then + echo "✅ ${name} — OK" + else + echo "❌ ${name} — FAILED (exit code ${status})" + FAILED+=("${name}") + fi +} + +run_step "npm-packages" release_npm_packages +run_step "chrome-extensions" release_chrome_extensions +run_step "vscode" release_vscode +run_step "container-images" release_container_images +run_step "helm-charts" release_helm_charts +run_step "github-pages" release_github_pages +run_step "dev-deployment-upload-service" release_dev_deployment_upload_service +run_step "source-tarball" release_source_tarball + +echo "" +echo "==========================================" +echo "Release Summary" +echo "==========================================" +if [[ ${#FAILED[@]} -eq 0 ]]; then + echo "✅ All components completed successfully!" + [[ "${RC_MODE}" == "true" || "${PUBLISH}" == "true" ]] && echo "Artifacts in: ${ARTIFACTS_DIR}" + exit 0 +else + echo "❌ Failed components:" + for c in "${FAILED[@]}"; do echo " - ${c}"; done + exit 1 +fi --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
