From d017a68d2f23953c928b709ac90a9702b9639dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20Vay=C3=A1?= Date: Mon, 28 Oct 2019 12:05:05 +0100 Subject: [PATCH] [MM-19051] [MM-14180] [MM-19330] Release helpers, push to github and aws, fix weird name on msi at UAC (#1063) * [MM-19051] release helpers * [MM-14180] release to github [MM-18330] more release helpers * [MM-19330] add proper name during uac * [MM-19051] address CR comments * add this branch fo testing * missing commits, remove trap to prevent ugly output * Run shellcheck against Bash scripts to fix issues * Try to fix build - attempt 1 * Add patch option to release script * add setup exe installer to generate_release script --- .circleci/config.yml | 68 +++++++++- scripts/Makefile.ps1 | 8 +- scripts/cp_artifacts.sh | 38 +++--- scripts/generate_release_markdown.sh | 18 ++- scripts/release.sh | 194 +++++++++++++++++++++++++++ 5 files changed, 293 insertions(+), 33 deletions(-) create mode 100755 scripts/release.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index c4dd06d4..5bef847a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,8 @@ version: 2.1 orbs: win: circleci/windows@1.0.0 + aws-s3: circleci/aws-s3@1.0.11 + executors: wine-chrome: working_directory: ~/mattermost-desktop @@ -16,6 +18,14 @@ executors: working_directory: ~/mattermost-desktop macos: xcode: "10.3.0" + aws: + working_directory: ~/mattermost-desktop + docker: + - image: 'circleci/python:2.7' + github: + working_directory: ~/mattermost-desktop + docker: + - image: circleci/golang:1.12 commands: update_image: description: "Update base image" @@ -178,10 +188,10 @@ jobs: - win_make: operation: "build" - run: mkdir -p ./dist/win-release - - run: cp -r release/*.exe ./dist/win-release + #- run: cp -r release/*.exe ./dist/win-release - run: cp -r release/*.zip ./dist/win-release - run: cp -r release/*.msi ./dist/win-release - - run: cp -r release/*.blockmap ./dist/win-release + #- run: cp -r release/*.blockmap ./dist/win-release - persist_to_workspace: root: ./dist/ @@ -213,6 +223,39 @@ jobs: path: ./dist destination: packages + upload_to_s3: + executor: aws + steps: + - checkout + - attach_workspace: + at: ./dist + - aws-s3/copy: + from: ./dist/ + to: s3://releases.mattermost.com/desktop/$(jq -r .version package.json)/ + arguments: --acl public-read --cache-control "no-cache" --recursive + upload_to_github: + executor: github + steps: + - checkout + - attach_workspace: + at: ./dist + - run: + name: "Setup files for ghr" + command: | + mkdir -p ./ghr-dist + cp ./dist/{macos-release,win-release,linux}/* ./ghr-dist + - run: + name: "Publish Release on GitHub" + command: | + go get github.com/tcnksm/ghr + VERSION=$(jq -r .version package.json) + RELEASE_TITLE="${VERSION} ($(date -u "+%Y-%m-%d"))" + ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -draft \ + --body="$(./scripts/generate_release_markdown.sh $VERSION)" \ + --name="${RELEASE_TITLE}" $( [[ $VERSION =~ "-rc" ]] && printf %s "-prerelease") \ + -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} \ + -delete ${VERSION} ./ghr-dist + workflows: version: 2 build_and_test: @@ -246,7 +289,7 @@ workflows: # release-XX.YY.ZZ # release-XX.YY.ZZ-rc-something - /^release-\d+\.\d+\.\d+?(-rc.*)?/ - + - release-helpers # remove me - mac_installer: requires: - check @@ -255,6 +298,7 @@ workflows: branches: only: - /^release-\d+\.\d+\.\d+?(-rc.*)?/ + - release-helpers # remove-me - store_artifacts: # for master/PR builds requires: @@ -265,13 +309,27 @@ workflows: branches: ignore: - /^release-\d+\.\d+\.\d+?(-rc.*)?/ - - store_artifacts: - # for release and rc builds + - upload_to_s3: + # for release builds requires: - msi_installer - mac_installer - build-linux + context: mattermost-ci-s3 + filters: + tags: + only: + - /^v\d+\.\d+\.\d+?$/ + - release-helpers # remove me + + - upload_to_github: + requires: + - msi_installer + - mac_installer + - build-linux + context: matterbuild-github-token filters: branches: only: - /^release-\d+\.\d+\.\d+?(-rc.*)?/ + - release-helpers # remove me diff --git a/scripts/Makefile.ps1 b/scripts/Makefile.ps1 index 7a192ec9..067eaee8 100644 --- a/scripts/Makefile.ps1 +++ b/scripts/Makefile.ps1 @@ -405,22 +405,22 @@ function Run-BuildMsi { # Dual signing is not supported on msi files. Is it recommended to sign with 256 hash. # src.: https://security.stackexchange.com/a/124685/84134 # src.: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-us/d4b70ecd-a883-4289-8047-cc9cde28b492#0b3e3b80-6b3b-463f-ac1e-1bf0dc831952 - signtool.exe sign /f "resources\windows\certificate\mattermost-desktop-windows.pfx" /p "$env:COM_MATTERMOST_MAKEFILE_CERTIFICATE_PRIVATE_KEY_ENCRYPTED" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" + signtool.exe sign /f "resources\windows\certificate\mattermost-desktop-windows.pfx" /p "$env:COM_MATTERMOST_MAKEFILE_CERTIFICATE_PRIVATE_KEY_ENCRYPTED" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" /d "mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" Print-Info "Signing mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi (waiting for 15 seconds)..." Start-Sleep -s 15 - signtool.exe sign /f "resources\windows\certificate\mattermost-desktop-windows.pfx" /p "$env:COM_MATTERMOST_MAKEFILE_CERTIFICATE_PRIVATE_KEY_ENCRYPTED" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" + signtool.exe sign /f "resources\windows\certificate\mattermost-desktop-windows.pfx" /p "$env:COM_MATTERMOST_MAKEFILE_CERTIFICATE_PRIVATE_KEY_ENCRYPTED" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-\$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" /d "mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" } elseif (Test-Path 'env:PFX') { Print-Info "Signing mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi (waiting for 15 seconds)..." Start-Sleep -s 15 # Dual signing is not supported on msi files. Is it recommended to sign with 256 hash. # src.: https://security.stackexchange.com/a/124685/84134 # src.: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-us/d4b70ecd-a883-4289-8047-cc9cde28b492#0b3e3b80-6b3b-463f-ac1e-1bf0dc831952 - signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" + signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" /d "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x86.msi" Print-Info "Signing mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi (waiting for 15 seconds)..." Start-Sleep -s 15 - signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" + signtool.exe sign /f "./mattermost-desktop-windows.pfx" /p "$env:PFX_KEY" /tr "http://timestamp.digicert.com" /fd sha256 /td sha256 "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" /d "release\mattermost-desktop-$($env:COM_MATTERMOST_MAKEFILE_BUILD_ID)-x64.msi" } else { Print-Info "Not signing msi" } diff --git a/scripts/cp_artifacts.sh b/scripts/cp_artifacts.sh index 59ef993f..1ded8583 100644 --- a/scripts/cp_artifacts.sh +++ b/scripts/cp_artifacts.sh @@ -1,47 +1,49 @@ #!/usr/bin/env bash set -eu -VERSION=$(cat package.json | jq -r '.version') +VERSION="$(jq -r '.version' "${temp_file}" && mv "${temp_file}" ./package.json + temp_file="$(mktemp -t package-lock.json)" + jq ".version = \"${1}\"" ./package-lock.json > "${temp_file}" && mv "${temp_file}" ./package-lock.json + temp_file="$(mktemp -t src-package.json)" + jq ".version = \"${1}\"" ./src/package.json > "${temp_file}" && mv "${temp_file}" ./src/package.json + temp_file="$(mktemp -t src-package-lock.json)" + jq ".version = \"${1}\"" ./src/package-lock.json > "${temp_file}" && mv "${temp_file}" ./src/package-lock.json + + git add ./package.json ./package-lock.json ./src/package.json ./src/package-lock.json + git commit -qm "Bump to version ${1}" +} + + +# keep track of the last executed command +# src.: https://stackoverflow.com/a/6110446/3514658 +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +# echo an error message before exiting +trap 'echo "\"${last_command}\" command filed with exit code $?."' EXIT + +# mattermost repo might not be the origin one, we don't want to enforce that. +org="github.com:mattermost" +git_origin="$(git remote -v | grep ${org} | grep push | awk '{print $1}')" +if [[ -z "${git_origin}" ]]; then + print_warning "Can't find a mattermost remote, defaulting to origin" + git_origin="origin" +fi + +# get original git branch +branch_name="$(git symbolic-ref -q HEAD)" +branch_name="${branch_name##refs/heads/}" +branch_name="${branch_name:-HEAD}" + +# don't run if branch is dirty, releases shouldn't be done on a dirty branch +dirty="$(git diff --quiet && echo 0 || echo 1)" +if (( dirty == 1 )); then + print_error "Please use this script on a clean branch" + exit 10 +fi + +# require jq +if ! type jq >/dev/null 2>&1; then + print_error "This script requires jq to run" + exit 11 +fi + +# get version +pkg_version="$(jq -r .version package.json)" +# remove trailing +current_version="${pkg_version%-develop}" +current_version="${pkg_version%-rc*}" +# parse version +IFS='.' read -r major minor micro <<<"${current_version}" +case "${1}" in + "help") + echo "todo" + ;; + "rc") + if [[ "${branch_name}" =~ "release-" ]]; then + if [[ "${pkg_version}" =~ "-rc" ]]; then + rc="${pkg_version#*-rc}" + else + print_warning "No release candidate on the version, assuming 0" + rc=0 + fi + case "${rc}" in + ''|*[!0-9]*) + print_warning "Can't guess release candidate from version, assuming 0" + rc=1 + ;; + *) + rc=$(( rc + 1 )) + ;; + esac + print_info "Generating ${current_version} release candidate ${rc}" + new_pkg_version="${current_version}-rc${rc}" + write_package_version "${new_pkg_version}" + tag "${new_pkg_version}" "Release candidate ${rc}" + print_info "Locally created an rc. In order to build you'll have to:" + print_info "$ git push --follow-tags ${git_origin} ${branch_name}:${branch_name}" + else + print_error "Can't generate a release candidate on a non release-X.Y branch" + exit 2 + + fi + ;; + "final") + if [[ "${branch_name}" =~ "release-" ]]; then + print_info "Releasing v${current_version}" + new_pkg_version="${current_version}" + write_package_version "${new_pkg_version}" + tag "${new_pkg_version}" "Released on $(date -u)" + print_info "Locally created an final version. In order to build you'll have to:" + print_info "$ git push --follow-tags ${git_origin} ${branch_name}:${branch_name}" + else + print_error "Can't release on a non release-X.Y branch" + exit 2 + fi + ;; + "patch") + if [[ "${branch_name}" =~ "release-" ]]; then + new_pkg_version="${major}.${minor}.$(( micro + 1 ))" + print_info "Releasing v${new_pkg_version}" + write_package_version "${new_pkg_version}" + tag "${new_pkg_version}" "Released on $(date -u)" + print_info "Locally created an patch version. In order to build you'll have to:" + print_info "$ git push --follow-tags ${git_origin} ${branch_name}:${branch_name}" + else + print_error "Can't patch on a non release-X.Y branch" + exit 2 + fi + ;; + "branch") + # Quality releases should run from a release branch + if [[ "${branch_name}" =~ "release-" ]]; then + new_branch_version="${major}.$(( minor + 1 ))" + new_branch_name="release-${new_branch_version}" + print_info "Doing a quality branch: ${new_branch_name}" + + if git show-ref --verify --quiet "refs/heads/${new_branch_name}"; then + print_error "Branch ${new_branch_name} exists" + exit 3 + fi + + new_pkg_version="${new_branch_version}.0-rc0" + git checkout -b "${new_branch_name}" + write_package_version "${new_pkg_version}" + tag "${new_pkg_version}" "Quality branch" + print_info "Locally created quality branch. In order to build you'll have to:" + print_info "$ git push --follow-tags ${git_origin} ${new_branch_name}:${new_branch_name}" + + else + if [[ "${branch_name}" != "master" ]]; then + print_warning "You are branching on ${branch_name} instead of master or a release-branch" + read -p "Do you wish to continue? [y/n]" -n 1 -r + if [[ ! "${REPLY}" =~ ^[Yy]$ ]]; then + exit 1 + fi + fi + new_branch_version="${major}.${minor}" + new_branch_name="release-${new_branch_version}" + new_pkg_version="${new_branch_version}.0-rc0" + master_pkg_version="${major}.$(( minor + 2 )).0-develop" + print_info "Creating a new features branch: ${new_branch_name}" + + if git show-ref --verify --quiet "refs/heads/${new_branch_name}"; then + print_error "Branch ${new_branch_name} exists" + exit 3 + fi + + git branch "${new_branch_name}" + print_info "Writing new package version for development: ${master_pkg_version}" + write_package_version "${master_pkg_version}" + git checkout "${new_branch_name}" + write_package_version "${new_pkg_version}" + tag "${new_pkg_version}" "New features branch" + print_info "Locally created new features branch. In order to build you'll have to:" + print_info "$ git push --follow-tags ${git_origin} ${new_branch_name}:${new_branch_name}" + print_info "For writing master changes you'll need to:" + print_info "$ git push ${git_origin} ${branch_name}:${branch_name}" + fi + ;; + *) + print_error "Only branch|rc|final parameters are accepted" + exit 1 + ;; +esac + +trap - EXIT +