From bb312495d6df7cf0f2f71b8519b11ff38f2064c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Jan 2022 09:37:43 -0600 Subject: [PATCH] v2 new release (#47) * Add support for Linux-arm64 Co-authored-by: Christophe Sauthier Co-authored-by: Oliver King Co-authored-by: OliverMKing --- .github/workflows/release-pr.yml | 56 +++++++++++++++++++ .github/workflows/tag-and-release.yml | 77 +++++++++++++++++++++++++++ __tests__/utilities.test.ts | 54 +++++++++++++++---- lib/utilities.js | 12 +++-- src/utilities.ts | 21 +++++--- 5 files changed, 201 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/release-pr.yml create mode 100644 .github/workflows/tag-and-release.yml diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml new file mode 100644 index 00000000..a536d72b --- /dev/null +++ b/.github/workflows/release-pr.yml @@ -0,0 +1,56 @@ +name: "Create release PR" + +on: + workflow_dispatch: + inputs: + release: + description: "Define release version (ex: v1, v2, v3)" + required: true + +jobs: + createPullRequest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Check if remote branch exists + env: + BRANCH: releases/${{ github.event.inputs.release }} + run: | + echo "##[set-output name=exists;]$(echo $(if [[ -z $(git ls-remote --heads origin ${BRANCH}) ]]; then echo false; else echo true; fi;))" + id: extract-branch-status + # these two only need to occur if the branch exists + - name: Checkout proper branch + if: ${{ steps.extract-branch-status.outputs.exists == 'true' }} + env: + BRANCH: releases/${{ github.event.inputs.release }} + run: git checkout ${BRANCH} + - name: Reset promotion branch + if: ${{ steps.extract-branch-status.outputs.exists == 'true' }} + run: | + git fetch origin master:master + git reset --hard master + - name: Install packages + run: | + rm -rf node_modules/ + npm install --no-bin-links + npm run build + - name: Remove node_modules from gitignore + run: | + sed -i '/node_modules/d' ./.gitignore + - name: Create branch + uses: peterjgrainger/action-create-branch@v2.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + branch: releases/${{ github.event.inputs.release }} + - name: Create pull request + uses: peter-evans/create-pull-request@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Add node modules and new code for release + title: ${{ github.event.inputs.release }} new release + base: releases/${{ github.event.inputs.release }} + branch: create-release + delete-branch: true diff --git a/.github/workflows/tag-and-release.yml b/.github/workflows/tag-and-release.yml new file mode 100644 index 00000000..89bc15a2 --- /dev/null +++ b/.github/workflows/tag-and-release.yml @@ -0,0 +1,77 @@ +name: "Tag and create release draft" + +on: + push: + branches: + - releases/* + +jobs: + gh_tagged_release: + runs-on: "ubuntu-latest" + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Test release + run: | + sudo npm install n + sudo n latest + npm test + - name: Get branch ending + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/} | sed 's:.*/::')" + id: extract-branch + - name: Get tags + run: | + echo "##[set-output name=tags;]$(echo $(git tag))" + id: extract-tags + - name: Get latest tag + uses: actions/github-script@v5 + env: + TAGS: ${{ steps.extract-tags.outputs.tags }} + BRANCH: ${{ steps.extract-branch.outputs.branch }} + with: + script: | + const tags = process.env["TAGS"] + .split(" ") + .map((x) => x.trim()); + const branch = process.env["BRANCH"]; + const splitTag = (x) => + x + .substring(branch.length + 1) + .split(".") + .map((x) => Number(x)); + function compareTags(nums1, nums2, position = 0) { + if (nums1.length < position && nums2.length < position) return nums2; + const num1 = splitTag(nums1)[position] || 0; + const num2 = splitTag(nums2)[position] || 0; + if (num1 === num2) return compareTags(nums1, nums2, position + 1); + else if (num1 > num2) return nums1; + else return nums2; + } + const branchTags = tags.filter((tag) => tag.startsWith(branch)); + if (branchTags.length < 1) return branch + ".-1" + return branchTags.reduce((prev, curr) => compareTags(prev, curr)); + result-encoding: string + id: get-latest-tag + - name: Get new tag + uses: actions/github-script@v5 + env: + PREV: ${{ steps.get-latest-tag.outputs.result }} + with: + script: | + let version = process.env["PREV"] + if (!version.includes(".")) version += ".0"; // case of v1 or v2 + const prefix = /^([a-zA-Z]+)/.exec(version)[0]; + const numbers = version.substring(prefix.length); + let split = numbers.split("."); + split[split.length - 1] = parseInt(split[split.length - 1]) + 1; + return prefix + split.join("."); + result-encoding: string + id: get-new-tag + - uses: "marvinpinto/action-automatic-releases@v1.2.1" + with: + title: ${{ steps.get-new-tag.outputs.result }} release + automatic_release_tag: ${{ steps.get-new-tag.outputs.result }} + repo_token: "${{ secrets.GITHUB_TOKEN }}" + draft: true diff --git a/__tests__/utilities.test.ts b/__tests__/utilities.test.ts index 47692221..a998b73c 100644 --- a/__tests__/utilities.test.ts +++ b/__tests__/utilities.test.ts @@ -64,12 +64,24 @@ describe('Test all functions in utilities file', () => { expect(await utils.execCommand('ls', [], {} as ExecOptions)).toMatchObject({'stderr': '', 'stdout': 'list of files'}); }); - test('getDownloadUrl() - return the URL to download helm for Linux', () => { + test('getDownloadUrl() - return the URL to download helm for Linux_x64', () => { jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('x64'); const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip' expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl); - expect(os.type).toBeCalled(); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); + }); + + test('getDownloadUrl() - return the URL to download helm for Linux_arm64', () => { + jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('arm64'); + const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-arm64.zip' + + expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); }); test('getDownloadUrl() - return the URL to download helm for Darwin', () => { @@ -88,12 +100,24 @@ describe('Test all functions in utilities file', () => { expect(os.type).toBeCalled(); }); - test('getDownloadUrl() - return the URL to download kompose for Linux', () => { + test('getDownloadUrl() - return the URL to download kompose for Linux_x64', () => { jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('x64'); const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64' - + expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl); - expect(os.type).toBeCalled(); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); + }); + + test('getDownloadUrl() - return the URL to download kompose for Linux_arm64', () => { + jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('arm64'); + const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-arm64' + + expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); }); test('getDownloadUrl() - return the URL to download kompose for Darwin', () => { @@ -112,12 +136,24 @@ describe('Test all functions in utilities file', () => { expect(os.type).toBeCalled(); }); - test('getDownloadUrl() - return the URL to download kubectl for Linux', () => { + test('getDownloadUrl() - return the URL to download kubectl for Linux_x64', () => { jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('x64'); const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/amd64/kubectl' - + expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl); - expect(os.type).toBeCalled(); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); + }); + + test('getDownloadUrl() - return the URL to download kubectl for Linux_arm64', () => { + jest.spyOn(os, 'type').mockReturnValue('Linux'); + jest.spyOn(os, 'arch').mockReturnValue('arm64'); + const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/arm64/kubectl' + + expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl); + expect(os.type).toBeCalled(); + expect(os.arch).toBeCalled(); }); test('getDownloadUrl() - return the URL to download kubectl for Darwin', () => { @@ -209,4 +245,4 @@ describe('Test all functions in utilities file', () => { expect(toolCache.downloadTool).toBeCalled(); expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8'); }); -}); \ No newline at end of file +}); diff --git a/lib/utilities.js b/lib/utilities.js index 27cc6d79..8083dad1 100644 --- a/lib/utilities.js +++ b/lib/utilities.js @@ -90,10 +90,11 @@ function setCachedToolPath(toolName, version) { exports.setCachedToolPath = setCachedToolPath; function getDownloadUrl(toolName, version) { const system = os.type(); - if (!downloadLinks[system] || !downloadLinks[system][toolName]) { + const systemAndArch = system == "Linux" ? `${system}_${os.arch()}` : system; + if (!downloadLinks[systemAndArch] || !downloadLinks[systemAndArch][toolName]) { throw Error("Unknown OS or render engine type"); } - return util.format(downloadLinks[system][toolName], version); + return util.format(downloadLinks[systemAndArch][toolName], version); } exports.getDownloadUrl = getDownloadUrl; function getStableVerison(toolName) { @@ -125,11 +126,16 @@ const stableVersionUrls = { 'helm': 'https://api.github.com/repos/helm/helm/releases/latest', }; const downloadLinks = { - 'Linux': { + 'Linux_x64': { 'helm': 'https://get.helm.sh/helm-%s-linux-amd64.zip', 'kompose': 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64', 'kubectl': 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl' }, + 'Linux_arm64': { + 'helm': 'https://get.helm.sh/helm-%s-linux-arm64.zip', + 'kompose': 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64', + 'kubectl': 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl' + }, 'Darwin': { 'helm': 'https://get.helm.sh/helm-%s-darwin-amd64.zip', 'kompose': 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64', diff --git a/src/utilities.ts b/src/utilities.ts index 0e803037..06446919 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -36,7 +36,7 @@ export async function execCommand(toolPath: string, args: string[], options: Exe stdout : "", stderr : "" } as ExecResult; - + options.listeners = { stdout: (data: Buffer) => { execResult.stdout += data.toString(); @@ -86,11 +86,13 @@ export async function setCachedToolPath(toolName:string, version : string) { export function getDownloadUrl(toolName : string, version: string): string { const system = os.type() - if (!downloadLinks[system] || !downloadLinks[system][toolName]) { + const systemAndArch = system == "Linux" ? `${system}_${os.arch()}` : system; + + if (!downloadLinks[systemAndArch] || !downloadLinks[systemAndArch][toolName]) { throw Error("Unknown OS or render engine type"); } - return util.format(downloadLinks[system][toolName], version) + return util.format(downloadLinks[systemAndArch][toolName], version) } export async function getStableVerison(toolName : string){ @@ -122,19 +124,24 @@ const stableVersionUrls = { } const downloadLinks = { - 'Linux': { + 'Linux_x64': { 'helm' : 'https://get.helm.sh/helm-%s-linux-amd64.zip', - 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64', + 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64', 'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl' }, + 'Linux_arm64': { + 'helm' : 'https://get.helm.sh/helm-%s-linux-arm64.zip', + 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64', + 'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl' + }, 'Darwin' : { 'helm' : 'https://get.helm.sh/helm-%s-darwin-amd64.zip', - 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64', + 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64', 'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/darwin/amd64/kubectl' }, 'Windows_NT' : { 'helm' : 'https://get.helm.sh/helm-%s-windows-amd64.zip', - 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe', + 'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe', 'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/windows/amd64/kubectl.exe' } }