From 86ec5b391732679770c8706f9d336e1f0d34bf02 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 4 Mar 2020 17:18:37 +0100 Subject: [PATCH] Nightly binary releases This doesn't publish nightly plugin to the marketplace yet --- .github/actions/github-release/Dockerfile | 8 ++ .github/actions/github-release/README.md | 21 ++++ .github/actions/github-release/action.yml | 15 +++ .github/actions/github-release/main.js | 117 ++++++++++++++++++++ .github/actions/github-release/package.json | 10 ++ .github/workflows/release.yaml | 59 ++-------- 6 files changed, 183 insertions(+), 47 deletions(-) create mode 100644 .github/actions/github-release/Dockerfile create mode 100644 .github/actions/github-release/README.md create mode 100644 .github/actions/github-release/action.yml create mode 100644 .github/actions/github-release/main.js create mode 100644 .github/actions/github-release/package.json diff --git a/.github/actions/github-release/Dockerfile b/.github/actions/github-release/Dockerfile new file mode 100644 index 00000000000..5849eac7d24 --- /dev/null +++ b/.github/actions/github-release/Dockerfile @@ -0,0 +1,8 @@ +FROM node:slim + +COPY . /action +WORKDIR /action + +RUN npm install --production + +ENTRYPOINT ["node", "/action/main.js"] diff --git a/.github/actions/github-release/README.md b/.github/actions/github-release/README.md new file mode 100644 index 00000000000..7b50d002001 --- /dev/null +++ b/.github/actions/github-release/README.md @@ -0,0 +1,21 @@ +# github-release + +Copy-pasted from +https://github.com/bytecodealliance/wasmtime/tree/8acfdbdd8aa550d1b84e0ce1e6222a6605d14e38/.github/actions/github-release + +An action used to publish GitHub releases for `wasmtime`. + +As of the time of this writing there's a few actions floating around which +perform github releases but they all tend to have their set of drawbacks. +Additionally nothing handles deleting releases which we need for our rolling +`dev` release. + +To handle all this this action rolls-its-own implementation using the +actions/toolkit repository and packages published there. These run in a Docker +container and take various inputs to orchestrate the release from the build. + +More comments can be found in `main.js`. + +Testing this is really hard. If you want to try though run `npm install` and +then `node main.js`. You'll have to configure a bunch of env vars though to get +anything reasonably working. diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml new file mode 100644 index 00000000000..51a074adfaa --- /dev/null +++ b/.github/actions/github-release/action.yml @@ -0,0 +1,15 @@ +name: 'wasmtime github releases' +description: 'wasmtime github releases' +inputs: + token: + description: '' + required: true + name: + description: '' + required: true + files: + description: '' + required: true +runs: + using: 'docker' + image: 'Dockerfile' diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js new file mode 100644 index 00000000000..295c0262616 --- /dev/null +++ b/.github/actions/github-release/main.js @@ -0,0 +1,117 @@ +const core = require('@actions/core'); +const path = require("path"); +const fs = require("fs"); +const github = require('@actions/github'); +const glob = require('glob'); + +function sleep(milliseconds) { + return new Promise(resolve => setTimeout(resolve, milliseconds)) +} + +async function runOnce() { + // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` + const files = core.getInput('files'); + const name = core.getInput('name'); + const token = core.getInput('token'); + const slug = process.env.GITHUB_REPOSITORY; + const owner = slug.split('/')[0]; + const repo = slug.split('/')[1]; + const sha = process.env.GITHUB_SHA; + + core.info(`files: ${files}`); + core.info(`name: ${name}`); + core.info(`token: ${token}`); + + const octokit = new github.GitHub(token); + + // Delete the previous release since we can't overwrite one. This may happen + // due to retrying an upload or it may happen because we're doing the dev + // release. + const releases = await octokit.paginate("GET /repos/:owner/:repo/releases", { owner, repo }); + for (const release of releases) { + if (release.tag_name !== name) { + continue; + } + const release_id = release.id; + core.info(`deleting release ${release_id}`); + await octokit.repos.deleteRelease({ owner, repo, release_id }); + } + + // We also need to update the `dev` tag while we're at it on the `dev` branch. + if (name == 'nightly') { + try { + core.info(`updating nightly tag`); + await octokit.git.updateRef({ + owner, + repo, + ref: 'tags/nightly', + sha, + force: true, + }); + } catch (e) { + console.log("ERROR: ", JSON.stringify(e, null, 2)); + core.info(`creating nightly tag`); + await octokit.git.createTag({ + owner, + repo, + tag: 'nightly', + message: 'nightly release', + object: sha, + type: 'commit', + }); + } + } + + // Creates an official GitHub release for this `tag`, and if this is `dev` + // then we know that from the previous block this should be a fresh release. + core.info(`creating a release`); + const release = await octokit.repos.createRelease({ + owner, + repo, + tag_name: name, + prerelease: name === 'nightly', + }); + + // Upload all the relevant assets for this release as just general blobs. + for (const file of glob.sync(files)) { + const size = fs.statSync(file).size; + core.info(`upload ${file}`); + await octokit.repos.uploadReleaseAsset({ + data: fs.createReadStream(file), + headers: { 'content-length': size, 'content-type': 'application/octet-stream' }, + name: path.basename(file), + url: release.data.upload_url, + }); + } +} + +async function run() { + const retries = 10; + for (let i = 0; i < retries; i++) { + try { + await runOnce(); + break; + } catch (e) { + if (i === retries - 1) + throw e; + logError(e); + console.log("RETRYING after 10s"); + await sleep(10000) + } + } +} + +function logError(e) { + console.log("ERROR: ", e.message); + try { + console.log(JSON.stringify(e, null, 2)); + } catch (e) { + // ignore json errors for now + } + console.log(e.stack); +} + +run().catch(err => { + logError(err); + core.setFailed(err.message); +}); diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json new file mode 100644 index 00000000000..abfc55f6ff2 --- /dev/null +++ b/.github/actions/github-release/package.json @@ -0,0 +1,10 @@ +{ + "name": "wasmtime-github-release", + "version": "0.0.0", + "main": "main.js", + "dependencies": { + "@actions/core": "^1.0.0", + "@actions/github": "^1.0.0", + "glob": "^7.1.5" + } +} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index fe893e00510..30f1ff22f3a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,5 +1,8 @@ name: release on: + schedule: + - cron: '0 0 * * *' # midnight UTC + push: branches: - release @@ -113,6 +116,9 @@ jobs: node-version: 12.x - run: echo "::set-env name=TAG::$(date --iso)" + if: github.event_name == 'push' + - run: echo "::set-env name=TAG::nightly" + if: github.event_name != 'push' - run: 'echo "TAG: $TAG"' - name: Checkout repository @@ -136,59 +142,18 @@ jobs: path: dist - run: ls -all ./dist - - name: Create Release - id: create_release - # uses: actions/create-release@v1 - # https://github.com/actions/create-release/pull/32 - uses: fleskesvor/create-release@1a72e235c178bf2ae6c51a8ae36febc24568c5fe - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Publish Release + uses: ./.github/actions/github-release with: - tag_name: ${{ env.TAG }} - release_name: ${{ env.TAG }} - draft: false - prerelease: false - - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/rust-analyzer-linux - asset_name: rust-analyzer-linux - asset_content_type: application/octet-stream - - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/rust-analyzer-mac - asset_name: rust-analyzer-mac - asset_content_type: application/octet-stream - - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/rust-analyzer-windows.exe - asset_name: rust-analyzer-windows.exe - asset_content_type: application/octet-stream - - - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./dist/rust-analyzer.vsix - asset_name: rust-analyzer.vsix - asset_content_type: application/octet-stream + files: "dist/*" + name: ${{ env.TAG }} + token: ${{ secrets.GITHUB_TOKEN }} - run: npm ci working-directory: ./editors/code - name: Publish Extension + if: github.event_name == 'push' working-directory: ./editors/code # token from https://dev.azure.com/rust-analyzer/ run: npx vsce publish 0.1.$(date +%Y%m%d) --pat ${{ secrets.MARKETPLACE_TOKEN }}