From 4ecbea673415ba39efedc86cff963dae53cc303d Mon Sep 17 00:00:00 2001 From: Antoine CORDIER Date: Fri, 7 Jun 2024 17:02:10 +0200 Subject: [PATCH] ci: update release job and drop semantic release --- .circleci/config.yml | 186 +++++++++++++++++++++----- .github/workflows/clean-release.yml | 36 ----- .github/workflows/trigger-release.yml | 39 ++++-- make/docker.mk | 10 -- make/lint.mk | 6 +- make/tool.mk | 2 +- release.config.js | 60 --------- scripts/generate-changelog.mjs | 98 ++++++++++++++ scripts/get-release-branch.mjs | 28 ++++ scripts/lib/circleci.mjs | 40 ++++++ scripts/lib/index.mjs | 12 +- scripts/lib/version.mjs | 30 +++++ scripts/release-helm-chart.mjs | 86 +----------- scripts/run-kind.mjs | 107 +++++++-------- scripts/trigger-release.mjs | 47 +++++++ 15 files changed, 486 insertions(+), 301 deletions(-) delete mode 100644 .github/workflows/clean-release.yml delete mode 100644 release.config.js create mode 100644 scripts/generate-changelog.mjs create mode 100644 scripts/get-release-branch.mjs create mode 100644 scripts/lib/circleci.mjs create mode 100644 scripts/lib/version.mjs create mode 100644 scripts/trigger-release.mjs diff --git a/.circleci/config.yml b/.circleci/config.yml index 70cb08cb5..845cb0ad8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,25 +7,34 @@ orbs: keeper: gravitee-io/keeper@0.6.3 gravitee: gravitee-io/gravitee@4.1.1 slack: circleci/slack@4.13.3 + gh: circleci/github-cli@1.0.5 parameters: go-version: type: string default: "1.22.1" + trigger: + type: enum + default: test + enum: + - release + - test + release-version: + type: string + default: "" + latest: + type: boolean + default: false + description: Is this version the latest version available ? + dry-run: + type: boolean + default: false executors: azure-cli: - parameters: - resource_class: - description: The resource class - type: enum - enum: ["small", "medium", "large", "xlarge"] - default: "medium" docker: - # Version can be found here https://docs.microsoft.com/en-us/cli/azure/release-notes-azure-cli - # be careful when updating the version as it looks it is not following semver - image: mcr.microsoft.com/azure-cli:2.61.0 - resource_class: <> + resource_class: small commands: notify-on-failure: @@ -242,7 +251,6 @@ jobs: login-to-azure: executor: name: azure-cli - resource_class: small parameters: clusterName: type: enum @@ -341,38 +349,140 @@ jobs: - go/save-cache - notify-on-failure - semantic-release: + release: docker: - image: cimg/go:<< pipeline.parameters.go-version >>-node - environment: - GITHUB_TOKEN: "keeper://TIlcGPFq4rN5GvgnZb9hng/field/password" - GIT_AUTHOR_NAME: "keeper://q9AKrHbbTqSGDoUl-Lg85g/field/login" - GIT_AUTHOR_EMAIL: "keeper://q9AKrHbbTqSGDoUl-Lg85g/custom_field/email" - GIT_COMMITTER_NAME: "keeper://q9AKrHbbTqSGDoUl-Lg85g/field/login" - GIT_COMMITTER_EMAIL: "keeper://q9AKrHbbTqSGDoUl-Lg85g/custom_field/email" - DOCKER_USERNAME: "keeper://cooU9UoXIk8Kj0hsP2rkBw/field/login" - DOCKER_TOKEN: "keeper://cooU9UoXIk8Kj0hsP2rkBw/field/password" steps: - checkout - - gravitee/install-semantic-release - setup_remote_docker - - keeper/exec: - step-name: Docker login + - keeper/env-export: + secret-url: keeper://TIlcGPFq4rN5GvgnZb9hng/field/password + var-name: GITHUB_TOKEN + - keeper/env-export: + secret-url: keeper://q9AKrHbbTqSGDoUl-Lg85g/field/login + var-name: GIT_AUTHOR_NAME + - keeper/env-export: + secret-url: keeper://q9AKrHbbTqSGDoUl-Lg85g/custom_field/email + var-name: GIT_AUTHOR_EMAIL + - keeper/env-export: + secret-url: keeper://q9AKrHbbTqSGDoUl-Lg85g/field/login + var-name: GIT_COMMITTER_NAME + - keeper/env-export: + secret-url: keeper://q9AKrHbbTqSGDoUl-Lg85g/custom_field/email + var-name: GIT_COMMITTER_EMAIL + - keeper/env-export: + secret-url: keeper://cooU9UoXIk8Kj0hsP2rkBw/field/login + var-name: DOCKER_USERNAME + - keeper/env-export: + secret-url: keeper://cooU9UoXIk8Kj0hsP2rkBw/field/password + var-name: DOCKER_TOKEN + - keeper/env-export: + secret-url: keeper://hfnQD5TEfxzwRXUKhJhM-A/field/password + var-name: JIRA_TOKEN + - run: + name: Switch to release branch + command: | + export RELEASE_BRANCH=$(npx zx scripts/get-release-branch.mjs --version << pipeline.parameters.release-version >>) + echo "Switching to branch $RELEASE_BRANCH" + git fetch + git switch $RELEASE_BRANCH 2>/dev/null || git switch -c $RELEASE_BRANCH + - run: + name: Docker login command: docker login --username="${DOCKER_USERNAME}" -p="${DOCKER_TOKEN}" - run: - name: Install operator SDK + name: Build Docker image for version << pipeline.parameters.release-version >> command: | - export OPERATOR_SDK_RELEASE_VERSION=v1.23.0 - export ARCH=$(case $(uname -m) in amd64|x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) - export OS=$(uname | awk '{print tolower($0)}') - export DOWNLOAD_URL=https://github.com/operator-framework/operator-sdk/releases/latest/download - export BINARY=operator-sdk_${OS}_${ARCH} - curl -OJL ${DOWNLOAD_URL}/${BINARY} - chmod +x ${BINARY} && sudo cp ${BINARY} /usr/local/bin/operator-sdk && rm ${BINARY} + docker build -t graviteeio/kubernetes-operator:<< pipeline.parameters.release-version >> . + - when: + condition: << pipeline.parameters.latest >> + steps: + - run: + name: Tag << pipeline.parameters.release-version >> image as latest + command: | + docker tag \ + graviteeio/kubernetes-operator:<< pipeline.parameters.release-version >> \ + graviteeio/kubernetes-operator:latest + - when: + condition: + and: + - not: << pipeline.parameters.dry-run >> + - << pipeline.parameters.latest >> + steps: + - run: + name: Push << pipeline.parameters.release-version >> Docker image as latest tag + command: | + docker push graviteeio/kubernetes-operator:<< pipeline.parameters.release-version >> + docker push graviteeio/kubernetes-operator:latest + - when: + condition: + and: + - not: << pipeline.parameters.dry-run >> + - not: << pipeline.parameters.latest >> + steps: + - run: + name: Push << pipeline.parameters.release-version >> Docker image tag + command: | + docker push graviteeio/kubernetes-operator:<< pipeline.parameters.release-version >> - helm/install_helm_client - - keeper/exec: - step-name: "Run Semantic Release" - command: npx semantic-release + - when: + condition: << pipeline.parameters.dry-run >> + steps: + - run: + name: Dry run release Helm chart + command: | + npx zx scripts/release-helm-chart.mjs --dry-run --version << pipeline.parameters.release-version >> + - when: + condition: + not: << pipeline.parameters.dry-run >> + steps: + - run: + name: Release Helm chart + command: | + npx zx scripts/release-helm-chart.mjs --version << pipeline.parameters.release-version >> + - run: + name: Commit and tag release + command: | + make add-license > /dev/null + git add helm/gko/Chart.yaml + git commit -m "ci: release version << pipeline.parameters.release-version >> [skip ci]" + git tag << pipeline.parameters.release-version >> + echo + git diff HEAD~1 HEAD + - when: + condition: + not: << pipeline.parameters.dry-run >> + steps: + - run: + name: Push release tag and commit + command: | + export RELEASE_BRANCH=$(npx zx scripts/get-release-branch.mjs --version << pipeline.parameters.release-version >>) + git push -u origin $RELEASE_BRANCH + git push --tags origin $RELEASE_BRANCH + - run: + name: Generate Changelog + command: npx zx scripts/generate-changelog.mjs --version << pipeline.parameters.release-version >> > /tmp/CHANGELOG.md + - when: + condition: << pipeline.parameters.dry-run >> + steps: + - run: + name: Print Changelog + command: cat /tmp/CHANGELOG.md + - run: + name: Generate Release Artifacts + command: | + cp -r helm/gko/crds /tmp/crds + pushd /tmp/crds + zip -r /tmp/custom-resource-definitions.zip ./* + popd + - when: + condition: + not: << pipeline.parameters.dry-run >> + steps: + - gh/setup + - run: + name: Publish Github Release << pipeline.parameters.release-version >> + command: | + gh release create --latest << pipeline.parameters.release-version >> /tmp/custom-resource-definitions.zip -F /tmp/CHANGELOG.md notify-release-slack: docker: @@ -462,6 +572,10 @@ workflows: and: - not: equal: [master, << pipeline.git.branch >>] + - not: + equal: ['release', << pipeline.parameters.trigger >>] + - not: + equal: ['test', << pipeline.parameters.trigger >>] jobs: - lint-sources: name: Lint sources @@ -550,10 +664,10 @@ workflows: release: when: - equal: [trigger-release, << pipeline.git.branch >>] + equal: ['release', << pipeline.parameters.trigger >>] jobs: - - semantic-release: - name: Semantic Release + - release: + name: Release context: cicd-orchestrator notify-release: diff --git a/.github/workflows/clean-release.yml b/.github/workflows/clean-release.yml deleted file mode 100644 index 9f2adc05e..000000000 --- a/.github/workflows/clean-release.yml +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2015 The Gravitee team (http://gravitee.io) -# -# Licensed 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. - -name: Clean release - -on: - push: - tags: - - '[0-9]+.[0-9]+.[0-9]+' - -jobs: - clean-release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: "Set up git" - run: | - git config user.name "Gravitee.io Bot" - git config user.email contact@gravitee.io - - name: "Delete release branch" - run: | - echo "🚀 Deleting release branch" - git push origin --delete trigger-release &>/dev/null diff --git a/.github/workflows/trigger-release.yml b/.github/workflows/trigger-release.yml index 66cb999ec..c3bb0f4f8 100644 --- a/.github/workflows/trigger-release.yml +++ b/.github/workflows/trigger-release.yml @@ -14,21 +14,34 @@ name: Trigger Release -on: workflow_dispatch - +on: + workflow_dispatch: + inputs: + version: + description: 'Which version should we release ?' + required: true + type: string + latest: + description: 'Is this version the latest version ?' + required: false + default: false + type: boolean + dry-run: + description: 'Should this run as a dry run ?' + required: true + default: true + type: boolean jobs: trigger-release: runs-on: ubuntu-latest + env: + VERSION: ${{ inputs.version }} + LATEST: ${{ inputs.latest }} + DRY_RUN: ${{ inputs.dry-run }} steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: "Set up git" - run: | - git config user.name "Gravitee.io Bot" - git config user.email contact@gravitee.io - - name: "Create release branch" + - name: "Trigger release pipeline" run: | - echo "🚀 Creating release branch" - git checkout -b trigger-release - git push --set-upstream origin trigger-release + echo "🚀 Releasing version ${VERSION}" + echo " Latest: ${LATEST}" + echo " Dry run: ${DRY_RUN}" + npx zx scripts/trigger-release.mjs --version ${VERSION} --dry-run ${DRY_RUN} --latest ${LATEST} diff --git a/make/docker.mk b/make/docker.mk index f931aecd8..a4ceae275 100644 --- a/make/docker.mk +++ b/make/docker.mk @@ -14,14 +14,4 @@ docker-build: ## Build docker image with the manager. docker-push: ## Push docker image with the manager. docker push ${IMG}:${TAG} -# RELEASE - -.PHONY: docker-build-release -docker-build-release: ## Build docker image with the manager. - docker build -t ${IMG}:${TAG} -t ${IMG}:latest . - -.PHONY: docker-push-release -docker-push-release: ## Push docker image with the manager. - docker push ${IMG}:${TAG} - docker push ${IMG}:latest diff --git a/make/lint.mk b/make/lint.mk index f2b9dff76..27818a573 100644 --- a/make/lint.mk +++ b/make/lint.mk @@ -28,7 +28,7 @@ lint-licenses: addlicense ## Run addlicense linter and fail on error .PHONY: add-license add-license: addlicense ## Add license headers to files @echo "Adding license headers ..." - $(ADDLICENSE) -f LICENSE_TEMPLATE.txt \ + @$(ADDLICENSE) -f LICENSE_TEMPLATE.txt \ -ignore ".circleci/**" \ -ignore ".mergify.yml" \ -ignore "config/**" \ @@ -39,5 +39,5 @@ lint: $(ALL_LINT) .PHONY: lint-fix lint-fix: golangci-lint addlicense ## Fix whatever golangci-lint can fix and add licenses headers - $(GOLANGCILINT) run ./... --fix - $(MAKE) add-license + @$(GOLANGCILINT) run ./... --fix + @$(MAKE) add-license diff --git a/make/tool.mk b/make/tool.mk index c5183c895..57273d7b7 100644 --- a/make/tool.mk +++ b/make/tool.mk @@ -3,7 +3,7 @@ ## Location to install dependencies to LOCALBIN ?= $(shell pwd)/bin $(LOCALBIN): - mkdir -p $(LOCALBIN) + @mkdir -p $(LOCALBIN) ## Tool Binaries CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen diff --git a/release.config.js b/release.config.js deleted file mode 100644 index 0a00a9809..000000000 --- a/release.config.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2015 The Gravitee team (http://gravitee.io) - * - * Licensed 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. - */ - -const config = { - branches: ["trigger-release"], - tagFormat: "${version}", -}; -const changelogFile = "CHANGELOG.md"; -const chartDirectory = "helm/gko" -const crdDirectory = "helm/gko/crds" - -const plugins = [ - "@semantic-release/commit-analyzer", - "@semantic-release/release-notes-generator", - [ - "@semantic-release/changelog", - { - changelogFile, - }, - ], - [ - "@semantic-release/exec", - { - prepareCmd: - "npx zx scripts/release-helm-chart.mjs --version ${nextRelease.version} --img graviteeio/kubernetes-operator", - }, - ], - [ - "@semantic-release/github", - { - assets: [ - { - path: crdDirectory, label: "Operator Custom Resource Definitions" - }, - ], - }, - ], - [ - "@semantic-release/git", - { - assets: [changelogFile, chartDirectory], - message: "chore(release): ${nextRelease.version} [skip ci]", - }, - ], -]; - -module.exports = { ...config, plugins }; diff --git a/scripts/generate-changelog.mjs b/scripts/generate-changelog.mjs new file mode 100644 index 000000000..6b915dd1f --- /dev/null +++ b/scripts/generate-changelog.mjs @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed 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. + */ + +import { LOG, isEmptyString, toggleVerbosity } from "./lib/index.mjs"; + +const VERSION = argv.version; +const VERBOSE = argv.verbose; +const JIRA_TOKEN = process.env.JIRA_TOKEN; +const JIRA_BASE = "https://gravitee.atlassian.net/rest/api/3"; +const JIRA_PROJECT = "GKO"; +const DATE_OPTS = { year: "numeric", month: "long", day: "numeric" }; + +const JIRA_HEADERS = { + Authorization: `Basic ${JIRA_TOKEN}`, + Accept: "application/json", +}; + +const CHANGELOG_ISSUES = ["Story"]; + +toggleVerbosity(VERBOSE); + +if (isEmptyString(VERSION)) { + LOG.red("You must specify a version using the --version flag"); + await $`exit 1`; +} + +if (isEmptyString(JIRA_TOKEN)) { + LOG.red("JIRA_TOKEN must be defined as an environment variable"); + await $`exit 1`; +} + +async function getJiraVersion(versionName) { + return fetch(`${JIRA_BASE}/project/GKO/versions`, { + method: "GET", + headers: JIRA_HEADERS, + }) + .then((response) => response.json()) + .then((versions) => versions.find(({ name }) => name === versionName)); +} + +async function getJiraIssues(versionId) { + const query = `jql=project=${JIRA_PROJECT} AND fixVersion=${versionId}`; + + const issues = await fetch(`${JIRA_BASE}/search?${query}`, { + method: "GET", + headers: JIRA_HEADERS, + }) + .then((response) => response.json()) + .then((body) => body.issues); + + return issues + .filter((issue) => CHANGELOG_ISSUES.includes(issue.fields.issuetype.name)) + .map((issue) => ({ + key: issue.key, + githubIssue: issue.fields.customfield_10115, + summary: issue.fields.summary, + components: issue.fields.components, + type: issue.fields.issuetype.name, + })); +} + +const jiraVersion = await getJiraVersion(VERSION); + +const jiraIssues = await getJiraIssues(jiraVersion.id); + +let changelog = ` +## GKO ${VERSION} - ${new Date().toLocaleDateString("en-US", DATE_OPTS)} +`; + +changelog += ` +
+ What's new ? +`; + +for (const issue of jiraIssues) { + changelog += ` + * ${issue.summary} + `; +} + +changelog += ` +
+`; + +echo(changelog); diff --git a/scripts/get-release-branch.mjs b/scripts/get-release-branch.mjs new file mode 100644 index 000000000..bebc59835 --- /dev/null +++ b/scripts/get-release-branch.mjs @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed 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. + */ + +import { LOG, isEmptyString } from "./lib/index.mjs"; + +import { Version } from "./lib/version.mjs"; + +const VERSION = argv.version; + +if (isEmptyString(VERSION)) { + LOG.red("You must specify a version using the --version flag"); + await $`exit 1`; +} + +LOG.log(new Version(VERSION).branch()); diff --git a/scripts/lib/circleci.mjs b/scripts/lib/circleci.mjs new file mode 100644 index 000000000..ad61cf1dc --- /dev/null +++ b/scripts/lib/circleci.mjs @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed 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. + */ + +import { isEmptyString } from "./index.mjs"; + +const CIRCLECI_BASE = "https://circleci.com/api/v2"; +const ORG = "gravitee-io"; +const SCM = "github"; +const PROJECT = "gravitee-kubernetes-operator"; +const CIRCLECI_TOKEN = process.env.CIRCLECI_TOKEN; + +if (isEmptyString(CIRCLECI_TOKEN)) { + LOG.red("You must specify a version using the --version flag"); + await $`exit 1`; +} + +export async function triggerPipeline(parameters) { + return fetch(`${CIRCLECI_BASE}/project/${SCM}/${ORG}/${PROJECT}/pipeline`, { + method: "POST", + headers: { + "Circle-Token": CIRCLECI_TOKEN, + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ parameters }), + }).then((response) => response.json()); +} diff --git a/scripts/lib/index.mjs b/scripts/lib/index.mjs index 6c0fc83a5..b829a582b 100644 --- a/scripts/lib/index.mjs +++ b/scripts/lib/index.mjs @@ -59,6 +59,10 @@ export function isNonEmptyString(str) { return String(str) === str && str.trim().length > 0; } +export function isEmptyString(str) { + return !isNonEmptyString(str); +} + // Color loggers const green = newLoggerFn(chalk.green); const blue = newLoggerFn(chalk.blue); @@ -71,15 +75,9 @@ export const LOG = Object.seal({ green, blue, magenta, yellow, red, log }); // Path to the local helm chart directory const chartDir = path.join(__dirname, "..", "helm", "gko"); -// Path to the helm templates directory -const templateDir = path.join(chartDir, "templates"); - // Path to the helm crds directory. This resources are not templated. const crdDir = path.join(chartDir, "crds"); -// The template file is the file that contains all the resources except the CRDs. This file can be templated. -const templateFile = path.join(templateDir, "bundle.yaml"); - // The gravitee.io official helm charts repository const chartsRepo = "gravitee-io/helm-charts"; @@ -88,8 +86,6 @@ const releaseBranch = "gh-pages"; export const HELM = { chartDir, - templateDir, - templateFile, crdDir, chartsRepo, releaseBranch, diff --git a/scripts/lib/version.mjs b/scripts/lib/version.mjs new file mode 100644 index 000000000..4535e8273 --- /dev/null +++ b/scripts/lib/version.mjs @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed 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. + */ + +export class Version { + major; + minor; + patch; + + constructor(version) { + const [major, minor, patch] = [...version.split(".").map(Number)]; + Object.assign(this, { major, minor, patch }); + } + + branch() { + return `${this.major}.${this.minor}.x`; + } +} diff --git a/scripts/release-helm-chart.mjs b/scripts/release-helm-chart.mjs index 82f4b77c4..d56ce2a45 100644 --- a/scripts/release-helm-chart.mjs +++ b/scripts/release-helm-chart.mjs @@ -19,46 +19,34 @@ import { HELM, toggleVerbosity, time, - isNonEmptyString, + isEmptyString, } from "./lib/index.mjs"; const WORKING_DIR = path.join(os.tmpdir(), "helm-charts"); const PROJECT_DIR = path.join(__dirname, ".."); const VERSION = argv.version; -const IMG = argv.img; const VERBOSE = argv.verbose; const DRY_RUN = argv["dry-run"]; -const GITHUB_TOKEN=$.env.GITHUB_TOKEN +const GITHUB_TOKEN = $.env.GITHUB_TOKEN; -$.env["IMG"] = `${IMG}`; -$.env["TAG"] = `${VERSION}`; +toggleVerbosity(VERBOSE); LOG.magenta(` 🚀 Releasing version ${VERSION} ... 📦 Project dir | ${PROJECT_DIR} - 📦 Working dir | ${WORKING_DIR} - 🐳 Docker image | ${$.env.IMG}`); - -toggleVerbosity(VERBOSE); + 📦 Working dir | ${WORKING_DIR}`); await checkRequirements(); async function checkRequirements() { - if (!isNonEmptyString(VERSION)) { + if (isEmptyString(VERSION)) { LOG.red("You must specify a version to release using the --version flag"); await $`exit 1`; } - if (!isNonEmptyString(IMG)) { - LOG.red( - "You must specify a docker image to build (without any tag) using the --img flag" - ); - await $`exit 1`; - } - - if (!isNonEmptyString(GITHUB_TOKEN) && !DRY_RUN) { + if (isEmptyString(GITHUB_TOKEN) && !DRY_RUN) { LOG.red( "A github token is needed to push the release. Please set the GITHUB_TOKEN environment variable." ); @@ -76,34 +64,6 @@ async function checkRequirements() { } } -LOG.blue(` -🐳 Building docker image ... -`); - -if (!DRY_RUN) { - await time(buildDockerImage); -} else { - LOG.yellow(` ⚠️ This is a dry run, image will not be built ...`); -} - -async function buildDockerImage() { - await $`make docker-build-release`; -} - -LOG.blue(` -🐳 Pushing docker image ... -`); - -if (!DRY_RUN) { - await time(pushDockerImage); -} else { - LOG.yellow(` ⚠️ This is a dry run, image will not be pushed ...`); -} - -async function pushDockerImage() { - await $`make docker-push-release`; -} - LOG.blue(` ⎈ Checking out ${HELM.chartsRepo}:${HELM.releaseBranch} ... `); @@ -117,7 +77,6 @@ async function checkoutHelmCharts() { --depth 1 ${WORKING_DIR}`; } - LOG.blue(` ⎈ Packaging chart ... `); @@ -155,23 +114,13 @@ if (!DRY_RUN) { async function publishRelease() { cd(WORKING_DIR); - await $`git remote set-url origin "https://${GITHUB_TOKEN}@github.com/${HELM.chartsRepo}.git"` + await $`git remote set-url origin "https://${GITHUB_TOKEN}@github.com/${HELM.chartsRepo}.git"`; await $`git add helm/gko/gko-${VERSION}.tgz index.yaml`; await $`git commit -m "chore(gko): release version ${VERSION}"`; await $`git push origin ${HELM.releaseBranch}`; cd(PROJECT_DIR); } -LOG.blue(` -📦 Generating legacy bundle.yml file ... -`); - -await time(generateLegacyBundle); - -async function generateLegacyBundle() { - await $`make helm-template`; -} - LOG.blue(` ⎈ Setting chart version to ${VERSION} ... `); @@ -186,26 +135,6 @@ async function setChartVersion() { await fs.writeFile(`${HELM.chartDir}/Chart.yaml`, YAML.stringify(chartYaml)); } -LOG.blue(` -⎈ Generating chart reference ... -`); - -await time(generateChartReference); - -async function generateChartReference() { - await $`make helm-reference`; -} - -LOG.blue(` -⎈ Adding license headers to generated files ... -`); - -await time(addLicense); - -async function addLicense() { - await $`make add-license`; -} - if (!DRY_RUN) { LOG.magenta(` 🎉 version ${VERSION} has been released !`); @@ -213,4 +142,3 @@ if (!DRY_RUN) { LOG.magenta(` 🎉 dry run done for version ${VERSION}`); } - diff --git a/scripts/run-kind.mjs b/scripts/run-kind.mjs index d0f1ceec8..8b2de1b25 100644 --- a/scripts/run-kind.mjs +++ b/scripts/run-kind.mjs @@ -14,82 +14,80 @@ * limitations under the License. */ -import { LOG, setNoQuoteEscape, setQuoteEscape, time, toggleVerbosity } from "./lib/index.mjs"; +import { + LOG, + setNoQuoteEscape, + setQuoteEscape, + time, + toggleVerbosity, +} from "./lib/index.mjs"; -const KIND_CONFIG = path.join(__dirname, '..', 'kind'); +const KIND_CONFIG = path.join(__dirname, "..", "kind"); -const APIM_REGISTRY = `${ process.env.APIM_IMAGE_REGISTRY || "graviteeio" }`; -const APIM_TAG = `${ process.env.APIM_IMAGE_TAG || "latest"}`; -const APIM_VALUES= `${ process.env.APIM_VALUES || "values.yaml"}`; +const APIM_REGISTRY = `${process.env.APIM_IMAGE_REGISTRY || "graviteeio"}`; +const APIM_TAG = `${process.env.APIM_IMAGE_TAG || "latest"}`; +const APIM_VALUES = `${process.env.APIM_VALUES || "values.yaml"}`; const IMAGES = new Map([ - [ - `${APIM_REGISTRY}/apim-gateway:${APIM_TAG}`, - `gravitee-apim-gateway:dev`, - ], - [ - `${APIM_REGISTRY}/apim-management-api:${APIM_TAG}`, - `gravitee-apim-management-api:dev`, - ], - [ - `${APIM_REGISTRY}/apim-management-ui:${APIM_TAG}`, - `gravitee-apim-management-ui:dev`, - ], - [ - `mongo:6.0.15-jammy`, - `mongo:6.0.15-jammy` - ], - [ - `mccutchen/go-httpbin:latest`, - `go-httpbin:dev` - ] + [`${APIM_REGISTRY}/apim-gateway:${APIM_TAG}`, `gravitee-apim-gateway:dev`], + [ + `${APIM_REGISTRY}/apim-management-api:${APIM_TAG}`, + `gravitee-apim-management-api:dev`, + ], + [ + `${APIM_REGISTRY}/apim-management-ui:${APIM_TAG}`, + `gravitee-apim-management-ui:dev`, + ], + [`mongo:6.0.15-jammy`, `mongo:6.0.15-jammy`], + [`mccutchen/go-httpbin:latest`, `go-httpbin:dev`], ]); -const REDIRECT = argv.verbose ? '' : '> /dev/null'; +const REDIRECT = argv.verbose ? "" : "> /dev/null"; toggleVerbosity(argv.verbose); - async function createKindCluster() { - setNoQuoteEscape(); - await $`kind create cluster --config ${KIND_CONFIG}/kind.yaml ${REDIRECT}` - setQuoteEscape(); + setNoQuoteEscape(); + await $`kind create cluster --config ${KIND_CONFIG}/kind.yaml ${REDIRECT}`; + setQuoteEscape(); } async function loadImages() { - setNoQuoteEscape(); - - await Promise.all( - Array.from(IMAGES.keys()).map( - (image) => $`docker pull ${image} ${REDIRECT}` - ) - ); - - await Promise.all( - Array.from(IMAGES.entries()).map( - ([image, tag]) => $`docker tag ${image} ${tag} ${REDIRECT}` - ) - ); - - await Promise.all( - Array.from(IMAGES.values()).map((tag) => $`kind load docker-image ${tag} --name gravitee ${REDIRECT}`) - ); - - setQuoteEscape(); + setNoQuoteEscape(); + + await Promise.all( + Array.from(IMAGES.keys()).map( + (image) => $`docker pull ${image} ${REDIRECT}` + ) + ); + + await Promise.all( + Array.from(IMAGES.entries()).map( + ([image, tag]) => $`docker tag ${image} ${tag} ${REDIRECT}` + ) + ); + + await Promise.all( + Array.from(IMAGES.values()).map( + (tag) => $`kind load docker-image ${tag} --name gravitee ${REDIRECT}` + ) + ); + + setQuoteEscape(); } async function helmInstallAPIM() { - await $`helm repo add graviteeio https://helm.gravitee.io`; - await $`helm repo update graviteeio`; - await $`helm install apim graviteeio/apim3 -f ${KIND_CONFIG}/apim/${APIM_VALUES}`; + await $`helm repo add graviteeio https://helm.gravitee.io`; + await $`helm repo update graviteeio`; + await $`helm install apim graviteeio/apim3 -f ${KIND_CONFIG}/apim/${APIM_VALUES}`; } async function deployHTTPBin() { - await $`kubectl apply -f ${KIND_CONFIG}/httpbin`; + await $`kubectl apply -f ${KIND_CONFIG}/httpbin`; } async function waitForApim() { - await $`kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=apim3 --timeout=360s`; + await $`kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=apim3 --timeout=360s`; } LOG.blue(` @@ -133,4 +131,3 @@ LOG.blue(`Waiting for services to be ready ... `); await time(waitForApim); - diff --git a/scripts/trigger-release.mjs b/scripts/trigger-release.mjs new file mode 100644 index 000000000..10ee364be --- /dev/null +++ b/scripts/trigger-release.mjs @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * Licensed 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. + */ + +import { + LOG, + HELM, + toggleVerbosity, + time, + isEmptyString, +} from "./lib/index.mjs"; + +const VERSION = argv.version; +const VERBOSE = argv.verbose; +const DRY_RUN = !!argv["dry-run"]; +const LATEST = !!argv["latest"]; +const TRIGGER = "release"; + +toggleVerbosity(VERBOSE); + +if (isEmptyString(VERSION)) { + LOG.red("You must specify a version using the --version flag"); + await $`exit 1`; +} + +LOG.blue(`Triggering release pipeline for version ${VERSION}`); + +const parameters = { + trigger: TRIGGER, + "release-version": VERSION, + "dry-run": DRY_RUN, + latest: LATEST, +}; + +console.log({ parameters });