Merge remote-tracking branch 'origin/master' into feat/add-generateReleaseNotes

This commit is contained in:
Paulo Cesar 2024-03-18 19:46:20 -03:00
commit 1b9115ad1a
No known key found for this signature in database
GPG key ID: 04A5F4ED0689315F
15 changed files with 1791 additions and 4986 deletions

View file

@ -8,7 +8,7 @@ jobs:
steps:
# https://github.com/actions/checkout
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install
run: npm ci
- name: Build

2
.nvmrc
View file

@ -1 +1 @@
16.13.1
20.11.1

View file

@ -1,3 +1,27 @@
## 2.0.4
- Minor follow up to [#417](https://github.com/softprops/action-gh-release/pull/417). [#425](https://github.com/softprops/action-gh-release/pull/425)
## 2.0.3
- Declare `make_latest` as an input field in `action.yml` [#419](https://github.com/softprops/action-gh-release/pull/419)
## 2.0.2
- Revisit approach to [#384](https://github.com/softprops/action-gh-release/pull/384) making unresolved pattern failures opt-in [#417](https://github.com/softprops/action-gh-release/pull/417)
## 2.0.1
- Add support for make_latest property [#304](https://github.com/softprops/action-gh-release/pull/304) via [@samueljseay](https://github.com/samueljseay)
- Fail run if files setting contains invalid patterns [#384](https://github.com/softprops/action-gh-release/pull/384) via [@rpdelaney](https://github.com/rpdelaney)
- Add support for proxy env variables (don't use node-fetch) [#386](https://github.com/softprops/action-gh-release/pull/386/) via [@timor-raiman](https://github.com/timor-raiman)
- Suppress confusing warning when input_files is empty [#389](https://github.com/softprops/action-gh-release/pull/389) via [@Drowze](https://github.com/Drowze)
## 2.0.0
- `2.0.0`!? this release corrects a disjunction between git tag versions used in the marketplace and versions list this file. Previous versions should have really been 1.\*. Going forward this should be better aligned.
- Upgrade action.yml declaration to node20 to address deprecations
## 0.1.15
- Upgrade to action.yml declaration to node16 to address deprecations

View file

@ -1,4 +1,4 @@
Copyright (c) 2019 Doug Tangren
Copyright (c) 2019-current Doug Tangren
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View file

@ -41,9 +41,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
```
@ -62,9 +62,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
```
### ⬆️ Uploading release assets
@ -88,13 +88,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Build
run: echo ${{ github.sha }} > Release.txt
- name: Test
run: cat Release.txt
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: Release.txt
@ -112,13 +112,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Build
run: echo ${{ github.sha }} > Release.txt
- name: Test
run: cat Release.txt
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
@ -126,7 +126,7 @@ jobs:
LICENSE
```
> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That let's you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That lets you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
> **⚠️ Note for Windows:** Paths must use `/` as a separator, not `\`, as `\` is used to escape characters with special meaning in the pattern; for example, instead of specifying `D:\Foo.txt`, you must specify `D:/Foo.txt`. If you're using PowerShell, you can do this with `$Path = $Path -replace '\\','/'`
@ -146,11 +146,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Generate Changelog
run: echo "# Good things have arrived" > ${{ github.workspace }}-CHANGELOG.txt
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
body_path: ${{ github.workspace }}-CHANGELOG.txt
@ -183,6 +183,7 @@ The following are optional as `step.with` keys
| `discussion_category_name` | String | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository) |
| `generate_release_notes` | Boolean | Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information |
| `append_body` | Boolean | Append to existing body instead of overwriting it |
| `make_latest` | String | Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api defaults if not provided |
💡 When providing a `body` and `body_path` at the same time, `body_path` will be
attempted first, then falling back on `body` if the path can not be read from.
@ -195,11 +196,11 @@ release will retain its original info.
The following outputs can be accessed via `${{ steps.<step-id>.outputs }}` from this action
| Name | Type | Description |
| ------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url` | String | Github.com URL for the release |
| `id` | String | Release ID |
| `upload_url` | String | URL for uploading assets to the release |
| Name | Type | Description |
| ------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url` | String | Github.com URL for the release |
| `id` | String | Release ID |
| `upload_url` | String | URL for uploading assets to the release |
| `assets` | String | JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/releases/assets#get-a-release-asset) (minus the `uploader` field) |
As an example, you can use `${{ fromJSON(steps.<step-id>.outputs.assets)[0].browser_download_url }}` to get the download URL of the first asset.
@ -234,4 +235,7 @@ permissions:
[GitHub token permissions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) can be set for an individual job, workflow, or for Actions as a whole.
Note that if you intend to run workflows on the release event (`on: { release: { types: [published] } }`), you need to use
a personal access token for this action, as the [default `secrets.GITHUB_TOKEN` does not trigger another workflow](https://github.com/actions/create-release/issues/71).
Doug Tangren (softprops) 2019

View file

@ -52,6 +52,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
})
);
@ -73,6 +74,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
})
);
@ -94,6 +96,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
})
);
@ -128,6 +131,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -154,6 +158,7 @@ describe("util", () => {
input_target_commitish: "affa18ef97bc9db20076945705aba8c516139abd",
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -179,6 +184,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: "releases",
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -205,6 +211,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: true,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -234,6 +241,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -261,6 +269,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);
@ -287,6 +296,32 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
}
);
});
it("parses basic config where make_latest is passed", () => {
assert.deepStrictEqual(
parseConfig({
INPUT_MAKE_LATEST: "false",
}),
{
github_ref: "",
github_repository: "",
github_token: "",
input_append_body: false,
input_body: undefined,
input_body_path: undefined,
input_draft: undefined,
input_prerelease: undefined,
input_files: [],
input_name: undefined,
input_tag_name: undefined,
input_fail_on_unmatched_files: false,
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: "false",
input_previous_tag: undefined,
}
);
@ -312,6 +347,7 @@ describe("util", () => {
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
input_previous_tag: undefined,
}
);

View file

@ -50,8 +50,9 @@ inputs:
append_body:
description: "Append to existing body instead of overwriting it. Default is false."
required: false
env:
"GITHUB_TOKEN": "As provided by Github Actions"
make_latest:
description: "Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api default if not provided"
required: false
outputs:
url:
description: "URL to the Release HTML Page"
@ -62,7 +63,7 @@ outputs:
assets:
description: "JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/reference/repos#upload-a-release-asset--code-samples) (minus the `uploader` field)"
runs:
using: "node16"
using: "node20"
main: "dist/index.js"
branding:
color: "green"

452
dist/37.index.js vendored
View file

@ -1,452 +0,0 @@
"use strict";
exports.id = 37;
exports.ids = [37];
exports.modules = {
/***/ 4037:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "toFormData": () => (/* binding */ toFormData)
/* harmony export */ });
/* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2777);
/* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8010);
let s = 0;
const S = {
START_BOUNDARY: s++,
HEADER_FIELD_START: s++,
HEADER_FIELD: s++,
HEADER_VALUE_START: s++,
HEADER_VALUE: s++,
HEADER_VALUE_ALMOST_DONE: s++,
HEADERS_ALMOST_DONE: s++,
PART_DATA_START: s++,
PART_DATA: s++,
END: s++
};
let f = 1;
const F = {
PART_BOUNDARY: f,
LAST_BOUNDARY: f *= 2
};
const LF = 10;
const CR = 13;
const SPACE = 32;
const HYPHEN = 45;
const COLON = 58;
const A = 97;
const Z = 122;
const lower = c => c | 0x20;
const noop = () => {};
class MultipartParser {
/**
* @param {string} boundary
*/
constructor(boundary) {
this.index = 0;
this.flags = 0;
this.onHeaderEnd = noop;
this.onHeaderField = noop;
this.onHeadersEnd = noop;
this.onHeaderValue = noop;
this.onPartBegin = noop;
this.onPartData = noop;
this.onPartEnd = noop;
this.boundaryChars = {};
boundary = '\r\n--' + boundary;
const ui8a = new Uint8Array(boundary.length);
for (let i = 0; i < boundary.length; i++) {
ui8a[i] = boundary.charCodeAt(i);
this.boundaryChars[ui8a[i]] = true;
}
this.boundary = ui8a;
this.lookbehind = new Uint8Array(this.boundary.length + 8);
this.state = S.START_BOUNDARY;
}
/**
* @param {Uint8Array} data
*/
write(data) {
let i = 0;
const length_ = data.length;
let previousIndex = this.index;
let {lookbehind, boundary, boundaryChars, index, state, flags} = this;
const boundaryLength = this.boundary.length;
const boundaryEnd = boundaryLength - 1;
const bufferLength = data.length;
let c;
let cl;
const mark = name => {
this[name + 'Mark'] = i;
};
const clear = name => {
delete this[name + 'Mark'];
};
const callback = (callbackSymbol, start, end, ui8a) => {
if (start === undefined || start !== end) {
this[callbackSymbol](ui8a && ui8a.subarray(start, end));
}
};
const dataCallback = (name, clear) => {
const markSymbol = name + 'Mark';
if (!(markSymbol in this)) {
return;
}
if (clear) {
callback(name, this[markSymbol], i, data);
delete this[markSymbol];
} else {
callback(name, this[markSymbol], data.length, data);
this[markSymbol] = 0;
}
};
for (i = 0; i < length_; i++) {
c = data[i];
switch (state) {
case S.START_BOUNDARY:
if (index === boundary.length - 2) {
if (c === HYPHEN) {
flags |= F.LAST_BOUNDARY;
} else if (c !== CR) {
return;
}
index++;
break;
} else if (index - 1 === boundary.length - 2) {
if (flags & F.LAST_BOUNDARY && c === HYPHEN) {
state = S.END;
flags = 0;
} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {
index = 0;
callback('onPartBegin');
state = S.HEADER_FIELD_START;
} else {
return;
}
break;
}
if (c !== boundary[index + 2]) {
index = -2;
}
if (c === boundary[index + 2]) {
index++;
}
break;
case S.HEADER_FIELD_START:
state = S.HEADER_FIELD;
mark('onHeaderField');
index = 0;
// falls through
case S.HEADER_FIELD:
if (c === CR) {
clear('onHeaderField');
state = S.HEADERS_ALMOST_DONE;
break;
}
index++;
if (c === HYPHEN) {
break;
}
if (c === COLON) {
if (index === 1) {
// empty header field
return;
}
dataCallback('onHeaderField', true);
state = S.HEADER_VALUE_START;
break;
}
cl = lower(c);
if (cl < A || cl > Z) {
return;
}
break;
case S.HEADER_VALUE_START:
if (c === SPACE) {
break;
}
mark('onHeaderValue');
state = S.HEADER_VALUE;
// falls through
case S.HEADER_VALUE:
if (c === CR) {
dataCallback('onHeaderValue', true);
callback('onHeaderEnd');
state = S.HEADER_VALUE_ALMOST_DONE;
}
break;
case S.HEADER_VALUE_ALMOST_DONE:
if (c !== LF) {
return;
}
state = S.HEADER_FIELD_START;
break;
case S.HEADERS_ALMOST_DONE:
if (c !== LF) {
return;
}
callback('onHeadersEnd');
state = S.PART_DATA_START;
break;
case S.PART_DATA_START:
state = S.PART_DATA;
mark('onPartData');
// falls through
case S.PART_DATA:
previousIndex = index;
if (index === 0) {
// boyer-moore derrived algorithm to safely skip non-boundary data
i += boundaryEnd;
while (i < bufferLength && !(data[i] in boundaryChars)) {
i += boundaryLength;
}
i -= boundaryEnd;
c = data[i];
}
if (index < boundary.length) {
if (boundary[index] === c) {
if (index === 0) {
dataCallback('onPartData', true);
}
index++;
} else {
index = 0;
}
} else if (index === boundary.length) {
index++;
if (c === CR) {
// CR = part boundary
flags |= F.PART_BOUNDARY;
} else if (c === HYPHEN) {
// HYPHEN = end boundary
flags |= F.LAST_BOUNDARY;
} else {
index = 0;
}
} else if (index - 1 === boundary.length) {
if (flags & F.PART_BOUNDARY) {
index = 0;
if (c === LF) {
// unset the PART_BOUNDARY flag
flags &= ~F.PART_BOUNDARY;
callback('onPartEnd');
callback('onPartBegin');
state = S.HEADER_FIELD_START;
break;
}
} else if (flags & F.LAST_BOUNDARY) {
if (c === HYPHEN) {
callback('onPartEnd');
state = S.END;
flags = 0;
} else {
index = 0;
}
} else {
index = 0;
}
}
if (index > 0) {
// when matching a possible boundary, keep a lookbehind reference
// in case it turns out to be a false lead
lookbehind[index - 1] = c;
} else if (previousIndex > 0) {
// if our boundary turned out to be rubbish, the captured lookbehind
// belongs to partData
const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);
callback('onPartData', 0, previousIndex, _lookbehind);
previousIndex = 0;
mark('onPartData');
// reconsider the current character even so it interrupted the sequence
// it could be the beginning of a new sequence
i--;
}
break;
case S.END:
break;
default:
throw new Error(`Unexpected state entered: ${state}`);
}
}
dataCallback('onHeaderField');
dataCallback('onHeaderValue');
dataCallback('onPartData');
// Update properties for the next call
this.index = index;
this.state = state;
this.flags = flags;
}
end() {
if ((this.state === S.HEADER_FIELD_START && this.index === 0) ||
(this.state === S.PART_DATA && this.index === this.boundary.length)) {
this.onPartEnd();
} else if (this.state !== S.END) {
throw new Error('MultipartParser.end(): stream ended unexpectedly');
}
}
}
function _fileName(headerValue) {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);
if (!m) {
return;
}
const match = m[2] || m[3] || '';
let filename = match.slice(match.lastIndexOf('\\') + 1);
filename = filename.replace(/%22/g, '"');
filename = filename.replace(/&#(\d{4});/g, (m, code) => {
return String.fromCharCode(code);
});
return filename;
}
async function toFormData(Body, ct) {
if (!/multipart/i.test(ct)) {
throw new TypeError('Failed to fetch');
}
const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
if (!m) {
throw new TypeError('no or bad content-type header, no multipart boundary');
}
const parser = new MultipartParser(m[1] || m[2]);
let headerField;
let headerValue;
let entryValue;
let entryName;
let contentType;
let filename;
const entryChunks = [];
const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct();
const onPartData = ui8a => {
entryValue += decoder.decode(ui8a, {stream: true});
};
const appendToFile = ui8a => {
entryChunks.push(ui8a);
};
const appendFileToFormData = () => {
const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType});
formData.append(entryName, file);
};
const appendEntryToFormData = () => {
formData.append(entryName, entryValue);
};
const decoder = new TextDecoder('utf-8');
decoder.decode();
parser.onPartBegin = function () {
parser.onPartData = onPartData;
parser.onPartEnd = appendEntryToFormData;
headerField = '';
headerValue = '';
entryValue = '';
entryName = '';
contentType = '';
filename = null;
entryChunks.length = 0;
};
parser.onHeaderField = function (ui8a) {
headerField += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderValue = function (ui8a) {
headerValue += decoder.decode(ui8a, {stream: true});
};
parser.onHeaderEnd = function () {
headerValue += decoder.decode();
headerField = headerField.toLowerCase();
if (headerField === 'content-disposition') {
// matches either a quoted-string or a token (RFC 2616 section 19.5.1)
const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);
if (m) {
entryName = m[2] || m[3] || '';
}
filename = _fileName(headerValue);
if (filename) {
parser.onPartData = appendToFile;
parser.onPartEnd = appendFileToFormData;
}
} else if (headerField === 'content-type') {
contentType = headerValue;
}
headerValue = '';
headerField = '';
};
for await (const chunk of Body) {
parser.write(chunk);
}
parser.end();
return formData;
}
/***/ })
};
;

10
dist/index.js vendored

File diff suppressed because one or more lines are too long

6001
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "action-gh-release",
"version": "0.1.15",
"version": "2.0.4",
"private": true,
"description": "GitHub Action for creating GitHub Releases",
"main": "lib/main.js",
@ -8,7 +8,8 @@
"build": "ncc build src/main.ts --minify",
"test": "jest",
"fmt": "prettier --write \"src/**/*.ts\" \"__tests__/**/*.ts\"",
"fmtcheck": "prettier --check \"src/**/*.ts\" \"__tests__/**/*.ts\""
"fmtcheck": "prettier --check \"src/**/*.ts\" \"__tests__/**/*.ts\"",
"updatetag": "git tag -d v2 && git push origin :v2 && git tag -a v2 -m '' && git push origin v2"
},
"repository": {
"type": "git",
@ -19,26 +20,24 @@
],
"author": "softprops",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
"@octokit/plugin-retry": "^4.0.3",
"@octokit/plugin-throttling": "^4.3.2",
"glob": "^8.0.3",
"mime": "^3.0.0",
"node-fetch": "^2.6.7"
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@octokit/plugin-retry": "^7.0.3",
"@octokit/plugin-throttling": "^9.0.3",
"glob": "^10.3.10",
"mime": "^4.0.1"
},
"devDependencies": {
"@types/glob": "^8.0.0",
"@types/jest": "^29.2.3",
"@types/mime": "^3.0.1",
"@types/node": "^18.11.9",
"@types/node-fetch": "^2.5.12",
"@vercel/ncc": "^0.34.0",
"jest": "^29.3.1",
"jest-circus": "^29.3.1",
"prettier": "2.8.0",
"ts-jest": "^29.0.3",
"typescript": "^4.9.3",
"@types/glob": "^8.1.0",
"@types/jest": "^29.5.12",
"@types/mime": "^3.0.4",
"@types/node": "^20.11.28",
"@vercel/ncc": "^0.38.1",
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"prettier": "3.2.5",
"ts-jest": "^29.1.2",
"typescript": "^5.4.2",
"typescript-formatter": "^7.2.2"
}
}

View file

@ -1,17 +0,0 @@
#!/bin/bash
# actions requires a node_modules dir https://github.com/actions/toolkit/blob/master/docs/javascript-action.md#publish-a-releasesv1-action
# but its recommended not to check these in https://github.com/actions/toolkit/blob/master/docs/action-versioning.md#recommendations
# as such the following hack is how we dill with it
if [[ $# -ne 1 ]]; then
echo "please pass a release version. i.e. $0 v1"
exit 1
fi
git checkout -b releases/$1 # If this branch already exists, omit the -b flag
rm -rf node_modules
sed -i '/node_modules/d' .gitignore # Bash command that removes node_modules from .gitignore
npm install --production
git add node_modules -f .gitignore
git commit -m node_modules
git push origin releases/$1

View file

@ -1,8 +1,7 @@
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 mime from "mime";
import { basename } from "path";
type GitHub = InstanceType<typeof GitHub>;
@ -14,6 +13,10 @@ export interface ReleaseAsset {
data: Buffer;
}
export type GenerateReleaseNotesParams = Partial<Parameters<GitHub["rest"]["repos"]["generateReleaseNotes"]['defaults']>[0]>;
export type CreateReleaseParams = Partial<Parameters<GitHub["rest"]["repos"]["createRelease"]>[0]>;
export type UpdateReleaseParams = Partial<Parameters<GitHub["rest"]["repos"]["updateRelease"]>[0]>;
export interface Release {
id: number;
upload_url: string;
@ -34,30 +37,9 @@ export interface Releaser {
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;
}): Promise<{ data: Release }>;
createRelease(params: CreateReleaseParams): 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;
}): Promise<{ data: Release }>;
updateRelease(params: UpdateReleaseParams): Promise<{ data: Release }>;
allReleases(params: {
owner: string;
@ -70,7 +52,7 @@ export interface Releaser {
}): Promise<undefined | string>;
generateReleaseBody(
params: Parameters<GitHub["rest"]["repos"]["generateReleaseNotes"]>[0]
params: GenerateReleaseNotesParams
): Promise<string>;
}
@ -85,42 +67,21 @@ export class GitHubReleaser implements Releaser {
repo: string;
tag: string;
}): Promise<{ data: Release }> {
return this.github.rest.repos.getReleaseByTag(params);
return this.github.rest.repos.getReleaseByTag(params as any);
}
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;
}): Promise<{ data: Release }> {
createRelease(params: CreateReleaseParams): Promise<{ data: Release }> {
return this.github.rest.repos.createRelease({
...params,
generate_release_notes: false,
});
generate_release_notes: false
} as any);
}
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;
}): Promise<{ data: Release }> {
updateRelease(params: UpdateReleaseParams): Promise<{ data: Release }> {
return this.github.rest.repos.updateRelease({
...params,
generate_release_notes: false,
});
} as any);
}
allReleases(params: {
@ -129,7 +90,7 @@ export class GitHubReleaser implements Releaser {
}): AsyncIterableIterator<{ data: Release[] }> {
const updatedParams = { per_page: 100, ...params };
return this.github.paginate.iterator(
this.github.rest.repos.listReleases.endpoint.merge(updatedParams)
this.github.rest.repos.listReleases.endpoint.merge(updatedParams as any)
);
}
@ -138,7 +99,7 @@ export class GitHubReleaser implements Releaser {
repo: string;
}): Promise<undefined | string> {
try {
const release = await this.github.rest.repos.getLatestRelease(params);
const release = await this.github.rest.repos.getLatestRelease(params as any);
if (!release?.data) {
return;
@ -152,11 +113,11 @@ export class GitHubReleaser implements Releaser {
}
}
async generateReleaseBody(
params: Parameters<GitHub["rest"]["repos"]["generateReleaseNotes"]>[0]
): Promise<string> {
async generateReleaseBody(params: GenerateReleaseNotesParams): Promise<string> {
try {
const { data } = await this.github.rest.repos.generateReleaseNotes(params);
const { data } = await this.github.rest.repos.generateReleaseNotes(
params as any
);
if (!data.body) {
throw new Error("No release body generated");
@ -179,7 +140,7 @@ export const asset = (path: string): ReleaseAsset => {
};
export const mimeOrDefault = (path: string): string => {
return getType(path) || "application/octet-stream";
return mime.getType(path) || "application/octet-stream";
};
export const upload = async (
@ -205,16 +166,17 @@ export const upload = async (
console.log(`⬆️ Uploading ${name}...`);
const endpoint = new URL(url);
endpoint.searchParams.append("name", name);
const resp = await fetch(endpoint, {
const resp = await github.request({
method: "POST",
url: endpoint.toString(),
headers: {
"content-length": `${size}`,
"content-type": mime,
authorization: `token ${config.github_token}`,
},
method: "POST",
body,
data: body,
});
const json = await resp.json();
const json = resp.data;
if (resp.status !== 201) {
throw new Error(
`Failed to upload release asset ${name}. received status code ${
@ -247,11 +209,11 @@ export const release = async (
const generate_release_notes = config.input_generate_release_notes;
const latestTag: string | undefined = !previous_tag
? await releaser.getLatestTag({
owner,
repo,
})
: undefined;
? await releaser.getLatestTag({
owner,
repo,
})
: undefined;
if (latestTag) {
console.log(`🏷️ Latest tag related to a release is ${latestTag}`);
@ -267,11 +229,15 @@ export const release = async (
repo,
tag_name,
previous_tag_name: previous_tag || latestTag,
})
} as GenerateReleaseNotesParams)
: "";
if (generate_release_notes && previous_tag || latestTag) {
console.log(`Will generate release notes using ${previous_tag || latestTag} as previous tag`);
if ((generate_release_notes && previous_tag) || latestTag) {
console.log(
`Will generate release notes using ${
previous_tag || latestTag
} as previous tag`
);
}
body = body ? `${body}\n` : "";
@ -319,10 +285,12 @@ export const release = async (
const existingReleaseBody = existingRelease.data.body || "";
if (config.input_append_body && workflowBody && existingReleaseBody) {
console.log(' Appending existing release body');
console.log(" Appending existing release body");
body = body + existingReleaseBody + "\n" + workflowBody;
} else {
console.log(` Using ${workflowBody ? 'workflow body' : 'existing release body'}`);
console.log(
` Using ${workflowBody ? "workflow body" : "existing release body"}`
);
body = body + (workflowBody || existingReleaseBody);
}
@ -335,6 +303,8 @@ export const release = async (
? config.input_prerelease
: existingRelease.data.prerelease;
const make_latest = config.input_make_latest!;
const release = await releaser.updateRelease({
owner,
repo,
@ -346,7 +316,8 @@ export const release = async (
draft,
prerelease,
discussion_category_name,
});
make_latest,
} as UpdateReleaseParams);
return release.data;
} catch (error) {
if (error.status === 404) {
@ -355,13 +326,14 @@ export const release = async (
const workflowBody = releaseBody(config) || "";
if (config.input_append_body && workflowBody) {
console.log(' Appending existing release body');
console.log(" Appending existing release body");
body = body + workflowBody;
}
const draft = config.input_draft;
const prerelease = config.input_prerelease;
const target_commitish = config.input_target_commitish;
const make_latest = config.input_make_latest!;
let commitMessage: string = "";
if (target_commitish) {
commitMessage = ` using commit "${target_commitish}"`;
@ -380,7 +352,8 @@ export const release = async (
prerelease,
target_commitish,
discussion_category_name,
});
make_latest,
} as CreateReleaseParams);
return release.data;
} catch (error) {
// presume a race with competing metrix runs

View file

@ -24,9 +24,13 @@ async function run() {
}
if (config.input_files) {
const patterns = unmatchedPatterns(config.input_files);
patterns.forEach((pattern) =>
console.warn(`🤔 Pattern '${pattern}' does not match any files.`)
);
patterns.forEach((pattern) => {
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ Pattern '${pattern}' does not match any files.`);
} else {
console.warn(`🤔 Pattern '${pattern}' does not match any files.`);
}
});
if (patterns.length > 0 && config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ There were unmatched files`);
}
@ -60,10 +64,14 @@ async function run() {
});
//);
const rel = await release(config, new GitHubReleaser(gh));
if (config.input_files) {
if (config.input_files && config.input_files.length > 0) {
const files = paths(config.input_files);
if (files.length == 0) {
console.warn(`🤔 ${config.input_files} not include valid file.`);
if (config.input_fail_on_unmatched_files) {
throw new Error(`⚠️ ${config.input_files} not include valid file.`);
} else {
console.warn(`🤔 ${config.input_files} not include valid file.`);
}
}
const currentAssets = rel.assets;
const assets = await Promise.all(

View file

@ -20,6 +20,7 @@ export interface Config {
input_generate_release_notes?: boolean;
input_append_body?: boolean;
input_previous_tag?: string;
input_make_latest?: string;
}
export const uploadUrl = (url: string): string => {
@ -71,6 +72,9 @@ export const parseConfig = (env: Env): Config => {
env.INPUT_DISCUSSION_CATEGORY_NAME || undefined,
input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true",
input_append_body: env.INPUT_APPEND_BODY == "true",
input_make_latest: env.INPUT_MAKE_LATEST
? env.INPUT_MAKE_LATEST
: undefined,
input_previous_tag: env.INPUT_PREVIOUS_TAG?.trim() || undefined,
};
};