action-gh-release/src/github.ts
koplo199 0bd7e8b279
Update all dependencies + dependabot.yml configuration + node16 (#275)
* Create dependabot.yml

* Bump actions/checkout from 2 to 3

Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update to node16

* Bump @types/node from 12.12.24 to 18.11.9

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 12.12.24 to 18.11.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump glob and @types/glob

Bumps [glob](https://github.com/isaacs/node-glob) and [@types/glob](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/glob). These dependencies needed to be updated together.

Updates `glob` from 7.1.6 to 8.0.3
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v7.1.6...v8.0.3)

Updates `@types/glob` from 7.1.1 to 8.0.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/glob)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: "@types/glob"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump @actions/github from 5.0.0 to 5.1.1

Bumps [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) from 5.0.0 to 5.1.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

---
updated-dependencies:
- dependency-name: "@actions/github"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ts-jest from 24.2.0 to 24.3.0

Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 24.2.0 to 24.3.0.
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v24.2.0...v24.3.0)

---
updated-dependencies:
- dependency-name: ts-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump prettier from 1.19.1 to 2.7.1

Bumps [prettier](https://github.com/prettier/prettier) from 1.19.1 to 2.7.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/1.19.1...2.7.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump @octokit/plugin-retry from 3.0.9 to 4.0.3

Bumps [@octokit/plugin-retry](https://github.com/octokit/plugin-retry.js) from 3.0.9 to 4.0.3.
- [Release notes](https://github.com/octokit/plugin-retry.js/releases)
- [Commits](https://github.com/octokit/plugin-retry.js/compare/v3.0.9...v4.0.3)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-retry"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Resolve conflicts

* Resolve conflicts

* Resolve conflicts

* Bump mime and @types/mime

Bumps [mime](https://github.com/broofa/mime) and [@types/mime](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mime). These dependencies needed to be updated together.

Updates `mime` from 2.4.4 to 3.0.0
- [Release notes](https://github.com/broofa/mime/releases)
- [Changelog](https://github.com/broofa/mime/blob/main/CHANGELOG.md)
- [Commits](https://github.com/broofa/mime/compare/v2.4.4...v3.0.0)

Updates `@types/mime` from 2.0.1 to 3.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/mime)

---
updated-dependencies:
- dependency-name: mime
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: "@types/mime"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump @octokit/plugin-throttling from 3.7.0 to 4.3.2

Bumps [@octokit/plugin-throttling](https://github.com/octokit/plugin-throttling.js) from 3.7.0 to 4.3.2.
- [Release notes](https://github.com/octokit/plugin-throttling.js/releases)
- [Commits](https://github.com/octokit/plugin-throttling.js/compare/v3.7.0...v4.3.2)

---
updated-dependencies:
- dependency-name: "@octokit/plugin-throttling"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump @zeit/ncc from 0.21.1 to 0.22.3

Bumps [@zeit/ncc](https://github.com/zeit/ncc) from 0.21.1 to 0.22.3.
- [Release notes](https://github.com/zeit/ncc/releases)
- [Commits](https://github.com/zeit/ncc/compare/0.21.1...0.22.3)

---
updated-dependencies:
- dependency-name: "@zeit/ncc"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update dependabot.yml

* Update dependabot.yml

* Regenerate package-lock.json and dist folder

* Update

* Bump typescript from 3.9.10 to 4.8.4

Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.9.10 to 4.8.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.9.10...v4.8.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Resolve conflicts

* Bump jest-circus from 24.9.0 to 29.2.2

Bumps [jest-circus](https://github.com/facebook/jest/tree/HEAD/packages/jest-circus) from 24.9.0 to 29.2.2.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.2/packages/jest-circus)

---
updated-dependencies:
- dependency-name: jest-circus
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Resolve conflicts

* Resolve conflicts

* Resolve conflicts

* Resolve conflicts

* Bump @types/jest from 24.9.1 to 29.2.2

Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 24.9.1 to 29.2.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update main.yml

* Bump jest-circus from 29.3.0 to 29.3.1

Bumps [jest-circus](https://github.com/facebook/jest/tree/HEAD/packages/jest-circus) from 29.3.0 to 29.3.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.3.1/packages/jest-circus)

---
updated-dependencies:
- dependency-name: jest-circus
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump jest from 29.3.0 to 29.3.1

Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.3.0 to 29.3.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.3.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 01:50:24 -05:00

320 lines
8.8 KiB
TypeScript

import fetch from "node-fetch";
import { GitHub } from "@actions/github/lib/utils";
import { Config, isTag, releaseBody } from "./util";
import { statSync, readFileSync } from "fs";
import { getType } from "mime";
import { basename } from "path";
type GitHub = InstanceType<typeof GitHub>;
export interface ReleaseAsset {
name: string;
mime: string;
size: number;
data: Buffer;
}
export interface Release {
id: number;
upload_url: string;
html_url: string;
tag_name: string;
name: string | null;
body?: string | null | undefined;
target_commitish: string;
draft: boolean;
prerelease: boolean;
assets: Array<{ id: number; name: string }>;
}
export interface Releaser {
getReleaseByTag(params: {
owner: string;
repo: string;
tag: string;
}): Promise<{ data: Release }>;
createRelease(params: {
owner: string;
repo: string;
tag_name: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
prerelease: boolean | undefined;
target_commitish: string | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }>;
updateRelease(params: {
owner: string;
repo: string;
release_id: number;
tag_name: string;
target_commitish: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
prerelease: boolean | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }>;
allReleases(params: {
owner: string;
repo: string;
}): AsyncIterableIterator<{ data: Release[] }>;
}
export class GitHubReleaser implements Releaser {
github: GitHub;
constructor(github: GitHub) {
this.github = github;
}
getReleaseByTag(params: {
owner: string;
repo: string;
tag: string;
}): Promise<{ data: Release }> {
return this.github.rest.repos.getReleaseByTag(params);
}
createRelease(params: {
owner: string;
repo: string;
tag_name: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
prerelease: boolean | undefined;
target_commitish: string | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }> {
return this.github.rest.repos.createRelease(params);
}
updateRelease(params: {
owner: string;
repo: string;
release_id: number;
tag_name: string;
target_commitish: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
prerelease: boolean | undefined;
discussion_category_name: string | undefined;
generate_release_notes: boolean | undefined;
}): Promise<{ data: Release }> {
return this.github.rest.repos.updateRelease(params);
}
allReleases(params: {
owner: string;
repo: string;
}): AsyncIterableIterator<{ data: Release[] }> {
const updatedParams = { per_page: 100, ...params };
return this.github.paginate.iterator(
this.github.rest.repos.listReleases.endpoint.merge(updatedParams)
);
}
}
export const asset = (path: string): ReleaseAsset => {
return {
name: basename(path),
mime: mimeOrDefault(path),
size: statSync(path).size,
data: readFileSync(path),
};
};
export const mimeOrDefault = (path: string): string => {
return getType(path) || "application/octet-stream";
};
export const upload = async (
config: Config,
github: GitHub,
url: string,
path: string,
currentAssets: Array<{ id: number; name: string }>
): Promise<any> => {
const [owner, repo] = config.github_repository.split("/");
const { name, size, mime, data: body } = asset(path);
const currentAsset = currentAssets.find(
({ name: currentName }) => currentName == name
);
if (currentAsset) {
console.log(`♻️ Deleting previously uploaded asset ${name}...`);
await github.rest.repos.deleteReleaseAsset({
asset_id: currentAsset.id || 1,
owner,
repo,
});
}
console.log(`⬆️ Uploading ${name}...`);
const endpoint = new URL(url);
endpoint.searchParams.append("name", name);
const resp = await fetch(endpoint, {
headers: {
"content-length": `${size}`,
"content-type": mime,
authorization: `token ${config.github_token}`,
},
method: "POST",
body,
});
const json = await resp.json();
if (resp.status !== 201) {
throw new Error(
`Failed to upload release asset ${name}. received status code ${
resp.status
}\n${json.message}\n${JSON.stringify(json.errors)}`
);
}
return json;
};
export const release = async (
config: Config,
releaser: Releaser,
maxRetries: number = 3
): Promise<Release> => {
if (maxRetries <= 0) {
console.log(`❌ Too many retries. Aborting...`);
throw new Error("Too many retries.");
}
const [owner, repo] = config.github_repository.split("/");
const tag =
config.input_tag_name ||
(isTag(config.github_ref)
? config.github_ref.replace("refs/tags/", "")
: "");
const discussion_category_name = config.input_discussion_category_name;
const generate_release_notes = config.input_generate_release_notes;
try {
// you can't get a an existing draft by tag
// so we must find one in the list of all releases
if (config.input_draft) {
for await (const response of releaser.allReleases({
owner,
repo,
})) {
let release = response.data.find((release) => release.tag_name === tag);
if (release) {
return release;
}
}
}
let existingRelease = await releaser.getReleaseByTag({
owner,
repo,
tag,
});
const release_id = existingRelease.data.id;
let target_commitish: string;
if (
config.input_target_commitish &&
config.input_target_commitish !== existingRelease.data.target_commitish
) {
console.log(
`Updating commit from "${existingRelease.data.target_commitish}" to "${config.input_target_commitish}"`
);
target_commitish = config.input_target_commitish;
} else {
target_commitish = existingRelease.data.target_commitish;
}
const tag_name = tag;
const name = config.input_name || existingRelease.data.name || tag;
// revisit: support a new body-concat-strategy input for accumulating
// body parts as a release gets updated. some users will likely want this while
// others won't previously this was duplicating content for most which
// no one wants
const workflowBody = releaseBody(config) || "";
const existingReleaseBody = existingRelease.data.body || "";
let body: string;
if (config.input_append_body && workflowBody && existingReleaseBody) {
body = existingReleaseBody + "\n" + workflowBody;
} else {
body = workflowBody || existingReleaseBody;
}
const draft =
config.input_draft !== undefined
? config.input_draft
: existingRelease.data.draft;
const prerelease =
config.input_prerelease !== undefined
? config.input_prerelease
: existingRelease.data.prerelease;
const release = await releaser.updateRelease({
owner,
repo,
release_id,
tag_name,
target_commitish,
name,
body,
draft,
prerelease,
discussion_category_name,
generate_release_notes,
});
return release.data;
} catch (error) {
if (error.status === 404) {
const tag_name = tag;
const name = config.input_name || tag;
const body = releaseBody(config);
const draft = config.input_draft;
const prerelease = config.input_prerelease;
const target_commitish = config.input_target_commitish;
let commitMessage: string = "";
if (target_commitish) {
commitMessage = ` using commit "${target_commitish}"`;
}
console.log(
`👩‍🏭 Creating new GitHub release for tag ${tag_name}${commitMessage}...`
);
try {
let release = await releaser.createRelease({
owner,
repo,
tag_name,
name,
body,
draft,
prerelease,
target_commitish,
discussion_category_name,
generate_release_notes,
});
return release.data;
} catch (error) {
// presume a race with competing metrix runs
console.log(
`⚠️ GitHub release failed with status: ${
error.status
}\n${JSON.stringify(error.response.data.errors)}\nretrying... (${
maxRetries - 1
} retries remaining)`
);
return release(config, releaser, maxRetries - 1);
}
} else {
console.log(
`⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`
);
throw error;
}
}
};