Skip to content

Commit

Permalink
try rust-analyzer's release workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Frefreak committed Dec 28, 2023
1 parent 4e5ede6 commit 6ca2efb
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 20 deletions.
8 changes: 8 additions & 0 deletions .github/actions/github-release/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM node:slim

COPY . /action
WORKDIR /action

RUN npm install --production

ENTRYPOINT ["node", "/action/main.js"]
21 changes: 21 additions & 0 deletions .github/actions/github-release/README.md
Original file line number Diff line number Diff line change
@@ -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.
15 changes: 15 additions & 0 deletions .github/actions/github-release/action.yml
Original file line number Diff line number Diff line change
@@ -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'
144 changes: 144 additions & 0 deletions .github/actions/github-release/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
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.HEAD_SHA;

core.info(`files: ${files}`);
core.info(`name: ${name}`);

const options = {
request: {
timeout: 30000,
}
};
const octokit = github.getOctokit(token, options);

// 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.rest.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.rest.git.updateRef({
owner,
repo,
ref: 'tags/nightly',
sha,
force: true,
});
} catch (e) {
core.error(e);
core.info(`creating nightly tag`);
await octokit.rest.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.rest.repos.createRelease({
owner,
repo,
name,
tag_name: name,
target_commitish: sha,
prerelease: name === 'nightly',
});
const release_id = release.data.id;

// 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;
const name = path.basename(file);

await runWithRetry(async function () {
// We can't overwrite assets, so remove existing ones from a previous try.
let assets = await octokit.rest.repos.listReleaseAssets({
owner,
repo,
release_id
});
for (const asset of assets.data) {
if (asset.name === name) {
core.info(`delete asset ${name}`);
const asset_id = asset.id;
await octokit.rest.repos.deleteReleaseAsset({ owner, repo, asset_id });
}
}

core.info(`upload ${file}`);
const headers = { 'content-length': size, 'content-type': 'application/octet-stream' };
const data = fs.createReadStream(file);
await octokit.rest.repos.uploadReleaseAsset({
data,
headers,
name,
url: release.data.upload_url,
});
});
}
}

async function runWithRetry(f) {
const retries = 10;
const maxDelay = 4000;
let delay = 1000;

for (let i = 0; i < retries; i++) {
try {
await f();
break;
} catch (e) {
if (i === retries - 1)
throw e;

core.error(e);
const currentDelay = Math.round(Math.random() * delay);
core.info(`sleeping ${currentDelay} ms`);
await sleep(currentDelay);
delay = Math.min(delay * 2, maxDelay);
}
}
}

async function run() {
await runWithRetry(runOnce);
}

run().catch(err => {
core.error(err);
core.setFailed(err.message);
});
10 changes: 10 additions & 0 deletions .github/actions/github-release/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "wasmtime-github-release",
"version": "0.0.0",
"main": "main.js",
"dependencies": {
"@actions/core": "^1.6",
"@actions/github": "^5.0",
"glob": "^7.1.5"
}
}
53 changes: 33 additions & 20 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,37 @@ jobs:
rustup target add ${{ matrix.targets }}
cargo build --release --target=${{ matrix.targets }}
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Archive production artifacts
uses: actions/upload-artifact@v2
with:
tag_name: ${{ github.sha }}
release_name: $(date +%Y-%m-%d)-${{ github.sha }}
draft: false
prerelease: false

- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./target/${{ matrix.targets }}/release/otk
asset_name: otk-${{ matrix.targets }}
asset_content_type: application/octet-stream
name: otk-${{ matrix.targets }}
path: ./target/${{ matrix.targets }}/release/otk

release:
name: publish
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Install Nodejs
uses: actions/setup-node@v3
with:
node-version: 16

- uses: actions/download-artifact@v1
with:
name: otk-x86_64-unknown-linux-musl
path: dist

- uses: actions/download-artifact@v1
with:
name: otk-x86_64-unknown-linux-gnu
path: dist

- run: ls -al ./dist

- name: Publish Release
uses: ./.github/actions/github-release
with:
files: "dist/*"
name: $(date +%Y-%m-%d)-${{ github.sha }}
token: ${{ secrets.GITHUB_TOKEN }}

0 comments on commit 6ca2efb

Please sign in to comment.