diff options
| author | Josh McKinney <joshka@users.noreply.github.com> | 2024-03-28 20:39:21 -0700 |
|---|---|---|
| committer | Josh McKinney <joshka@users.noreply.github.com> | 2024-03-28 20:42:44 -0700 |
| commit | 29d28f801cf7cac6a2b80dadfd60f3f6823bc3cf (patch) | |
| tree | 3c05166c97442ea82947c2dcaea6b0bd03992a41 /src/tools/rust-analyzer/.github/actions/github-release/main.js | |
| parent | ab10eea62ec59bc676a946ae8be562edcaccb950 (diff) | |
Make `cargo run` always available for binaries
Previously, items for `cargo test` and `cargo check` would appear as in the `Select Runnable` quick pick that appears when running `rust-analyzer: Run`, but `run` would only appear as a runnable if a `main`` function was selected in the editor. This change adds `cargo run` as an always available runnable command for binary packages. This makes it easier to develop cli / tui applications, as now users can run application from anywhere in their codebase.
Diffstat (limited to 'src/tools/rust-analyzer/.github/actions/github-release/main.js')
| -rw-r--r-- | src/tools/rust-analyzer/.github/actions/github-release/main.js | 144 |
1 files changed, 144 insertions, 0 deletions
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); +}); |
