about summary refs log tree commit diff
path: root/src/tools/rust-analyzer/.github/actions/github-release
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/.github/actions/github-release')
-rw-r--r--src/tools/rust-analyzer/.github/actions/github-release/Dockerfile8
-rw-r--r--src/tools/rust-analyzer/.github/actions/github-release/README.md21
-rw-r--r--src/tools/rust-analyzer/.github/actions/github-release/action.yml15
-rw-r--r--src/tools/rust-analyzer/.github/actions/github-release/main.js144
-rw-r--r--src/tools/rust-analyzer/.github/actions/github-release/package.json10
5 files changed, 198 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile b/src/tools/rust-analyzer/.github/actions/github-release/Dockerfile
new file mode 100644
index 00000000000..5849eac7d24
--- /dev/null
+++ b/src/tools/rust-analyzer/.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/src/tools/rust-analyzer/.github/actions/github-release/README.md b/src/tools/rust-analyzer/.github/actions/github-release/README.md
new file mode 100644
index 00000000000..c8ff3ec6e52
--- /dev/null
+++ b/src/tools/rust-analyzer/.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/src/tools/rust-analyzer/.github/actions/github-release/action.yml b/src/tools/rust-analyzer/.github/actions/github-release/action.yml
new file mode 100644
index 00000000000..51a074adfaa
--- /dev/null
+++ b/src/tools/rust-analyzer/.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/src/tools/rust-analyzer/.github/actions/github-release/main.js b/src/tools/rust-analyzer/.github/actions/github-release/main.js
new file mode 100644
index 00000000000..e8dba398733
--- /dev/null
+++ b/src/tools/rust-analyzer/.github/actions/github-release/main.js
@@ -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);
+});
diff --git a/src/tools/rust-analyzer/.github/actions/github-release/package.json b/src/tools/rust-analyzer/.github/actions/github-release/package.json
new file mode 100644
index 00000000000..af4bf074d2d
--- /dev/null
+++ b/src/tools/rust-analyzer/.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.6",
+    "@actions/github": "^5.0",
+    "glob": "^7.1.5"
+  }
+}