144 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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);
 | 
						|
});
 |