Compare commits

..

73 Commits

Author SHA1 Message Date
Jess Bees
125d07c91d Merge pull request #251 from konradpabjan/main
Deploy pages using artifact IDs
2023-11-03 14:07:27 -04:00
Konrad Pabjan
7496661f94 Undo unnecessary reorder 2023-10-30 15:44:53 -04:00
Konrad Pabjan
4279385f7d Add extra test 2023-10-30 15:36:01 -04:00
Konrad Pabjan
a075a5970d Rebuild the dist folder 2023-10-30 15:07:46 -04:00
Konrad Pabjan
b15b65d3e5 Misc tweaks 2023-10-30 15:04:12 -04:00
Konrad Pabjan
fa898e325d Update tests + cleanup 2023-10-30 14:58:12 -04:00
Konrad Pabjan
d45e4be1a6 WIP 2023-10-27 17:52:04 -04:00
Konrad Pabjan
b12897a760 WIP 2023-10-27 17:50:16 -04:00
Konrad Pabjan
499890a085 WIP 2023-10-27 17:40:12 -04:00
Konrad Pabjan
324d9f15de WIP 2023-10-27 17:00:48 -04:00
Konrad Pabjan
2196d013ad WIP 2023-10-27 16:49:22 -04:00
Konrad Pabjan
ce81cfb969 WIP 2023-10-27 16:47:13 -04:00
Konrad Pabjan
da4705cd08 WIP 2023-10-27 16:41:02 -04:00
Konrad Pabjan
961a4a1557 WIP 2023-10-27 16:34:41 -04:00
Konrad Pabjan
38d3e68bdc Build 2023-10-27 16:19:24 -04:00
Konrad Pabjan
08232476b8 WIP 2023-10-27 16:13:35 -04:00
James M. Greene
fa86ad3bc1 Merge pull request #243 from actions/definitely-not-beta
Remove "beta" disclaimer from README
2023-10-18 15:50:57 -05:00
James M. Greene
976abf18ca Remove "beta" disclaimer from README 2023-10-18 14:43:26 -05:00
Yoann Chaudet
f69bebbdd5 Improve the README on all things artifacts 2023-07-27 22:30:35 -07:00
James M. Greene
9dbe382482 Merge pull request #201 from actions/update-compat-table
Update GHES compatibility table after verifying with `3.9.x`
2023-07-21 01:31:59 -05:00
James M. Greene
96a5bb957b Fix typo 2023-07-20 00:18:22 -05:00
James M. Greene
8458d4c873 Update GHES compatibility table after verifying with 3.9.x 2023-07-20 00:17:35 -05:00
James M. Greene
0fd60c869b Merge pull request #194 from actions/dependabot/npm_and_yarn/octokit/request-error-5.0.0
Bump @octokit/request-error from 4.0.1 to 5.0.0
2023-07-10 16:52:19 -05:00
dependabot[bot]
9f42854283 Bump @octokit/request-error from 4.0.1 to 5.0.0
Bumps [@octokit/request-error](https://github.com/octokit/request-error.js) from 4.0.1 to 5.0.0.
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v4.0.1...v5.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 21:49:41 +00:00
James M. Greene
935c3f915d Merge pull request #196 from actions/dependabot/npm_and_yarn/prettier-3.0.0
Bump prettier from 2.8.8 to 3.0.0
2023-07-10 16:48:29 -05:00
dependabot[bot]
9c31b72d4a Bump prettier from 2.8.8 to 3.0.0
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.0.0.
- [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/2.8.8...3.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 21:38:04 +00:00
James M. Greene
2b0ca4a2d6 Merge pull request #195 from actions/dependabot/npm_and_yarn/jest-29.6.1
Bump jest from 29.5.0 to 29.6.1
2023-07-10 16:37:21 -05:00
dependabot[bot]
f7b0e1891f Bump jest from 29.5.0 to 29.6.1
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.5.0 to 29.6.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.6.1/packages/jest)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 21:35:26 +00:00
James M. Greene
8b4e85a223 Merge pull request #192 from actions/dependabot/github_actions/release-drafter/release-drafter-5.24.0
Bump release-drafter/release-drafter from 5.23.0 to 5.24.0
2023-07-10 16:24:53 -05:00
dependabot[bot]
cca68c9d4b Bump release-drafter/release-drafter from 5.23.0 to 5.24.0
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.23.0 to 5.24.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](569eb7ee3a...65c5fb495d)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 21:22:30 +00:00
James M. Greene
73a7feb190 Merge pull request #191 from actions/dependabot/npm_and_yarn/eslint-8.44.0
Bump eslint from 8.42.0 to 8.44.0
2023-07-10 16:21:29 -05:00
dependabot[bot]
2457a7fc63 Bump eslint from 8.42.0 to 8.44.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.42.0 to 8.44.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.42.0...v8.44.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 21:11:29 +00:00
James M. Greene
a562022ed9 Merge pull request #197 from actions/break-the-circle
Remove circular JSON references for error debugging
2023-07-10 15:03:45 -05:00
James M. Greene
b865ababeb Remove circular JSON references for error debugging 2023-07-10 14:58:49 -05:00
Fabian Aguilar Gomez
12ab2b16cf Merge pull request #187 from actions/update-deploy-error-message
Add error message for file permissions
2023-06-16 13:38:01 -05:00
Fabian Aguilar Gomez
157c090d5a update dist 2023-06-16 15:41:51 +00:00
Fabian Aguilar Gomez
39bfa7a819 Update dist/index.js
Co-authored-by: Mingzi  <yimysty@github.com>
2023-06-16 10:38:43 -05:00
Fabian Aguilar Gomez
cdd88557f6 update index 2023-06-15 22:20:55 +00:00
Fabian Aguilar Gomez
9cf15d70b7 Update deployment.js 2023-06-15 16:57:51 -05:00
James M. Greene
80d8f1cab8 Merge pull request #182 from actions/dependabot/npm_and_yarn/octokit/request-error-4.0.1
Bump @octokit/request-error from 3.0.3 to 4.0.1
2023-06-12 15:55:45 -05:00
github-actions[bot]
ffdf102557 Update distributables after Dependabot 🤖 2023-06-07 16:16:20 +00:00
dependabot[bot]
a1b3914731 Bump @octokit/request-error from 3.0.3 to 4.0.1
Bumps [@octokit/request-error](https://github.com/octokit/request-error.js) from 3.0.3 to 4.0.1.
- [Release notes](https://github.com/octokit/request-error.js/releases)
- [Commits](https://github.com/octokit/request-error.js/compare/v3.0.3...v4.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-07 16:14:11 +00:00
James M. Greene
ee48c7b82e Merge pull request #183 from actions/dependabot/npm_and_yarn/eslint-8.42.0
Bump eslint from 8.40.0 to 8.42.0
2023-06-06 09:53:14 -05:00
dependabot[bot]
d9731c4933 Bump eslint from 8.40.0 to 8.42.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.40.0 to 8.42.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.40.0...v8.42.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-06 14:51:05 +00:00
James M. Greene
90eb49531e Merge pull request #181 from actions/dependabot/npm_and_yarn/eslint-plugin-github-4.8.0
Bump eslint-plugin-github from 4.7.0 to 4.8.0
2023-06-06 09:50:26 -05:00
dependabot[bot]
27cfbcb894 Bump eslint-plugin-github from 4.7.0 to 4.8.0
Bumps [eslint-plugin-github](https://github.com/github/eslint-plugin-github) from 4.7.0 to 4.8.0.
- [Release notes](https://github.com/github/eslint-plugin-github/releases)
- [Commits](https://github.com/github/eslint-plugin-github/compare/v4.7.0...v4.8.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-github
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-06 14:48:34 +00:00
James M. Greene
dc213a7f7d Merge pull request #177 from actions/artifact-size
Check artifact size and warn if too large
2023-06-06 09:47:49 -05:00
James M. Greene
fdbbcdba1c Update distributables (again) 2023-06-06 09:43:48 -05:00
James M. Greene
2c56c1e0f7 Tweak wording 2023-06-06 09:40:22 -05:00
Greta Parks
2fb2bbeb02 Check artifact size and warn if too large 2023-05-22 17:00:13 +00:00
James M. Greene
b580d214b4 Merge pull request #169 from actions/dependabot/npm_and_yarn/eslint-8.40.0
Bump eslint from 8.38.0 to 8.40.0
2023-05-16 12:16:29 -05:00
dependabot[bot]
19e3eb4e0c Bump eslint from 8.38.0 to 8.40.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.38.0 to 8.40.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.38.0...v8.40.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-16 17:12:07 +00:00
James M. Greene
e3fab2ac01 Merge pull request #167 from actions/dependabot/npm_and_yarn/nock-13.3.1
Bump nock from 13.3.0 to 13.3.1
2023-05-16 12:11:22 -05:00
dependabot[bot]
bc2634f423 Bump nock from 13.3.0 to 13.3.1
Bumps [nock](https://github.com/nock/nock) from 13.3.0 to 13.3.1.
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v13.3.0...v13.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-16 16:32:08 +00:00
James M. Greene
f4c31b94b1 Merge pull request #159 from actions/dependabot/npm_and_yarn/prettier-2.8.8
Bump prettier from 2.8.7 to 2.8.8
2023-05-16 11:30:50 -05:00
dependabot[bot]
af578d2e40 Bump prettier from 2.8.7 to 2.8.8
Bumps [prettier](https://github.com/prettier/prettier) from 2.8.7 to 2.8.8.
- [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/2.8.7...2.8.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-16 16:15:02 +00:00
James M. Greene
8492390532 Merge pull request #170 from actions/timeout-fix
Timeout fix
2023-05-16 11:00:14 -05:00
James M. Greene
2905629ea4 Merge branch 'main' into timeout-fix 2023-05-16 10:28:30 -05:00
James M. Greene
c9a8d971f4 Merge pull request #175 from actions/ghes-warning
Add a support note to the deployment creation error if using GHES
2023-05-16 10:27:08 -05:00
James M. Greene
ff6c51e54c Remove period to avoid messing up URL 2023-05-16 10:15:22 -05:00
James M. Greene
b26c4cb790 Add a support note to the deployment creation error if using GHES 2023-05-16 10:13:05 -05:00
James M. Greene
6b39486d2c Move compatibility table to a less prominent spot 2023-05-15 17:49:07 -05:00
James M. Greene
69cf9b75ca Merge pull request #173 from actions/compat-table
Add GHES compatibility table
2023-05-15 14:32:13 -05:00
James M. Greene
668cc2675f Add a horizontal rule for a visual break 2023-05-15 14:29:46 -05:00
James M. Greene
edaafab71f Add a compatibility note to the release notes generation template 2023-05-15 14:21:12 -05:00
James M. Greene
fb67d78c18 Add a compatibility table to the README 2023-05-15 14:16:47 -05:00
Greta Parks
21b085af5f little rename for nuance 2023-05-12 16:54:50 +00:00
Greta Parks
ccca7e9d96 Some fixes 2023-05-12 16:28:50 +00:00
Greta Parks
c02d64fe5c Revert "fix error count lies and clean up tests a bit"
This reverts commit 3e2c26d7d5.
2023-05-12 15:53:50 +00:00
Greta Parks
dcb366ca66 Update src/internal/deployment.js
Co-authored-by: James M. Greene <JamesMGreene@github.com>
2023-05-12 09:40:31 -06:00
Greta Parks
3e2c26d7d5 fix error count lies and clean up tests a bit 2023-05-11 20:38:18 +00:00
Greta Parks
054faf7e6d enforce a max timeout 2023-05-11 18:39:06 +00:00
Greta Parks
bacaae7379 add warning and test for timeout over maximum 2023-05-09 21:26:22 +00:00
14 changed files with 1785 additions and 1642 deletions

View File

@@ -6,7 +6,11 @@ template: |
$CHANGES
---
See details of [all code changes](https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release.
:warning: For use with products other than GitHub.com, such as GitHub Enterprise Server, please consult the [compatibility table](https://github.com/$OWNER/$REPOSITORY/#compatibilty).
categories:
- title: '🚀 Features'
labels:

View File

@@ -11,6 +11,6 @@ jobs:
draft-release:
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@569eb7ee3a85817ab916c8f8ff03a5bd96c9c83e # v5.23.0
- uses: release-drafter/release-drafter@65c5fb495d1e69aa8c08a3317bc44ff8aabe9772 # v5.24.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,11 +6,11 @@ This action is used to deploy [Actions artifacts][artifacts] to [GitHub Pages](h
## Usage
See [action.yml](action.yml) for the various `inputs` this action supports.
See [action.yml](action.yml) for the various `inputs` this action supports (or [below](#inputs-📥)).
For examples that make use of this action, check out our [starter-workflows][starter-workflows] in a variety of frameworks.
This action expects an artifact named `github-pages` to have been created prior to execution. This is done automatically when using [`actions/upload-pages-artifact`][upload-pages-artifact].
This action deploys a Pages site previously uploaded as an artifact (e.g. using [`actions/upload-pages-artifact`][upload-pages-artifact]).
We recommend this action to be used in a dedicated job:
@@ -67,15 +67,11 @@ jobs:
| -------- | ----------- |
| `GITHUB_PAGES` | This environment variable is created and set to the string value `"true"` so that framework build tools may choose to differentiate their output based on the intended target hosting platform. |
## Scope
⚠️ Official support for building Pages with Actions is in public beta at the moment.
## Security Considerations
There are a few important considerations to be aware of:
1. The artifact being deployed must have been uploaded in a previous step, either in the same job or a separate job that doesn't execute until the upload is complete.
1. The artifact being deployed must have been uploaded in a previous step, either in the same job or a separate job that doesn't execute until the upload is complete. See [`actions/upload-pages-artifact`][upload-pages-artifact] for more information about the format of the artifact we expect.
2. The job that executes the deployment must at minimum have the following permissions:
- `pages: write`
@@ -87,6 +83,20 @@ There are a few important considerations to be aware of:
5. If your Pages site is using GitHub Actions as the source, while not required we highly recommend you also [protect your environment][environment-protection] (we will configure it by default for you).
## Compatibility
This action is primarily design for use with GitHub.com's Actions workflows and Pages deployments. However, certain releases should also be compatible with GitHub Enterprise Server (GHES) `3.7` and above.
| Release | GHES Compatibility |
|:---|:---|
| [`v2`](https://github.com/actions/deploy-pages/releases/tag/v2) | `>= 3.9` |
| `v2.x.x` | `>= 3.9` |
| [`v1`](https://github.com/actions/deploy-pages/releases/tag/v1) | `>= 3.7` |
| [`v1.2.8`](https://github.com/actions/deploy-pages/releases/tag/v1.2.8) | `>= 3.7` |
| [`v1.2.7`](https://github.com/actions/deploy-pages/releases/tag/v1.2.7) | :warning: `>= 3.9` [Incompatible with prior versions!](https://github.com/actions/deploy-pages/issues/137) |
| [`v1.2.6`](https://github.com/actions/deploy-pages/releases/tag/v1.2.6) | `>= 3.7` |
| `v1.x.x` | `>= 3.7` |
## Release Instructions
In order to release a new version of this Action:

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 73.13%"><title>Coverage: 73.13%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">73.13%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">73.13%</text></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 79.53%"><title>Coverage: 79.53%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">79.53%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">79.53%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

359
dist/index.js generated vendored
View File

@@ -4090,79 +4090,6 @@ exports.restEndpointMethods = restEndpointMethods;
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 537:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var deprecation = __nccwpck_require__(8932);
var once = _interopDefault(__nccwpck_require__(1223));
const logOnceCode = once(deprecation => console.warn(deprecation));
const logOnceHeaders = once(deprecation => console.warn(deprecation));
/**
* Error with extra properties to help with debugging
*/
class RequestError extends Error {
constructor(message, statusCode, options) {
super(message);
// Maintains proper stack trace (only available on V8)
/* istanbul ignore next */
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
this.name = "HttpError";
this.status = statusCode;
let headers;
if ("headers" in options && typeof options.headers !== "undefined") {
headers = options.headers;
}
if ("response" in options) {
this.response = options.response;
headers = options.response.headers;
}
// redact request credentials without mutating original request options
const requestCopy = Object.assign({}, options.request);
if (options.request.headers.authorization) {
requestCopy.headers = Object.assign({}, options.request.headers, {
authorization: options.request.headers.authorization.replace(/ .*$/, " [REDACTED]")
});
}
requestCopy.url = requestCopy.url
// client_id & client_secret can be passed as URL query parameters to increase rate limit
// see https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications
.replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]")
// OAuth tokens can be passed as URL query parameters, although it is not recommended
// see https://developer.github.com/v3/#oauth2-token-sent-in-a-header
.replace(/\baccess_token=\w+/g, "access_token=[REDACTED]");
this.request = requestCopy;
// deprecations
Object.defineProperty(this, "code", {
get() {
logOnceCode(new deprecation.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`."));
return statusCode;
}
});
Object.defineProperty(this, "headers", {
get() {
logOnceHeaders(new deprecation.Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`."));
return headers || {};
}
});
}
}
exports.RequestError = RequestError;
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 6234:
@@ -4639,102 +4566,6 @@ class Deprecation extends Error {
exports.Deprecation = Deprecation;
/***/ }),
/***/ 3703:
/***/ ((module) => {
// Source: 2014-06-11: http://en.wikipedia.org/wiki/HTTP_status_codes
module.exports = {
100: "Continue",
101: "Switching Protocols",
102: "Processing",
200: "OK",
201: "Created",
202: "Accepted",
203: "Non-Authoritative Information",
204: "No Content",
205: "Reset Content",
206: "Partial Content",
207: "Multi-Status",
208: "Already Reported",
226: "IM Used",
300: "Multiple Choices",
301: "Moved Permanently",
302: "Found",
303: "See Other",
304: "Not Modified",
305: "Use Proxy",
306: "Switch Proxy",
307: "Temporary Redirect",
308: "Permanent Redirect",
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Request Entity Too Large",
414: "Request-URI Too Long",
415: "Unsupported Media Type",
416: "Requested Range Not Satisfiable",
417: "Expectation Failed",
418: "I'm a teapot",
419: "Authentication Timeout",
420: "Method Failure",
420: "Enhance Your Calm",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
426: "Upgrade Required",
428: "Precondition Required",
429: "Too Many Requests",
431: "Request Header Fields Too Large",
440: "Login Timeout",
444: "No Response",
449: "Retry With",
450: "Blocked by Windows Parental Controls",
451: "Unavailable For Legal Reasons",
451: "Redirect",
494: "Request Header Too Large",
495: "Cert Error",
496: "No Cert",
497: "HTTP to HTTPS",
499: "Client Closed Request",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
506: "Variant Also Negotiates",
507: "Insufficient Storage",
508: "Loop Detected",
509: "Bandwidth Limit Exceeded",
510: "Not Extended",
511: "Network Authentication Required",
520: "Origin Error",
521: "Web server is down",
522: "Connection timed out",
523: "Proxy Declined Request",
524: "A timeout occurred",
598: "Network read timeout error",
599: "Network connect timeout error"
};
/***/ }),
/***/ 3287:
@@ -9786,110 +9617,62 @@ function wrappy (fn, cb) {
const core = __nccwpck_require__(2186)
const github = __nccwpck_require__(5438)
const hc = __nccwpck_require__(6255)
const { RequestError } = __nccwpck_require__(537)
const HttpStatusMessages = __nccwpck_require__(3703)
// All variables we need from the runtime are loaded here
const getContext = __nccwpck_require__(8454)
async function processRuntimeResponse(res, requestOptions) {
// Parse the response body as JSON
let obj = null
try {
const contents = await res.readBody()
if (contents && contents.length > 0) {
obj = JSON.parse(contents)
}
} catch (error) {
// Invalid resource (contents not json); leaving resulting obj as null
}
// Specific response shape aligned with Octokit
const response = {
url: res.message?.url || requestOptions.url,
status: res.message?.statusCode || 0,
headers: {
...res.message?.headers
},
data: obj
}
// Forcibly throw errors for negative HTTP status codes!
// @actions/http-client doesn't do this by default.
// Mimic the errors thrown by Octokit for consistency.
if (response.status >= 400) {
// Try to get an error message from the response body
const errorMsg =
(typeof response.data === 'string' && response.data) ||
response.data?.error ||
response.data?.message ||
// Try the Node HTTP IncomingMessage's statusMessage property
res.message?.statusMessage ||
// Fallback to the HTTP status message based on the status code
HttpStatusMessages[response.status] ||
// Or if the status code is unexpected...
`Unknown error (${response.status})`
throw new RequestError(errorMsg, response.status, {
response,
request: requestOptions
})
}
return response
}
async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName }) {
const { runTimeUrl: RUNTIME_URL } = getContext()
const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview`
const httpClient = new hc.HttpClient()
let data = null
async function getArtifactMetadata({ githubToken, runId, artifactName }) {
const octokit = github.getOctokit(githubToken)
try {
const requestHeaders = {
accept: 'application/json',
authorization: `Bearer ${runtimeToken}`
}
const requestOptions = {
method: 'GET',
url: artifactExchangeUrl,
headers: {
...requestHeaders
},
body: null
core.info(`Fetching artifact metadata for ${artifactName} in run ${runId}`)
const response = await octokit.request(
'GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts?name={artifactName}',
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
run_id: runId,
artifactName: artifactName
}
)
const artifactCount = response.data.total_count
core.debug(`List artifact count: ${artifactCount}`)
if (artifactCount === 0) {
throw new Error(
`No artifacts found for workflow run ${runId}. Ensure artifacts are uploaded with actions/artifact@v4 or later.`
)
} else if (artifactCount > 1) {
throw new Error(
`Multiple artifact unexpectedly found for workflow run ${runId}. Artifact count is ${artifactCount}.`
)
}
core.info(`Artifact exchange URL: ${artifactExchangeUrl}`)
const res = await httpClient.get(artifactExchangeUrl, requestHeaders)
const artifact = response.data.artifacts[0]
core.debug(`Artifact: ${JSON.stringify(artifact)}`)
// May throw a RequestError (HttpError)
const response = await processRuntimeResponse(res, requestOptions)
const artifactSize = artifact.size_in_bytes
if (!artifactSize) {
core.warning('Artifact size was not found. Unable to verify if artifact size exceeds the allowed size.')
}
data = response.data
core.debug(JSON.stringify(data))
return {
id: artifact.id,
size: artifactSize
}
} catch (error) {
core.error('Getting signed artifact URL failed', error)
core.error(
'Fetching artifact metadata failed. Is githubstatus.com reporting issues with API requests, Pages or Actions? Please re-run the deployment at a later time.',
error
)
throw error
}
const artifactRawUrl = data?.value?.find(artifact => artifact.name === artifactName)?.url
if (!artifactRawUrl) {
throw new Error(
'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.'
)
}
const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
return signedArtifactUrl
}
async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) {
async function createPagesDeployment({ githubToken, artifactId, buildVersion, idToken, isPreview = false }) {
const octokit = github.getOctokit(githubToken)
const payload = {
artifact_url: artifactUrl,
artifact_id: artifactId,
pages_build_version: buildVersion,
oidc_token: idToken
}
@@ -9949,7 +9732,7 @@ async function cancelPagesDeployment({ githubToken, deploymentId }) {
}
module.exports = {
getSignedArtifactUrl,
getArtifactMetadata,
createPagesDeployment,
getPagesDeploymentStatus,
cancelPagesDeployment
@@ -9966,9 +9749,7 @@ const core = __nccwpck_require__(2186)
// Load variables from Actions runtime
function getRequiredVars() {
return {
runTimeUrl: process.env.ACTIONS_RUNTIME_URL,
workflowRun: process.env.GITHUB_RUN_ID,
runTimeToken: process.env.ACTIONS_RUNTIME_TOKEN,
repositoryNwo: process.env.GITHUB_REPOSITORY,
buildVersion: process.env.GITHUB_SHA,
buildActor: process.env.GITHUB_ACTOR,
@@ -10003,7 +9784,7 @@ const core = __nccwpck_require__(2186)
// All variables we need from the runtime are loaded here
const getContext = __nccwpck_require__(8454)
const {
getSignedArtifactUrl,
getArtifactMetadata,
createPagesDeployment,
getPagesDeploymentStatus,
cancelPagesDeployment
@@ -10017,18 +9798,21 @@ const temporaryErrorStatus = {
const finalErrorStatus = {
deployment_failed: 'Deployment failed, try again later.',
deployment_perms_error: 'Deployment failed, Please ensure that the file permissions are correct.',
deployment_content_failed:
'Artifact could not be deployed. Please ensure the content does not contain any hard links, symlinks and total size is less than 10GB.',
deployment_cancelled: 'Deployment cancelled.',
deployment_lost: 'Deployment failed to report final status.'
}
const MAX_TIMEOUT = 600000
const ONE_GIGABYTE = 1073741824
const SIZE_LIMIT_DESCRIPTION = '1 GB'
class Deployment {
constructor() {
const context = getContext()
this.runTimeUrl = context.runTimeUrl
this.repositoryNwo = context.repositoryNwo
this.runTimeToken = context.runTimeToken
this.buildVersion = context.buildVersion
this.buildActor = context.buildActor
this.actionsId = context.actionsId
@@ -10039,25 +9823,42 @@ class Deployment {
this.githubServerUrl = context.githubServerUrl
this.artifactName = context.artifactName
this.isPreview = context.isPreview === true
this.timeout = MAX_TIMEOUT
this.startTime = null
}
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
// by creating a deployment with that artifact
// Call GitHub api to fetch artifacts matching the provided name and deploy to GitHub Pages
// by creating a deployment with that artifact id
async create(idToken) {
if (Number(core.getInput('timeout')) > MAX_TIMEOUT) {
core.warning(
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
)
}
const timeoutInput = Number(core.getInput('timeout'))
this.timeout = !timeoutInput || timeoutInput <= 0 ? MAX_TIMEOUT : Math.min(timeoutInput, MAX_TIMEOUT)
try {
core.debug(`Actor: ${this.buildActor}`)
core.debug(`Action ID: ${this.actionsId}`)
core.debug(`Actions Workflow Run ID: ${this.workflowRun}`)
const artifactUrl = await getSignedArtifactUrl({
runtimeToken: this.runTimeToken,
workflowRunId: this.workflowRun,
const artifactData = await getArtifactMetadata({
githubToken: this.githubToken,
runId: this.workflowRun,
artifactName: this.artifactName
})
if (artifactData?.size > ONE_GIGABYTE) {
core.warning(
`Uploaded artifact size of ${artifactData?.size} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
}
const deployment = await createPagesDeployment({
githubToken: this.githubToken,
artifactUrl,
artifactId: artifactData.id,
buildVersion: this.buildVersion,
idToken,
isPreview: this.isPreview
@@ -10069,6 +9870,7 @@ class Deployment {
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
pending: true
}
this.startTime = Date.now()
}
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
@@ -10079,9 +9881,6 @@ class Deployment {
} catch (error) {
core.error(error.stack)
// output raw error in debug mode.
core.debug(JSON.stringify(error))
// build customized error message based on server response
if (error.response) {
let errorMessage = `Failed to create deployment (status: ${error.status}) with build version ${this.buildVersion}. `
@@ -10092,6 +9891,11 @@ class Deployment {
} else if (error.status === 404) {
const pagesSettingsUrl = `${this.githubServerUrl}/${this.repositoryNwo}/settings/pages`
errorMessage += `Ensure GitHub Pages has been enabled: ${pagesSettingsUrl}`
// If using GHES, add a special note about compatibility
if (new URL(this.githubServerUrl).hostname.toLowerCase() !== 'github.com') {
errorMessage +=
'\nNote: This action version may not yet support GitHub Enterprise Server, please check the compatibility table.'
}
} else if (error.status >= 500) {
errorMessage +=
'Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.'
@@ -10117,11 +9921,9 @@ class Deployment {
}
const deploymentId = this.deploymentInfo.id || this.buildVersion
const timeout = Number(core.getInput('timeout'))
const reportingInterval = Number(core.getInput('reporting_interval'))
const maxErrorCount = Number(core.getInput('error_count'))
let startTime = Date.now()
let errorCount = 0
// Time in milliseconds between two deployment status report when status errored, default 0.
@@ -10163,9 +9965,6 @@ class Deployment {
} catch (error) {
core.error(error.stack)
// output raw error in debug mode.
core.debug(JSON.stringify(error))
// build customized error message based on server response
if (error.response) {
errorStatus = error.status || error.response.status
@@ -10189,7 +9988,7 @@ class Deployment {
}
// Handle timeout
if (Date.now() - startTime >= timeout) {
if (Date.now() - this.startTime >= this.timeout) {
core.error('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
@@ -10226,7 +10025,7 @@ class Deployment {
}
}
module.exports = { Deployment }
module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }
/***/ }),

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

2
dist/licenses.txt generated vendored
View File

@@ -453,8 +453,6 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
http-status-messages
is-plain-object
MIT
The MIT License (MIT)

2267
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,20 +5,17 @@
"main": "./dist/index.js",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
"@actions/http-client": "^2.1.0",
"@octokit/request-error": "^3.0.3",
"http-status-messages": "^1.1.0"
"@actions/github": "^5.1.1"
},
"devDependencies": {
"@vercel/ncc": "^0.36.1",
"eslint": "^8.36.0",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-github": "^4.7.0",
"jest": "^29.5.0",
"nock": "^13.3.0",
"prettier": "^2.8.7",
"make-coverage-badge": "^1.2.0"
"eslint-plugin-github": "^4.8.0",
"jest": "^29.6.1",
"make-coverage-badge": "^1.2.0",
"nock": "^13.3.1",
"prettier": "^3.0.0"
},
"scripts": {
"all": "npm run format && npm run lint && npm run prepare && npm run test && npm run coverage-badge",

View File

@@ -4,9 +4,7 @@ const path = require('path')
describe('with all environment variables set', () => {
beforeEach(() => {
process.env.ACTIONS_RUNTIME_URL = 'http://my-url'
process.env.GITHUB_RUN_ID = '123'
process.env.ACTIONS_RUNTIME_TOKEN = 'a-token'
process.env.GITHUB_REPOSITORY = 'actions/is-awesome'
process.env.GITHUB_TOKEN = 'gha-token'
process.env.GITHUB_SHA = '123abc'
@@ -26,7 +24,7 @@ describe('with all environment variables set', () => {
describe('with variables missing', () => {
it('execution fails if there are missing variables', done => {
delete process.env.ACTIONS_RUNTIME_URL
delete process.env.GITHUB_RUN_ID
const ip = path.join(__dirname, '../index.js')
cp.exec(`node ${ip}`, { env: process.env }, (err, stdout) => {
expect(stdout).toBe('')

View File

@@ -1,7 +1,7 @@
const core = require('@actions/core')
const nock = require('nock')
const { Deployment } = require('../../internal/deployment')
const { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION } = require('../../internal/deployment')
const fakeJwt =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
@@ -9,9 +9,7 @@ const fakeJwt =
describe('Deployment', () => {
beforeEach(() => {
jest.clearAllMocks()
process.env.ACTIONS_RUNTIME_URL = 'http://my-url/'
process.env.GITHUB_RUN_ID = '123'
process.env.ACTIONS_RUNTIME_TOKEN = 'a-token'
process.env.GITHUB_REPOSITORY = 'actions/is-awesome'
process.env.GITHUB_TOKEN = 'gha-token'
process.env.GITHUB_SHA = '123abc'
@@ -53,18 +51,18 @@ describe('Deployment', () => {
it('can successfully create a deployment', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
@@ -84,25 +82,25 @@ describe('Deployment', () => {
expect.stringMatching(new RegExp(`^Created deployment for ${process.env.GITHUB_SHA}`))
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('can successfully create a preview deployment', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt,
preview: true
@@ -127,36 +125,44 @@ describe('Deployment', () => {
expect.stringMatching(new RegExp(`^Created deployment for ${process.env.GITHUB_SHA}`))
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('reports errors with failed artifact exchange', async () => {
it('reports errors with failed artifact metadata exchange', async () => {
process.env.GITHUB_SHA = 'invalid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(400, {})
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(400, { message: 'Bad request' })
// Create the deployment
const deployment = new Deployment()
await expect(deployment.create()).rejects.toEqual(
new Error(
`Failed to create deployment (status: 400) with build version ${process.env.GITHUB_SHA}. Responded with: Bad Request`
`Failed to create deployment (status: 400) with build version ${process.env.GITHUB_SHA}. Responded with: Bad request`
)
)
artifactExchangeScope.done()
artifactMetadataScope.done()
})
it('reports errors with a failed 500 in a deployment', async () => {
process.env.GITHUB_SHA = 'build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] })
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA
})
.reply(500, { message: 'oh no' })
@@ -169,19 +175,24 @@ describe('Deployment', () => {
)
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('reports errors with an unexpected 403 during deployment', async () => {
process.env.GITHUB_SHA = 'build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] })
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA
})
.reply(403, { message: 'You are forbidden' })
@@ -194,19 +205,24 @@ describe('Deployment', () => {
)
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('reports errors with an unexpected 404 during deployment', async () => {
process.env.GITHUB_SHA = 'build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] })
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA
})
.reply(404, { message: 'Not found' })
@@ -219,19 +235,24 @@ describe('Deployment', () => {
)
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('reports errors with failed deployments', async () => {
process.env.GITHUB_SHA = 'invalid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] })
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA
})
.reply(400, { message: 'Bad request' })
@@ -244,7 +265,169 @@ describe('Deployment', () => {
)
)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('fails if there are multiple artifacts with the same name', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 2,
artifacts: [
{
id: 13,
name: `github-pages`,
size_in_bytes: 1400
},
{
id: 14,
name: `github-pages`,
size_in_bytes: 1620
}
]
})
const deployment = new Deployment()
await expect(deployment.create(fakeJwt)).rejects.toThrow(
`Multiple artifact unexpectedly found for workflow run ${process.env.GITHUB_RUN_ID}. Artifact count is 2.`
)
artifactMetadataScope.done()
})
it('fails if there are no artifacts found', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 0,
artifacts: []
})
const deployment = new Deployment()
await expect(deployment.create(fakeJwt)).rejects.toThrow(
`No artifacts found for workflow run ${process.env.GITHUB_RUN_ID}. Ensure artifacts are uploaded with actions/artifact@v4 or later.`
)
artifactMetadataScope.done()
})
it('fails with error message if list artifact endpoint returns 500', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(500, { message: 'oh no' })
const deployment = new Deployment()
await expect(deployment.create(fakeJwt)).rejects.toThrow(
`Failed to create deployment (status: 500) with build version valid-build-version. Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.`
)
artifactMetadataScope.done()
})
it('warns if the artifact size is bigger than maximum', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactSize = ONE_GIGABYTE + 1
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [
{
id: 12,
name: `github-pages`,
size_in_bytes: `${artifactSize}`
}
]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_id: 12,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
const deployment = new Deployment()
await deployment.create(fakeJwt)
expect(core.warning).toBeCalledWith(
`Uploaded artifact size of ${artifactSize} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
expect(core.setFailed).not.toHaveBeenCalled()
expect(core.info).toHaveBeenLastCalledWith(
expect.stringMatching(new RegExp(`^Created deployment for ${process.env.GITHUB_SHA}`))
)
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('warns when the timeout is greater than the maximum allowed', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
jest.spyOn(core, 'getInput').mockImplementation(param => {
switch (param) {
case 'artifact_name':
return 'github-pages'
case 'token':
return process.env.GITHUB_TOKEN
case 'timeout':
return MAX_TIMEOUT + 1
default:
return process.env[`INPUT_${param.toUpperCase()}`] || ''
}
})
const deployment = new Deployment()
await deployment.create(fakeJwt)
expect(core.warning).toBeCalledWith(
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
)
artifactMetadataScope.done()
createDeploymentScope.done()
})
})
@@ -253,18 +436,18 @@ describe('Deployment', () => {
it('sets output to success when deployment is successful', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
@@ -280,14 +463,6 @@ describe('Deployment', () => {
})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
core.GetInput = jest.fn(input => {
switch (input) {
case 'timeout':
return 10 * 1000
case 'reporting_interval':
return 0
}
})
// Create the deployment
const deployment = new Deployment()
@@ -297,7 +472,7 @@ describe('Deployment', () => {
expect(core.setOutput).toBeCalledWith('status', 'succeed')
expect(core.info).toHaveBeenLastCalledWith('Reported success!')
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
deploymentStatusScope.done()
})
@@ -312,18 +487,18 @@ describe('Deployment', () => {
it('exits early when deployment is not in progress', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
@@ -333,14 +508,6 @@ describe('Deployment', () => {
})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
core.GetInput = jest.fn(input => {
switch (input) {
case 'timeout':
return 10 * 1000
case 'reporting_interval':
return 0
}
})
const deployment = new Deployment()
await deployment.create(fakeJwt)
@@ -348,27 +515,228 @@ describe('Deployment', () => {
await deployment.check()
expect(core.setFailed).toBeCalledWith('Unable to get deployment status.')
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
})
it('enforces max timeout', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
const cancelDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`)
.reply(200, {})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
// Set timeout to great than max
jest.spyOn(core, 'getInput').mockImplementation(param => {
switch (param) {
case 'artifact_name':
return 'github-pages'
case 'token':
return process.env.GITHUB_TOKEN
case 'error_count':
return 10
case 'timeout':
return MAX_TIMEOUT + 1
default:
return process.env[`INPUT_${param.toUpperCase()}`] || ''
}
})
const now = Date.now()
const mockStartTime = now - MAX_TIMEOUT
jest
.spyOn(Date, 'now')
.mockImplementationOnce(() => mockStartTime)
.mockImplementationOnce(() => now)
// Create the deployment
const deployment = new Deployment()
await deployment.create(fakeJwt)
await deployment.check()
expect(deployment.timeout).toEqual(MAX_TIMEOUT)
expect(core.error).toBeCalledWith('Timeout reached, aborting!')
expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!')
artifactMetadataScope.done()
createDeploymentScope.done()
cancelDeploymentScope.done()
})
it('sets timeout to user timeout if user timeout is less than max timeout', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
const cancelDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`)
.reply(200, {})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
// Set timeout to great than max
jest.spyOn(core, 'getInput').mockImplementation(param => {
switch (param) {
case 'artifact_name':
return 'github-pages'
case 'token':
return process.env.GITHUB_TOKEN
case 'error_count':
return 10
case 'timeout':
return 42
default:
return process.env[`INPUT_${param.toUpperCase()}`] || ''
}
})
const now = Date.now()
const mockStartTime = now - 42
jest
.spyOn(Date, 'now')
.mockImplementationOnce(() => mockStartTime)
.mockImplementationOnce(() => now)
// Create the deployment
const deployment = new Deployment()
await deployment.create(fakeJwt)
await deployment.check()
expect(deployment.timeout).toEqual(42)
expect(core.error).toBeCalledWith('Timeout reached, aborting!')
expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!')
artifactMetadataScope.done()
createDeploymentScope.done()
cancelDeploymentScope.done()
})
it('sets output to success when timeout is set but not reached', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
.reply(200, {
status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`,
page_url: 'https://actions.github.io/is-awesome'
})
const deploymentStatusScope = nock('https://api.github.com')
.get(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`)
.reply(200, {
status: 'succeed'
})
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
// Set timeout to great than max
jest.spyOn(core, 'getInput').mockImplementation(param => {
switch (param) {
case 'artifact_name':
return 'github-pages'
case 'token':
return process.env.GITHUB_TOKEN
case 'error_count':
return 10
case 'timeout':
return 42
default:
return process.env[`INPUT_${param.toUpperCase()}`] || ''
}
})
const now = Date.now()
const mockStartTime = now
jest
.spyOn(Date, 'now')
.mockImplementationOnce(() => mockStartTime)
.mockImplementationOnce(() => now)
// Create the deployment
const deployment = new Deployment()
await deployment.create(fakeJwt)
await deployment.check()
expect(deployment.timeout).toEqual(42)
expect(core.error).not.toBeCalled()
expect(core.setOutput).toBeCalledWith('status', 'succeed')
expect(core.info).toHaveBeenLastCalledWith('Reported success!')
artifactMetadataScope.done()
createDeploymentScope.done()
deploymentStatusScope.done()
})
})
describe('#cancel', () => {
it('can successfully cancel a deployment', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
@@ -392,7 +760,7 @@ describe('Deployment', () => {
expect(core.info).toHaveBeenLastCalledWith(`Canceled deployment with ID ${process.env.GITHUB_SHA}`)
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
cancelDeploymentScope.done()
})
@@ -413,18 +781,18 @@ describe('Deployment', () => {
it('catches an error when trying to cancel a deployment', async () => {
process.env.GITHUB_SHA = 'valid-build-version'
const artifactExchangeScope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
const artifactMetadataScope = nock(`https://api.github.com`)
.get(
`/repos/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts?name=github-pages`
)
.reply(200, {
value: [
{ url: 'https://another-artifact.com', name: 'another-artifact' },
{ url: 'https://fake-artifact.com', name: 'github-pages' }
]
total_count: 1,
artifacts: [{ id: 11, name: `github-pages`, size_in_bytes: 221 }]
})
const createDeploymentScope = nock('https://api.github.com')
.post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, {
artifact_url: 'https://fake-artifact.com&%24expand=SignedContent',
artifact_id: 11,
pages_build_version: process.env.GITHUB_SHA,
oidc_token: fakeJwt
})
@@ -449,7 +817,7 @@ describe('Deployment', () => {
expect(core.error).toHaveBeenCalledWith(`Canceling Pages deployment failed`, expect.anything())
artifactExchangeScope.done()
artifactMetadataScope.done()
createDeploymentScope.done()
cancelDeploymentScope.done()
})

View File

@@ -1,109 +1,61 @@
const core = require('@actions/core')
const github = require('@actions/github')
const hc = require('@actions/http-client')
const { RequestError } = require('@octokit/request-error')
const HttpStatusMessages = require('http-status-messages')
// All variables we need from the runtime are loaded here
const getContext = require('./context')
async function processRuntimeResponse(res, requestOptions) {
// Parse the response body as JSON
let obj = null
try {
const contents = await res.readBody()
if (contents && contents.length > 0) {
obj = JSON.parse(contents)
}
} catch (error) {
// Invalid resource (contents not json); leaving resulting obj as null
}
// Specific response shape aligned with Octokit
const response = {
url: res.message?.url || requestOptions.url,
status: res.message?.statusCode || 0,
headers: {
...res.message?.headers
},
data: obj
}
// Forcibly throw errors for negative HTTP status codes!
// @actions/http-client doesn't do this by default.
// Mimic the errors thrown by Octokit for consistency.
if (response.status >= 400) {
// Try to get an error message from the response body
const errorMsg =
(typeof response.data === 'string' && response.data) ||
response.data?.error ||
response.data?.message ||
// Try the Node HTTP IncomingMessage's statusMessage property
res.message?.statusMessage ||
// Fallback to the HTTP status message based on the status code
HttpStatusMessages[response.status] ||
// Or if the status code is unexpected...
`Unknown error (${response.status})`
throw new RequestError(errorMsg, response.status, {
response,
request: requestOptions
})
}
return response
}
async function getSignedArtifactUrl({ runtimeToken, workflowRunId, artifactName }) {
const { runTimeUrl: RUNTIME_URL } = getContext()
const artifactExchangeUrl = `${RUNTIME_URL}_apis/pipelines/workflows/${workflowRunId}/artifacts?api-version=6.0-preview`
const httpClient = new hc.HttpClient()
let data = null
async function getArtifactMetadata({ githubToken, runId, artifactName }) {
const octokit = github.getOctokit(githubToken)
try {
const requestHeaders = {
accept: 'application/json',
authorization: `Bearer ${runtimeToken}`
}
const requestOptions = {
method: 'GET',
url: artifactExchangeUrl,
headers: {
...requestHeaders
},
body: null
core.info(`Fetching artifact metadata for ${artifactName} in run ${runId}`)
const response = await octokit.request(
'GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts?name={artifactName}',
{
owner: github.context.repo.owner,
repo: github.context.repo.repo,
run_id: runId,
artifactName: artifactName
}
)
const artifactCount = response.data.total_count
core.debug(`List artifact count: ${artifactCount}`)
if (artifactCount === 0) {
throw new Error(
`No artifacts found for workflow run ${runId}. Ensure artifacts are uploaded with actions/artifact@v4 or later.`
)
} else if (artifactCount > 1) {
throw new Error(
`Multiple artifact unexpectedly found for workflow run ${runId}. Artifact count is ${artifactCount}.`
)
}
core.info(`Artifact exchange URL: ${artifactExchangeUrl}`)
const res = await httpClient.get(artifactExchangeUrl, requestHeaders)
const artifact = response.data.artifacts[0]
core.debug(`Artifact: ${JSON.stringify(artifact)}`)
// May throw a RequestError (HttpError)
const response = await processRuntimeResponse(res, requestOptions)
const artifactSize = artifact.size_in_bytes
if (!artifactSize) {
core.warning('Artifact size was not found. Unable to verify if artifact size exceeds the allowed size.')
}
data = response.data
core.debug(JSON.stringify(data))
return {
id: artifact.id,
size: artifactSize
}
} catch (error) {
core.error('Getting signed artifact URL failed', error)
core.error(
'Fetching artifact metadata failed. Is githubstatus.com reporting issues with API requests, Pages or Actions? Please re-run the deployment at a later time.',
error
)
throw error
}
const artifactRawUrl = data?.value?.find(artifact => artifact.name === artifactName)?.url
if (!artifactRawUrl) {
throw new Error(
'No uploaded artifact was found! Please check if there are any errors at build step, or uploaded artifact name is correct.'
)
}
const signedArtifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
return signedArtifactUrl
}
async function createPagesDeployment({ githubToken, artifactUrl, buildVersion, idToken, isPreview = false }) {
async function createPagesDeployment({ githubToken, artifactId, buildVersion, idToken, isPreview = false }) {
const octokit = github.getOctokit(githubToken)
const payload = {
artifact_url: artifactUrl,
artifact_id: artifactId,
pages_build_version: buildVersion,
oidc_token: idToken
}
@@ -163,7 +115,7 @@ async function cancelPagesDeployment({ githubToken, deploymentId }) {
}
module.exports = {
getSignedArtifactUrl,
getArtifactMetadata,
createPagesDeployment,
getPagesDeploymentStatus,
cancelPagesDeployment

View File

@@ -3,9 +3,7 @@ const core = require('@actions/core')
// Load variables from Actions runtime
function getRequiredVars() {
return {
runTimeUrl: process.env.ACTIONS_RUNTIME_URL,
workflowRun: process.env.GITHUB_RUN_ID,
runTimeToken: process.env.ACTIONS_RUNTIME_TOKEN,
repositoryNwo: process.env.GITHUB_REPOSITORY,
buildVersion: process.env.GITHUB_SHA,
buildActor: process.env.GITHUB_ACTOR,

View File

@@ -3,7 +3,7 @@ const core = require('@actions/core')
// All variables we need from the runtime are loaded here
const getContext = require('./context')
const {
getSignedArtifactUrl,
getArtifactMetadata,
createPagesDeployment,
getPagesDeploymentStatus,
cancelPagesDeployment
@@ -17,18 +17,21 @@ const temporaryErrorStatus = {
const finalErrorStatus = {
deployment_failed: 'Deployment failed, try again later.',
deployment_perms_error: 'Deployment failed, Please ensure that the file permissions are correct.',
deployment_content_failed:
'Artifact could not be deployed. Please ensure the content does not contain any hard links, symlinks and total size is less than 10GB.',
deployment_cancelled: 'Deployment cancelled.',
deployment_lost: 'Deployment failed to report final status.'
}
const MAX_TIMEOUT = 600000
const ONE_GIGABYTE = 1073741824
const SIZE_LIMIT_DESCRIPTION = '1 GB'
class Deployment {
constructor() {
const context = getContext()
this.runTimeUrl = context.runTimeUrl
this.repositoryNwo = context.repositoryNwo
this.runTimeToken = context.runTimeToken
this.buildVersion = context.buildVersion
this.buildActor = context.buildActor
this.actionsId = context.actionsId
@@ -39,25 +42,42 @@ class Deployment {
this.githubServerUrl = context.githubServerUrl
this.artifactName = context.artifactName
this.isPreview = context.isPreview === true
this.timeout = MAX_TIMEOUT
this.startTime = null
}
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
// by creating a deployment with that artifact
// Call GitHub api to fetch artifacts matching the provided name and deploy to GitHub Pages
// by creating a deployment with that artifact id
async create(idToken) {
if (Number(core.getInput('timeout')) > MAX_TIMEOUT) {
core.warning(
`Warning: timeout value is greater than the allowed maximum - timeout set to the maximum of ${MAX_TIMEOUT} milliseconds.`
)
}
const timeoutInput = Number(core.getInput('timeout'))
this.timeout = !timeoutInput || timeoutInput <= 0 ? MAX_TIMEOUT : Math.min(timeoutInput, MAX_TIMEOUT)
try {
core.debug(`Actor: ${this.buildActor}`)
core.debug(`Action ID: ${this.actionsId}`)
core.debug(`Actions Workflow Run ID: ${this.workflowRun}`)
const artifactUrl = await getSignedArtifactUrl({
runtimeToken: this.runTimeToken,
workflowRunId: this.workflowRun,
const artifactData = await getArtifactMetadata({
githubToken: this.githubToken,
runId: this.workflowRun,
artifactName: this.artifactName
})
if (artifactData?.size > ONE_GIGABYTE) {
core.warning(
`Uploaded artifact size of ${artifactData?.size} bytes exceeds the allowed size of ${SIZE_LIMIT_DESCRIPTION}. Deployment might fail.`
)
}
const deployment = await createPagesDeployment({
githubToken: this.githubToken,
artifactUrl,
artifactId: artifactData.id,
buildVersion: this.buildVersion,
idToken,
isPreview: this.isPreview
@@ -69,6 +89,7 @@ class Deployment {
id: deployment.id || deployment.status_url?.split('/')?.pop() || this.buildVersion,
pending: true
}
this.startTime = Date.now()
}
core.info(`Created deployment for ${this.buildVersion}, ID: ${this.deploymentInfo?.id}`)
@@ -79,9 +100,6 @@ class Deployment {
} catch (error) {
core.error(error.stack)
// output raw error in debug mode.
core.debug(JSON.stringify(error))
// build customized error message based on server response
if (error.response) {
let errorMessage = `Failed to create deployment (status: ${error.status}) with build version ${this.buildVersion}. `
@@ -92,6 +110,11 @@ class Deployment {
} else if (error.status === 404) {
const pagesSettingsUrl = `${this.githubServerUrl}/${this.repositoryNwo}/settings/pages`
errorMessage += `Ensure GitHub Pages has been enabled: ${pagesSettingsUrl}`
// If using GHES, add a special note about compatibility
if (new URL(this.githubServerUrl).hostname.toLowerCase() !== 'github.com') {
errorMessage +=
'\nNote: This action version may not yet support GitHub Enterprise Server, please check the compatibility table.'
}
} else if (error.status >= 500) {
errorMessage +=
'Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.'
@@ -117,11 +140,9 @@ class Deployment {
}
const deploymentId = this.deploymentInfo.id || this.buildVersion
const timeout = Number(core.getInput('timeout'))
const reportingInterval = Number(core.getInput('reporting_interval'))
const maxErrorCount = Number(core.getInput('error_count'))
let startTime = Date.now()
let errorCount = 0
// Time in milliseconds between two deployment status report when status errored, default 0.
@@ -163,9 +184,6 @@ class Deployment {
} catch (error) {
core.error(error.stack)
// output raw error in debug mode.
core.debug(JSON.stringify(error))
// build customized error message based on server response
if (error.response) {
errorStatus = error.status || error.response.status
@@ -189,7 +207,7 @@ class Deployment {
}
// Handle timeout
if (Date.now() - startTime >= timeout) {
if (Date.now() - this.startTime >= this.timeout) {
core.error('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
@@ -226,4 +244,4 @@ class Deployment {
}
}
module.exports = { Deployment }
module.exports = { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION }