From 144c533f1430d9c998916696d22f08f38b52dbb4 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse Date: Thu, 10 Mar 2022 10:23:56 -0500 Subject: [PATCH] feat(release): Linux Manager (#1056) * start release process for linux * re-org * add get_version * fix for file name conventions * break out func, revert file * fix get_version.mjs * equals * update readme --- .../workflows/build_release_candidates.yml | 16 ++++ .../manager_linux_build_release_candidate.yml | 37 +++++++++ .../manager_linux_publish_release.yml | 79 +++++++++++++++++++ src/server_manager/README.md | 21 +++-- src/server_manager/scripts/get_version.mjs | 36 +++++++++ 5 files changed, 177 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/build_release_candidates.yml create mode 100644 .github/workflows/manager_linux_build_release_candidate.yml create mode 100644 .github/workflows/manager_linux_publish_release.yml create mode 100644 src/server_manager/scripts/get_version.mjs diff --git a/.github/workflows/build_release_candidates.yml b/.github/workflows/build_release_candidates.yml new file mode 100644 index 00000000..81bac31e --- /dev/null +++ b/.github/workflows/build_release_candidates.yml @@ -0,0 +1,16 @@ +name: Build Release Candidates + +concurrency: + group: ${{ github.head_ref || github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - master + +jobs: + linux: + uses: ./.github/workflows/manager_linux_build_release_candidate.yml + secrets: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} diff --git a/.github/workflows/manager_linux_build_release_candidate.yml b/.github/workflows/manager_linux_build_release_candidate.yml new file mode 100644 index 00000000..9a0f4af3 --- /dev/null +++ b/.github/workflows/manager_linux_build_release_candidate.yml @@ -0,0 +1,37 @@ +name: Build Linux Release Candidate + +on: + workflow_call: + secrets: + SENTRY_DSN: + required: true + +jobs: + manager-linux-release-build: + name: Manager Linux Release Build + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} + BUILD_ENV: production + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + + - name: Install Node + uses: actions/setup-node@v2.2.0 + with: + node-version: 16 + + - name: Install NPM Dependencies + run: npm ci + + - name: Build Linux Release Candidate + run: npm run action server_manager/electron_app/build linux -- --buildMode=release + + - name: Upload Linux Release Candidate + uses: actions/upload-artifact@v2 + with: + name: manager_linux_release_${{ github.sha }} + path: build/server_manager/electron_app/static/dist + if-no-files-found: error diff --git a/.github/workflows/manager_linux_publish_release.yml b/.github/workflows/manager_linux_publish_release.yml new file mode 100644 index 00000000..aaf094e2 --- /dev/null +++ b/.github/workflows/manager_linux_publish_release.yml @@ -0,0 +1,79 @@ +name: Publish Manager Linux Release Candidate + +on: + workflow_dispatch: + inputs: + commit_sha: + description: "SHA of commit to publish (example: 2ac8bd4a915a7c8a3e3a63081d72da33baa9ea7e)" + required: true + +jobs: + publish-release: + name: Publish Client Linux Release Candidate + runs-on: ubuntu-latest + timeout-minutes: 15 + environment: Releases Repository + env: + RELEASES_REPOSITORY: ${{ secrets.RELEASES_REPOSITORY }} + RELEASES_DEPLOY_KEY: ${{ secrets.RELEASES_DEPLOY_KEY }} + RELEASE_COMMIT_SHA: ${{ github.event.inputs.commit_sha }} + # STORE_LOGIN: ${{ secrets.SNAP_STORE_LOGIN }} + steps: + - name: Checkout + uses: actions/checkout@v2.3.4 + + - name: Install Node + uses: actions/setup-node@v2.2.0 + with: + node-version: 16 + + - name: Install NPM Dependencies + run: npm ci + + - name: Download Release Candidate + uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e + with: + workflow: build_release_candidates.yml + commit: ${{ env.RELEASE_COMMIT_SHA }} + name: manager_linux_release_${{ env.RELEASE_COMMIT_SHA }} + path: manager_linux_release + + - name: Checkout Releases Repository + uses: actions/checkout@v2.3.4 + with: + repository: ${{ env.RELEASES_REPOSITORY }} + ssh-key: ${{ env.RELEASES_DEPLOY_KEY }} + path: outline-releases + + - name: Push Tags and Release Commits + run: | + git config --global user.name "OutlineBot" + git config --global user.email "outlinebot@users.noreply.github.com" + + RELEASE_VERSION="$(node scripts/get_version.mjs linux)" + RELEASE_TAG="linux-${RELEASE_VERSION}" + + [ "$(git tag -l "$RELEASE_TAG")" != "" ] && exit 1 + + cp manager_linux_release/Outline-Manager.AppImage outline-releases/manager/stable/Outline-Manager.AppImage + cp manager_linux_release/latest-linux.yml outline-releases/manager/stable/latest-linux.yml + + cd outline-releases + git checkout master + git add manager/stable/Outline-Manager.AppImage manager/stable/latest-linux.yml + git commit -m "Release linux manager v${RELEASE_VERSION}" + git push origin master + git tag "$RELEASE_TAG" + git push origin "$RELEASE_TAG" + + cd .. + git tag "$RELEASE_TAG" + git push origin "$RELEASE_TAG" + # TODO(daniellacosse): S3 bucket? + # TODO(daniellacosse): snap store + # - name: Publish to Snap store + # uses: snapcore/action-publish@v1 + # with: + # store_login: ${{ secrets.STORE_LOGIN }} + # snap: build/dist/Outline-Manager.AppImage + # release: edge diff --git a/src/server_manager/README.md b/src/server_manager/README.md index a3d940bf..38eebfb5 100644 --- a/src/server_manager/README.md +++ b/src/server_manager/README.md @@ -39,10 +39,10 @@ This will enable the Developer menu on the application window. To build the app binary: ``` -npm run action server_manager/electron_app/package_${PLATFORM} +npm run action server_manager/electron_app/build ${PLATFORM} -- --buildMode=[debug,release] ``` -Where `${PLATFORM}` is one of `linux`, `macos`, `only_windows`. +Where `${PLATFORM}` is one of `linux`, `mac`, `windows`. The per-platform standalone apps will be at `build/electron_app/static/dist`. @@ -50,15 +50,6 @@ The per-platform standalone apps will be at `build/electron_app/static/dist`. - Linux: tar.gz files. - macOS: dmg files if built from macOS, zip files otherwise. -## Releases - -To perform a release, use -``` -npm run action server_manager/electron_app/release -``` - -This will perform a clean and reinstall all dependencies to make sure the build is not tainted. - ## Error reporting To enable error reporting through [Sentry](https://sentry.io/) for local builds, run: @@ -67,4 +58,10 @@ export SENTRY_DSN=[Sentry development API key] npm run action server_manager/electron_app/start ``` -Release builds on CI are configured with a production Sentry API key. +## CI Environment Variables + +For your CI to run smoothly, you'll need the following in your ENV: + +- `SENTRY_DSN` - [url required](https://docs.sentry.io/product/sentry-basics/dsn-explainer/) to enable sentry integration. Same across all platforms. +- `RELEASES_REPOSITORY` - the username and repository name of the repository you're pushing releases to. In our case, `Jigsaw-Code/outline-releases` +- `RELEASES_DEPLOY_KEY` - an ssh secret key for the matching releases repository public deploy key - [how to set this up](https://docs.github.com/en/developers/overview/managing-deploy-keys#setup-2) diff --git a/src/server_manager/scripts/get_version.mjs b/src/server_manager/scripts/get_version.mjs new file mode 100644 index 00000000..4f471181 --- /dev/null +++ b/src/server_manager/scripts/get_version.mjs @@ -0,0 +1,36 @@ +// Copyright 2022 The Outline Authors +// +// 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 url from "url"; +import path from "path"; +import {readFile} from "fs/promises"; + +const __filename = url.fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export async function get_version() { + const {version} = JSON.parse(await readFile(path.resolve(__dirname, "../package.json"))); + + return version; +} + +async function main() { + console.log(await get_version()); +} + +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + (async function() { + return main(); + })(); +}