Compare commits

..

79 Commits

Author SHA1 Message Date
James M. Greene
e490850a64 Lowercase the README title 2022-08-10 14:01:18 -05:00
James M. Greene
5743579482 Merge pull request #49 from actions/marketplace-unique-name
Update Action name to enable Marketplace publishing
2022-08-10 14:00:26 -05:00
James M. Greene
5fd268dcdd Update name per suggestion 2022-08-10 12:59:11 -05:00
James M. Greene
fbb46fa661 Update Action name for Marketplace publishing 2022-08-09 22:15:35 -05:00
Mingzi
eaaccf9fc5 Merge pull request #46 from actions/bug-fixing
Fix hardcoded api endpoint and artifact name lookup
2022-08-04 18:06:53 -07:00
yimysty
8daa1e0ead add syntax sugar back 2022-08-04 17:11:26 -07:00
yimysty
99f9079292 roll into right node syntax 2022-08-04 17:09:46 -07:00
yimysty
06d025f427 update node test version 2022-08-04 17:05:51 -07:00
yimysty
7f629c4ce0 apply the syntax 2022-08-04 17:04:26 -07:00
yimysty
35e615a00c check if it's due to "." 2022-08-04 16:56:13 -07:00
yimysty
462df77e16 add more log to debug 2022-08-04 16:52:07 -07:00
yimysty
9ebae0d26b try print error message 2022-08-04 16:25:55 -07:00
yimysty
d0b379e44d move artifact url out of context 2022-08-04 16:23:15 -07:00
yimysty
225abf7840 increase test timeout 2022-08-04 16:13:28 -07:00
yimysty
1f0422c0df add some debug log? 2022-08-04 16:07:20 -07:00
yimysty
85b0d1617e moke get artifact name 2022-08-04 16:02:46 -07:00
yimysty
3e976523d7 adjust pages hard code endpoint + fix artifact look up 2022-08-04 15:43:58 -07:00
Yoann Chaudet
38e42fe573 Merge pull request #42 from actions/more-doc
Update README to document a few things
2022-07-27 13:33:20 -07:00
Yoann Chaudet
44ea2ec0c1 Fix titles 2022-07-26 11:16:01 -07:00
Yoann Chaudet
b4e423ab11 Update README.md
Co-authored-by: Tommy Byrd <tcbyrd@github.com>
2022-07-26 11:14:52 -07:00
Yoann Chaudet
58b7d54130 Update README.md
Co-authored-by: Tommy Byrd <tcbyrd@github.com>
2022-07-26 11:14:35 -07:00
Yoann Chaudet
974e2a6ded Update README.md
Co-authored-by: Tommy Byrd <tcbyrd@github.com>
2022-07-26 11:11:30 -07:00
Yoann Chaudet
f5d172a561 Update README.md
Co-authored-by: Tommy Byrd <tcbyrd@github.com>
2022-07-26 11:11:16 -07:00
Yoann Chaudet
33bba0fd45 Update README.md
Co-authored-by: Tommy Byrd <tcbyrd@github.com>
2022-07-26 11:10:56 -07:00
Yoann Chaudet
1f18c7a3ba Document default too 2022-07-26 11:09:31 -07:00
Yoann Chaudet
86843fdbb5 Update README to document a few things 2022-07-26 10:47:31 -07:00
Mingzi
4d0af465be Merge pull request #41 from DarkC35/patch-1
Fix compare URL in Release
2022-07-05 14:44:51 -07:00
DarkC
bea9114e88 fix compare url in release 2022-07-05 12:24:09 +02:00
Mingzi
41f0a8ab89 Merge pull request #40 from actions/improve-error-message
Improve error message
2022-06-29 10:37:48 -07:00
yimysty
b918908973 run npm generate file 2022-06-29 10:35:08 -07:00
Mingzi
1ae5d2452b Update src/deployment.js
Co-authored-by: Yoann Chaudet <yoannchaudet@github.com>
2022-06-29 10:16:32 -07:00
yimysty
e2219a89b1 fix broken test cases 2022-06-28 18:18:42 -07:00
yimysty
72b116b825 fix unintended changes 2022-06-28 18:01:48 -07:00
yimysty
11a13019c2 adjust debugging message 2022-06-28 17:58:10 -07:00
yimysty
801d74db09 switch to console.log 2022-06-28 17:55:21 -07:00
yimysty
64c69a5fdf normalize error message 2022-06-28 17:50:08 -07:00
yimysty
03d70e4a19 info stack trace 2022-06-28 17:44:21 -07:00
yimysty
64e33b2a0d info stack trace 2022-06-28 17:39:10 -07:00
yimysty
c3d24faf75 info stack trace 2022-06-28 17:38:14 -07:00
yimysty
2b0c6eaf67 try output stacktrace as well 2022-06-28 17:35:03 -07:00
yimysty
358b034ef8 improve error message 2022-06-28 16:08:07 -07:00
Yoann Chaudet
13ef0cb0a0 Merge pull request #39 from actions/joshmgross/add-codeowners
Add CODEOWNERS
2022-06-14 13:30:16 -07:00
Josh Gross
2bf05927ae Add CODEOWNERS 2022-06-14 14:39:58 -04:00
Mingzi
0745e9700c Merge pull request #38 from actions/fix-cancell-token
Fix cancel deployment token is empty
2022-06-08 14:19:14 -07:00
yimysty
43dced9e8c add pack-lock.json 2022-06-08 12:57:34 -07:00
yimysty
fce105b3ea fix unable to cancel deployment due to cancel token nil 2022-06-08 11:47:06 -07:00
Yoann Chaudet
148e2ea9dd Create codeql-analysis.yml 2022-04-26 10:29:56 -07:00
Yoann Chaudet
506f839b97 Merge pull request #31 from fulldecent/patch-1
Correct documentation for reporting interval
2022-04-26 10:26:02 -07:00
Yoann Chaudet
f7a158aceb Merge branch 'main' into patch-1 2022-04-26 10:24:40 -07:00
Yoann Chaudet
ca23c7917e Merge pull request #29 from actions/dependabot/npm_and_yarn/minimist-1.2.6
Bump minimist from 1.2.5 to 1.2.6
2022-04-26 10:24:21 -07:00
dependabot[bot]
0c60998bd5 Bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-26 17:21:30 +00:00
Yoann Chaudet
4154a47b87 Merge pull request #34 from actions/dependabot/npm_and_yarn/follow-redirects-1.14.9
Bump follow-redirects from 1.14.4 to 1.14.9
2022-04-26 10:20:47 -07:00
Yoann Chaudet
17fd28439d ci 2022-04-26 10:19:37 -07:00
Yoann Chaudet
0f19a8f78c Update dist 2022-04-26 09:58:05 -07:00
dependabot[bot]
595c840e2a Bump follow-redirects from 1.14.4 to 1.14.9
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.4 to 1.14.9.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.4...v1.14.9)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-26 16:55:09 +00:00
Mingzi
57f2f8bd29 Merge pull request #32 from fulldecent/patch-2
correct spelling of GitHub
2022-04-15 11:21:39 -07:00
Mingzi
68c14dcd2c Merge branch 'main' into patch-2 2022-04-15 11:20:55 -07:00
Jess Bees
a7af90c328 Merge pull request #30 from actions/decouple-telemetry
Remove the support for older dynamic jekyll workflows
2022-04-15 13:51:54 -04:00
William Entriken
ef910bd895 correct spelling of GitHub 2022-04-11 14:30:09 -04:00
William Entriken
53f4e898cd Correct documentation for reporting interval 2022-04-11 14:29:33 -04:00
Jess Bees
62c650c70d Remove the support for older dynamic jekyll workflows
The pages dynamic workflow now decouples telemetry from deploy for 100%
of users, so we can remove this old conditional.
2022-04-04 16:12:36 -04:00
Jess Bees
eaf36f48c9 Merge pull request #24 from actions/decouple-telemetry
Decouple telemetry API call from main action
2022-03-31 12:34:24 -04:00
Jess Bees
01f6ae5af2 Recompile action after pulling in PR suggestions 2022-03-31 12:05:36 -04:00
Jess Bees
82cb77089c Update action.yml
Co-authored-by: James M. Greene <JamesMGreene@github.com>
2022-03-31 11:47:49 -04:00
Jess Bees
ad36b7023a Don't bother converting action input to string
This has been an established pattern with Actions for a long time; we don't have to worry about it changing.

Co-authored-by: James M. Greene <JamesMGreene@github.com>
2022-03-31 11:47:33 -04:00
Jess Bees
32b8b86ff0 Support existing behavior of this action 2022-03-29 15:08:35 -04:00
Jess Bees
a598b2af14 Correctly test for boolean input's truthiness
It gets cast to a string! Eep!
2022-03-29 09:45:18 -04:00
Jess Bees
f511fa4665 Merge branch 'main' into decouple-telemetry 2022-03-29 09:05:35 -04:00
Yoann Chaudet
0e157789db Merge pull request #27 from actions/increase-default-query-interval
Increase default query interval and fix time exceed bug
2022-03-28 12:38:22 -07:00
yimysty
12940a5b99 fix the timeout not honor bug 2022-03-28 12:32:59 -07:00
yimysty
6afc4f2884 slow query seconds 2022-03-28 12:28:46 -07:00
Mingzi
a68b5a4ae1 Merge pull request #26 from actions/parsing-number
Parse correct timeout
2022-03-28 11:21:14 -07:00
yimysty
171a8a05dd update number parsing 2022-03-28 11:19:50 -07:00
Jess Bees
7a1dc4e394 update dist files 2022-03-23 14:56:28 -04:00
Jess Bees
92f6725bee Only emit telemetry when the emit_telemetry input is truthy 2022-03-23 14:40:57 -04:00
Jess Bees
e1279a88ef Don't call the telemetry pre-hook entrypoint 2022-03-23 14:22:16 -04:00
Mingzi
479e82243a Merge pull request #17 from paper-spa/main
Add release action
2022-02-07 13:42:46 -08:00
Mingzi
243ed8c2df Merge pull request #1 from paper-spa/add-release-plan
Add release action
2022-02-07 12:30:28 -08:00
yimysty
c2e0577d92 add all 2022-02-07 12:27:36 -08:00
18 changed files with 678 additions and 271 deletions

38
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
template: |
# Changelog
$CHANGES
See details of [all code changes](https://github.com/actions/deploy-pages/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
labels:
- 'infrastructure'
- 'automation'
- 'documentation'
- title: '🏎 Performance'
label: 'performance'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
version-resolver:
major:
labels:
- 'type: breaking'
minor:
labels:
- 'type: enhancement'
patch:
labels:
- 'type: bug'
- 'type: maintenance'
- 'type: documentation'
default: patch

View File

@@ -37,8 +37,13 @@ jobs:
- name: Compare the expected and actual dist/ directories
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. See status below:"
echo "Detected uncommitted changes after build in dist folder. See status below:"
git diff
exit 1
fi
if [ "$(git diff --ignore-space-at-eol pre/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build in pre folder. See status below:"
git diff
exit 1
fi
id: diff

70
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '40 0 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -1,7 +1,7 @@
name: Release new action version
on:
release:
types: [released]
types: [edited]
workflow_dispatch:
inputs:
TAG_NAME:

View File

@@ -15,10 +15,14 @@ jobs:
- name: Set Node.JS
uses: actions/setup-node@v2
with:
node-version: 12.x
node-version: 16.x
- name: Install dependencies
run: npm install
- name: Run tests
run: npm run test
# Drafts your next Release notes as Pull Requests are merged into "main"
- uses: release-drafter/release-drafter@v5
if: github.ref_name == 'main'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
CODEOWNERS Normal file
View File

@@ -0,0 +1 @@
* @actions/pages

View File

@@ -1,17 +1,73 @@
# Deploy-Pages
# deploy-pages
This deploys artifacts to GitHub Pages.
This action is used to deploy [Actions artifacts][artifacts] to GitHub Pages.
# Scope
## Scope
⚠️ Official support for building Pages with Actions is in public beta at the moment. The scope is currently limited to **public repositories only**.
⚠️ Official support for building Pages with Actions is in public beta at the moment.
# Usage
## Usage
See [action.yml](action.yml)
See [action.yml](action.yml) for the various `inputs` this action supports.
<!-- TODO: document custom workflow -->
For examples that make use of this action, check out our [starter-workflows][starter-workflows] in a variety of frameworks.
# License
This action expects an artifact named `github-pages` to have been created prior to execution. This is done automatically using [`actions/upload-pages-artifact`][upload-pages-artifact].
We recommend this action to be used in a dedicated job:
```yaml
jobs:
# Build job
build:
# <Not provided for brevity>
# At a minimum this job should upload artifacts using actions/upload-pages-artifact
# Deploy job
deploy:
# Add a dependency to the build job
needs: build
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
# Specify runner + deployment step
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
```
## 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.
2. The job that executes the deployment must at minimum have the following permissions:
- `pages: write`
- `id-token: write`
3. The deployment should target the `github-pages` environment (you may use a different environment name if needed, but this is not recommended.)
4. If your Pages site is using a source branch, the deployment must originate from this source branch unless [your environment is protected][environment-protection] in which case the environment protection rules take precedence over the source branch rule
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 do it by default for you)
## License
The scripts and documentation in this project are released under the [MIT License](LICENSE).
<!-- references -->
[starter-workflows]: https://github.com/actions/starter-workflows/tree/main/pages
[upload-pages-artifact]: https://github.com/actions/upload-pages-artifact
[artifacts]: https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts
[environment-protection]: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#environment-protection-rules

View File

@@ -1,10 +1,14 @@
name: 'Deploy to GitHub Pages'
description: 'A GitHub Action to deploy an artifact to GitHub Pages'
name: 'Deploy GitHub Pages site'
description: 'A GitHub Action to deploy an artifact as a GitHub Pages site'
author: 'GitHub'
runs:
using: 'node16'
main: 'dist/index.js'
pre: 'pre/index.js'
inputs:
emit_telemetry:
description: 'Should this action only emit build telemetry instead of deploying the build artifact?'
required: false
default: "false"
token:
description: 'GitHub token'
default: ${{ github.token }}
@@ -18,9 +22,13 @@ inputs:
required: false
default: "10"
reporting_interval:
description: 'Time in milliseconds between two deployment status report (default: 1 second)'
description: 'Time in milliseconds between two deployment status report (default: 5 seconds)'
required: false
default: "1000"
default: "5000"
artifact_name:
description: 'Name of the artifact to deploy'
required: false
default: "github-pages"
outputs:
page_url:
description: 'URL to deployed Github Pages'
description: 'URL to deployed GitHub Pages'

291
dist/index.js vendored
View File

@@ -5068,7 +5068,7 @@ events.forEach(function (event) {
// Error types with codes
var RedirectionError = createErrorType(
"ERR_FR_REDIRECTION_FAILURE",
""
"Redirected request failed"
);
var TooManyRedirectsError = createErrorType(
"ERR_FR_TOO_MANY_REDIRECTS",
@@ -5219,10 +5219,16 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
// Stops a timeout from triggering
function clearTimer() {
// Clear the timeout
if (self._timeout) {
clearTimeout(self._timeout);
self._timeout = null;
}
// Clean up all attached listeners
self.removeListener("abort", clearTimer);
self.removeListener("error", clearTimer);
self.removeListener("response", clearTimer);
if (callback) {
self.removeListener("timeout", callback);
}
@@ -5246,8 +5252,9 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
// Clean up on events
this.on("socket", destroyOnTimeout);
this.once("response", clearTimer);
this.once("error", clearTimer);
this.on("abort", clearTimer);
this.on("error", clearTimer);
this.on("response", clearTimer);
return this;
};
@@ -5379,84 +5386,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
// the user agent MAY automatically redirect its request to the URI
// referenced by the Location field value,
// even if the specific status code is not understood.
// If the response is not a redirect; return it as-is
var location = response.headers.location;
if (location && this._options.followRedirects !== false &&
statusCode >= 300 && statusCode < 400) {
// Abort the current request
abortRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();
// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
this.emit("error", new TooManyRedirectsError());
return;
}
// RFC7231§6.4: Automatic redirection needs to done with
// care for methods not known to be safe, […]
// RFC7231§6.4.23: For historical reasons, a user agent MAY change
// the request method from POST to GET for the subsequent request.
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
// the server is redirecting the user agent to a different resource […]
// A user agent can perform a retrieval request targeting that URI
// (a GET or HEAD request if using HTTP) […]
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
this._options.method = "GET";
// Drop a possible entity and headers related to it
this._requestBodyBuffers = [];
removeMatchingHeaders(/^content-/i, this._options.headers);
}
// Drop the Host header, as the redirect might lead to a different host
var previousHostName = removeMatchingHeaders(/^host$/i, this._options.headers) ||
url.parse(this._currentUrl).hostname;
// Create the redirected request
var redirectUrl = url.resolve(this._currentUrl, location);
debug("redirecting to", redirectUrl);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
// Drop the Authorization header if redirecting to another host
if (redirectUrlParts.hostname !== previousHostName) {
removeMatchingHeaders(/^authorization$/i, this._options.headers);
}
// Evaluate the beforeRedirect callback
if (typeof this._options.beforeRedirect === "function") {
var responseDetails = { headers: response.headers };
try {
this._options.beforeRedirect.call(null, this._options, responseDetails);
}
catch (err) {
this.emit("error", err);
return;
}
this._sanitizeOptions(this._options);
}
// Perform the redirected request
try {
this._performRequest();
}
catch (cause) {
var error = new RedirectionError("Redirected request failed: " + cause.message);
error.cause = cause;
this.emit("error", error);
}
}
else {
// The response is not a redirect; return it as-is
if (!location || this._options.followRedirects === false ||
statusCode < 300 || statusCode >= 400) {
response.responseUrl = this._currentUrl;
response.redirects = this._redirects;
this.emit("response", response);
// Clean up
this._requestBodyBuffers = [];
return;
}
// The response is a redirect, so abort the current request
abortRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();
// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
this.emit("error", new TooManyRedirectsError());
return;
}
// RFC7231§6.4: Automatic redirection needs to done with
// care for methods not known to be safe, […]
// RFC7231§6.4.23: For historical reasons, a user agent MAY change
// the request method from POST to GET for the subsequent request.
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
// the server is redirecting the user agent to a different resource […]
// A user agent can perform a retrieval request targeting that URI
// (a GET or HEAD request if using HTTP) […]
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
this._options.method = "GET";
// Drop a possible entity and headers related to it
this._requestBodyBuffers = [];
removeMatchingHeaders(/^content-/i, this._options.headers);
}
// Drop the Host header, as the redirect might lead to a different host
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
// If the redirect is relative, carry over the host of the last request
var currentUrlParts = url.parse(this._currentUrl);
var currentHost = currentHostHeader || currentUrlParts.host;
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
url.format(Object.assign(currentUrlParts, { host: currentHost }));
// Determine the URL of the redirection
var redirectUrl;
try {
redirectUrl = url.resolve(currentUrl, location);
}
catch (cause) {
this.emit("error", new RedirectionError(cause));
return;
}
// Create the redirected request
debug("redirecting to", redirectUrl);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
// Drop confidential headers when redirecting to a less secure protocol
// or to a different domain that is not a superdomain
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
redirectUrlParts.protocol !== "https:" ||
redirectUrlParts.host !== currentHost &&
!isSubdomain(redirectUrlParts.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}
// Evaluate the beforeRedirect callback
if (typeof this._options.beforeRedirect === "function") {
var responseDetails = { headers: response.headers };
try {
this._options.beforeRedirect.call(null, this._options, responseDetails);
}
catch (err) {
this.emit("error", err);
return;
}
this._sanitizeOptions(this._options);
}
// Perform the redirected request
try {
this._performRequest();
}
catch (cause) {
this.emit("error", new RedirectionError(cause));
}
};
@@ -5560,13 +5584,20 @@ function removeMatchingHeaders(regex, headers) {
delete headers[header];
}
}
return lastValue;
return (lastValue === null || typeof lastValue === "undefined") ?
undefined : String(lastValue).trim();
}
function createErrorType(code, defaultMessage) {
function CustomError(message) {
function CustomError(cause) {
Error.captureStackTrace(this, this.constructor);
this.message = message || defaultMessage;
if (!cause) {
this.message = defaultMessage;
}
else {
this.message = defaultMessage + ": " + cause.message;
this.cause = cause;
}
}
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
@@ -5583,6 +5614,11 @@ function abortRequest(request) {
request.abort();
}
function isSubdomain(subdomain, domain) {
const dot = subdomain.length - domain.length - 1;
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
}
// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;
@@ -7021,7 +7057,9 @@ function getRequiredVars() {
buildVersion: process.env.GITHUB_SHA,
buildActor: process.env.GITHUB_ACTOR,
actionsId: process.env.GITHUB_ACTION,
githubToken: core.getInput('token')
githubToken: core.getInput('token'),
githubApiUrl: process.env.GITHUB_API_URL ?? 'https://api.github.com',
artifactName: core.getInput('artifact_name') ?? 'github-pages'
}
}
@@ -7069,6 +7107,8 @@ class Deployment {
this.workflowRun = context.workflowRun
this.requestedDeployment = false
this.deploymentInfo = null
this.githubApiUrl = context.githubApiUrl
this.artifactName = context.artifactName
}
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
@@ -7077,7 +7117,7 @@ class Deployment {
try {
core.info(`Actor: ${this.buildActor}`)
core.info(`Action ID: ${this.actionsId}`)
const pagesDeployEndpoint = `https://api.github.com/repos/${this.repositoryNwo}/pages/deployment`
const pagesDeployEndpoint = `${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment`
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
core.info(`Artifact URL: ${artifactExgUrl}`)
const {data} = await axios.get(artifactExgUrl, {
@@ -7087,10 +7127,12 @@ class Deployment {
}
})
core.info(JSON.stringify(data))
if (data.value.length == 0) {
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.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 artifactUrl = `${data.value[0].url}&%24expand=SignedContent`
const artifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
const payload = {
artifact_url: artifactUrl,
pages_build_version: this.buildVersion,
@@ -7106,15 +7148,41 @@ class Deployment {
})
this.requestedDeployment = true
core.info(`Created deployment for ${this.buildVersion}`)
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
} catch (error) {
core.info(`Failed to create deployment for ${this.buildVersion}.`)
if (error.response && error.response.data) {
core.info(JSON.stringify(error.response.data))
if (response && response.data) {
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
}
} catch (error) {
core.info(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.response.status}) with build version ${this.buildVersion}. `
if (error.response.status == 400) {
let message = ""
if (error.response.data && error.response.data.message) {
message = error.response.data.message
} else {
message = error.response.data
}
errorMessage += `Responded with: ${message}`
}
else if (error.response.status == 403) {
errorMessage += `Ensure GITHUB_TOKEN has permission "pages: write".`
} else if (error.response.status == 404) {
errorMessage += `Ensure GitHub Pages has been enabled.`
}
else if (error.response.status >= 500) {
errorMessage += `Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.`
}
throw errorMessage
} else {
throw error
}
core.setFailed(error)
throw error
}
}
@@ -7123,11 +7191,11 @@ class Deployment {
try {
const statusUrl = this.deploymentInfo != null ?
this.deploymentInfo["status_url"] :
`https://api.github.com/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
`${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
core.setOutput('page_url', this.deploymentInfo != null ? this.deploymentInfo["page_url"] : "")
const timeout = core.getInput('timeout')
const timeout = Number(core.getInput('timeout'))
const reportingInterval = Number(core.getInput('reporting_interval'))
const maxErrorCount = core.getInput('error_count')
const maxErrorCount = Number(core.getInput('error_count'))
var startTime = Date.now()
var errorCount = 0
@@ -7182,12 +7250,13 @@ class Deployment {
core.setFailed('Failed with status code: ' + res.status)
break
}
}
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
}
}
} catch (error) {
core.setFailed(error)
@@ -7227,7 +7296,7 @@ const {Deployment} = __nccwpck_require__(2877)
async function emitTelemetry() {
// All variables we need from the runtime are set in the Deployment constructor
const deployment = new Deployment()
const telemetryUrl = `https://api.github.com/repos/${deployment.repositoryNwo}/pages/telemetry`
const telemetryUrl = `${deployment.githubApiUrl}/repos/${deployment.repositoryNwo}/pages/telemetry`
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
await axios
.post(
@@ -7437,14 +7506,14 @@ const deployment = new Deployment()
async function cancelHandler(evtOrExitCodeOrError) {
try {
if (deployment.requestedDeployment) {
const pagesCancelDeployEndpoint = `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployment/cancel/${process.env.GITHUB_SHA}`
const pagesCancelDeployEndpoint = `${deployment.githubApiUrl}/repos/${process.env.GITHUB_REPOSITORY}/pages/deployment/cancel/${process.env.GITHUB_SHA}`
await axios.put(
pagesCancelDeployEndpoint,
{},
{
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
Authorization: `Bearer ${deployment.githubToken}`,
'Content-type': 'application/json'
}
}
@@ -7452,14 +7521,21 @@ async function cancelHandler(evtOrExitCodeOrError) {
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
}
} catch (e) {
console.info('Deployment cancellation failed', e)
console.log('Deployment cancellation failed', e)
}
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
}
async function main() {
let idToken = ""
try {
idToken = await core.getIDToken()
} catch (error) {
console.log(error)
core.setFailed(`Ensure GITHUB_TOKEN has permission "idToken: write".`)
return
}
try {
const idToken = await core.getIDToken()
await deployment.create(idToken)
await deployment.check()
} catch (error) {
@@ -7472,7 +7548,12 @@ process.on('SIGINT', cancelHandler)
process.on('SIGTERM', cancelHandler)
// Main
main().then(() => __nccwpck_require__(9557))
const emitTelemetry = core.getInput("emit_telemetry")
if (emitTelemetry === "true") {
__nccwpck_require__(9557)
} else {
main()
}
})();

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

45
package-lock.json generated
View File

@@ -4211,9 +4211,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"funding": [
{
"type": "individual",
@@ -5975,9 +5975,9 @@
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/minipass": {
"version": "3.1.5",
@@ -7123,6 +7123,20 @@
"is-typedarray": "^1.0.0"
}
},
"node_modules/typescript": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
"dev": true,
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -10546,9 +10560,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
},
"form-data": {
"version": "3.0.1",
@@ -11859,9 +11873,9 @@
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"minipass": {
"version": "3.1.5",
@@ -12709,6 +12723,13 @@
"is-typedarray": "^1.0.0"
}
},
"typescript": {
"version": "4.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz",
"integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==",
"dev": true,
"peer": true
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",

View File

@@ -5068,7 +5068,7 @@ events.forEach(function (event) {
// Error types with codes
var RedirectionError = createErrorType(
"ERR_FR_REDIRECTION_FAILURE",
""
"Redirected request failed"
);
var TooManyRedirectsError = createErrorType(
"ERR_FR_TOO_MANY_REDIRECTS",
@@ -5219,10 +5219,16 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
// Stops a timeout from triggering
function clearTimer() {
// Clear the timeout
if (self._timeout) {
clearTimeout(self._timeout);
self._timeout = null;
}
// Clean up all attached listeners
self.removeListener("abort", clearTimer);
self.removeListener("error", clearTimer);
self.removeListener("response", clearTimer);
if (callback) {
self.removeListener("timeout", callback);
}
@@ -5246,8 +5252,9 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
// Clean up on events
this.on("socket", destroyOnTimeout);
this.once("response", clearTimer);
this.once("error", clearTimer);
this.on("abort", clearTimer);
this.on("error", clearTimer);
this.on("response", clearTimer);
return this;
};
@@ -5379,84 +5386,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
// the user agent MAY automatically redirect its request to the URI
// referenced by the Location field value,
// even if the specific status code is not understood.
// If the response is not a redirect; return it as-is
var location = response.headers.location;
if (location && this._options.followRedirects !== false &&
statusCode >= 300 && statusCode < 400) {
// Abort the current request
abortRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();
// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
this.emit("error", new TooManyRedirectsError());
return;
}
// RFC7231§6.4: Automatic redirection needs to done with
// care for methods not known to be safe, […]
// RFC7231§6.4.23: For historical reasons, a user agent MAY change
// the request method from POST to GET for the subsequent request.
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
// the server is redirecting the user agent to a different resource […]
// A user agent can perform a retrieval request targeting that URI
// (a GET or HEAD request if using HTTP) […]
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
this._options.method = "GET";
// Drop a possible entity and headers related to it
this._requestBodyBuffers = [];
removeMatchingHeaders(/^content-/i, this._options.headers);
}
// Drop the Host header, as the redirect might lead to a different host
var previousHostName = removeMatchingHeaders(/^host$/i, this._options.headers) ||
url.parse(this._currentUrl).hostname;
// Create the redirected request
var redirectUrl = url.resolve(this._currentUrl, location);
debug("redirecting to", redirectUrl);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
// Drop the Authorization header if redirecting to another host
if (redirectUrlParts.hostname !== previousHostName) {
removeMatchingHeaders(/^authorization$/i, this._options.headers);
}
// Evaluate the beforeRedirect callback
if (typeof this._options.beforeRedirect === "function") {
var responseDetails = { headers: response.headers };
try {
this._options.beforeRedirect.call(null, this._options, responseDetails);
}
catch (err) {
this.emit("error", err);
return;
}
this._sanitizeOptions(this._options);
}
// Perform the redirected request
try {
this._performRequest();
}
catch (cause) {
var error = new RedirectionError("Redirected request failed: " + cause.message);
error.cause = cause;
this.emit("error", error);
}
}
else {
// The response is not a redirect; return it as-is
if (!location || this._options.followRedirects === false ||
statusCode < 300 || statusCode >= 400) {
response.responseUrl = this._currentUrl;
response.redirects = this._redirects;
this.emit("response", response);
// Clean up
this._requestBodyBuffers = [];
return;
}
// The response is a redirect, so abort the current request
abortRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();
// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
this.emit("error", new TooManyRedirectsError());
return;
}
// RFC7231§6.4: Automatic redirection needs to done with
// care for methods not known to be safe, […]
// RFC7231§6.4.23: For historical reasons, a user agent MAY change
// the request method from POST to GET for the subsequent request.
if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" ||
// RFC7231§6.4.4: The 303 (See Other) status code indicates that
// the server is redirecting the user agent to a different resource […]
// A user agent can perform a retrieval request targeting that URI
// (a GET or HEAD request if using HTTP) […]
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
this._options.method = "GET";
// Drop a possible entity and headers related to it
this._requestBodyBuffers = [];
removeMatchingHeaders(/^content-/i, this._options.headers);
}
// Drop the Host header, as the redirect might lead to a different host
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
// If the redirect is relative, carry over the host of the last request
var currentUrlParts = url.parse(this._currentUrl);
var currentHost = currentHostHeader || currentUrlParts.host;
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
url.format(Object.assign(currentUrlParts, { host: currentHost }));
// Determine the URL of the redirection
var redirectUrl;
try {
redirectUrl = url.resolve(currentUrl, location);
}
catch (cause) {
this.emit("error", new RedirectionError(cause));
return;
}
// Create the redirected request
debug("redirecting to", redirectUrl);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
// Drop confidential headers when redirecting to a less secure protocol
// or to a different domain that is not a superdomain
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
redirectUrlParts.protocol !== "https:" ||
redirectUrlParts.host !== currentHost &&
!isSubdomain(redirectUrlParts.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}
// Evaluate the beforeRedirect callback
if (typeof this._options.beforeRedirect === "function") {
var responseDetails = { headers: response.headers };
try {
this._options.beforeRedirect.call(null, this._options, responseDetails);
}
catch (err) {
this.emit("error", err);
return;
}
this._sanitizeOptions(this._options);
}
// Perform the redirected request
try {
this._performRequest();
}
catch (cause) {
this.emit("error", new RedirectionError(cause));
}
};
@@ -5560,13 +5584,20 @@ function removeMatchingHeaders(regex, headers) {
delete headers[header];
}
}
return lastValue;
return (lastValue === null || typeof lastValue === "undefined") ?
undefined : String(lastValue).trim();
}
function createErrorType(code, defaultMessage) {
function CustomError(message) {
function CustomError(cause) {
Error.captureStackTrace(this, this.constructor);
this.message = message || defaultMessage;
if (!cause) {
this.message = defaultMessage;
}
else {
this.message = defaultMessage + ": " + cause.message;
this.cause = cause;
}
}
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
@@ -5583,6 +5614,11 @@ function abortRequest(request) {
request.abort();
}
function isSubdomain(subdomain, domain) {
const dot = subdomain.length - domain.length - 1;
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
}
// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;
@@ -7021,7 +7057,9 @@ function getRequiredVars() {
buildVersion: process.env.GITHUB_SHA,
buildActor: process.env.GITHUB_ACTOR,
actionsId: process.env.GITHUB_ACTION,
githubToken: core.getInput('token')
githubToken: core.getInput('token'),
githubApiUrl: process.env.GITHUB_API_URL ?? 'https://api.github.com',
artifactName: core.getInput('artifact_name') ?? 'github-pages'
}
}
@@ -7069,6 +7107,8 @@ class Deployment {
this.workflowRun = context.workflowRun
this.requestedDeployment = false
this.deploymentInfo = null
this.githubApiUrl = context.githubApiUrl
this.artifactName = context.artifactName
}
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
@@ -7077,7 +7117,7 @@ class Deployment {
try {
core.info(`Actor: ${this.buildActor}`)
core.info(`Action ID: ${this.actionsId}`)
const pagesDeployEndpoint = `https://api.github.com/repos/${this.repositoryNwo}/pages/deployment`
const pagesDeployEndpoint = `${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment`
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
core.info(`Artifact URL: ${artifactExgUrl}`)
const {data} = await axios.get(artifactExgUrl, {
@@ -7087,10 +7127,12 @@ class Deployment {
}
})
core.info(JSON.stringify(data))
if (data.value.length == 0) {
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.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 artifactUrl = `${data.value[0].url}&%24expand=SignedContent`
const artifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
const payload = {
artifact_url: artifactUrl,
pages_build_version: this.buildVersion,
@@ -7106,15 +7148,41 @@ class Deployment {
})
this.requestedDeployment = true
core.info(`Created deployment for ${this.buildVersion}`)
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
} catch (error) {
core.info(`Failed to create deployment for ${this.buildVersion}.`)
if (error.response && error.response.data) {
core.info(JSON.stringify(error.response.data))
if (response && response.data) {
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
}
} catch (error) {
core.info(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.response.status}) with build version ${this.buildVersion}. `
if (error.response.status == 400) {
let message = ""
if (error.response.data && error.response.data.message) {
message = error.response.data.message
} else {
message = error.response.data
}
errorMessage += `Responded with: ${message}`
}
else if (error.response.status == 403) {
errorMessage += `Ensure GITHUB_TOKEN has permission "pages: write".`
} else if (error.response.status == 404) {
errorMessage += `Ensure GitHub Pages has been enabled.`
}
else if (error.response.status >= 500) {
errorMessage += `Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.`
}
throw errorMessage
} else {
throw error
}
core.setFailed(error)
throw error
}
}
@@ -7123,11 +7191,11 @@ class Deployment {
try {
const statusUrl = this.deploymentInfo != null ?
this.deploymentInfo["status_url"] :
`https://api.github.com/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
`${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
core.setOutput('page_url', this.deploymentInfo != null ? this.deploymentInfo["page_url"] : "")
const timeout = core.getInput('timeout')
const timeout = Number(core.getInput('timeout'))
const reportingInterval = Number(core.getInput('reporting_interval'))
const maxErrorCount = core.getInput('error_count')
const maxErrorCount = Number(core.getInput('error_count'))
var startTime = Date.now()
var errorCount = 0
@@ -7182,12 +7250,13 @@ class Deployment {
core.setFailed('Failed with status code: ' + res.status)
break
}
}
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
}
}
} catch (error) {
core.setFailed(error)
@@ -7227,7 +7296,7 @@ const {Deployment} = __nccwpck_require__(2877)
async function emitTelemetry() {
// All variables we need from the runtime are set in the Deployment constructor
const deployment = new Deployment()
const telemetryUrl = `https://api.github.com/repos/${deployment.repositoryNwo}/pages/telemetry`
const telemetryUrl = `${deployment.githubApiUrl}/repos/${deployment.repositoryNwo}/pages/telemetry`
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
await axios
.post(

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,9 @@ function getRequiredVars() {
buildVersion: process.env.GITHUB_SHA,
buildActor: process.env.GITHUB_ACTOR,
actionsId: process.env.GITHUB_ACTION,
githubToken: core.getInput('token')
githubToken: core.getInput('token'),
githubApiUrl: process.env.GITHUB_API_URL ?? 'https://api.github.com',
artifactName: core.getInput('artifact_name') ?? 'github-pages'
}
}

View File

@@ -25,6 +25,8 @@ class Deployment {
this.workflowRun = context.workflowRun
this.requestedDeployment = false
this.deploymentInfo = null
this.githubApiUrl = context.githubApiUrl
this.artifactName = context.artifactName
}
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
@@ -33,7 +35,7 @@ class Deployment {
try {
core.info(`Actor: ${this.buildActor}`)
core.info(`Action ID: ${this.actionsId}`)
const pagesDeployEndpoint = `https://api.github.com/repos/${this.repositoryNwo}/pages/deployment`
const pagesDeployEndpoint = `${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment`
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
core.info(`Artifact URL: ${artifactExgUrl}`)
const {data} = await axios.get(artifactExgUrl, {
@@ -43,10 +45,12 @@ class Deployment {
}
})
core.info(JSON.stringify(data))
if (data.value.length == 0) {
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.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 artifactUrl = `${data.value[0].url}&%24expand=SignedContent`
const artifactUrl = `${artifactRawUrl}&%24expand=SignedContent`
const payload = {
artifact_url: artifactUrl,
pages_build_version: this.buildVersion,
@@ -62,15 +66,41 @@ class Deployment {
})
this.requestedDeployment = true
core.info(`Created deployment for ${this.buildVersion}`)
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
} catch (error) {
core.info(`Failed to create deployment for ${this.buildVersion}.`)
if (error.response && error.response.data) {
core.info(JSON.stringify(error.response.data))
if (response && response.data) {
core.info(JSON.stringify(response.data))
this.deploymentInfo = response.data
}
} catch (error) {
core.info(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.response.status}) with build version ${this.buildVersion}. `
if (error.response.status == 400) {
let message = ""
if (error.response.data && error.response.data.message) {
message = error.response.data.message
} else {
message = error.response.data
}
errorMessage += `Responded with: ${message}`
}
else if (error.response.status == 403) {
errorMessage += `Ensure GITHUB_TOKEN has permission "pages: write".`
} else if (error.response.status == 404) {
errorMessage += `Ensure GitHub Pages has been enabled.`
}
else if (error.response.status >= 500) {
errorMessage += `Server error, is githubstatus.com reporting a Pages outage? Please re-run the deployment at a later time.`
}
throw errorMessage
} else {
throw error
}
core.setFailed(error)
throw error
}
}
@@ -79,11 +109,11 @@ class Deployment {
try {
const statusUrl = this.deploymentInfo != null ?
this.deploymentInfo["status_url"] :
`https://api.github.com/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
`${this.githubApiUrl}/repos/${this.repositoryNwo}/pages/deployment/status/${process.env['GITHUB_SHA']}`
core.setOutput('page_url', this.deploymentInfo != null ? this.deploymentInfo["page_url"] : "")
const timeout = core.getInput('timeout')
const timeout = Number(core.getInput('timeout'))
const reportingInterval = Number(core.getInput('reporting_interval'))
const maxErrorCount = core.getInput('error_count')
const maxErrorCount = Number(core.getInput('error_count'))
var startTime = Date.now()
var errorCount = 0
@@ -138,12 +168,13 @@ class Deployment {
core.setFailed('Failed with status code: ' + res.status)
break
}
}
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
// Handle timeout
if (Date.now() - startTime >= timeout) {
core.info('Timeout reached, aborting!')
core.setFailed('Timeout reached, aborting!')
return
}
}
} catch (error) {
core.setFailed(error)

View File

@@ -17,14 +17,14 @@ const deployment = new Deployment()
async function cancelHandler(evtOrExitCodeOrError) {
try {
if (deployment.requestedDeployment) {
const pagesCancelDeployEndpoint = `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployment/cancel/${process.env.GITHUB_SHA}`
const pagesCancelDeployEndpoint = `${deployment.githubApiUrl}/repos/${process.env.GITHUB_REPOSITORY}/pages/deployment/cancel/${process.env.GITHUB_SHA}`
await axios.put(
pagesCancelDeployEndpoint,
{},
{
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
Authorization: `Bearer ${deployment.githubToken}`,
'Content-type': 'application/json'
}
}
@@ -32,14 +32,21 @@ async function cancelHandler(evtOrExitCodeOrError) {
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
}
} catch (e) {
console.info('Deployment cancellation failed', e)
console.log('Deployment cancellation failed', e)
}
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
}
async function main() {
let idToken = ""
try {
idToken = await core.getIDToken()
} catch (error) {
console.log(error)
core.setFailed(`Ensure GITHUB_TOKEN has permission "idToken: write".`)
return
}
try {
const idToken = await core.getIDToken()
await deployment.create(idToken)
await deployment.check()
} catch (error) {
@@ -52,4 +59,9 @@ process.on('SIGINT', cancelHandler)
process.on('SIGTERM', cancelHandler)
// Main
main().then(() => require('./pre'))
const emitTelemetry = core.getInput("emit_telemetry")
if (emitTelemetry === "true") {
require('./pre')
} else {
main()
}

View File

@@ -55,6 +55,14 @@ describe('create', () => {
process.env.GITHUB_ACTOR = 'monalisa'
process.env.GITHUB_ACTION = '__monalisa/octocat'
process.env.GITHUB_ACTION_PATH = 'something'
jest.spyOn(core, 'getInput').mockImplementation(param => {
switch (param) {
case 'artifact_name':
return 'github-pages'
case 'token':
return process.env.GITHUB_TOKEN
}
})
jest.spyOn(core, 'setOutput').mockImplementation(param => {
return param
@@ -75,7 +83,7 @@ describe('create', () => {
const fakeJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
const scope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://fake-artifact.com' }] })
.reply(200, { value: [ {url: 'https://another-artifact.com', name: 'another-artifact'}, { url: 'https://fake-artifact.com', name: 'github-pages' }] })
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
axios.post = jest.fn().mockResolvedValue('test')
@@ -94,7 +102,7 @@ describe('create', () => {
{
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: 'Bearer ',
Authorization: `Bearer gha-token`,
'Content-type': 'application/json'
}
}
@@ -112,7 +120,7 @@ describe('create', () => {
process.env.GITHUB_SHA = 'invalid-build-version'
const scope = nock(`http://my-url`)
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
.reply(200, { value: [{ url: 'https://invalid-artifact.com' }] })
.reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] })
axios.post = jest.fn().mockRejectedValue({
status: 400
@@ -161,6 +169,7 @@ describe('check', () => {
process.env.GITHUB_ACTOR = 'monalisa'
process.env.GITHUB_ACTION = '__monalisa/octocat'
process.env.GITHUB_ACTION_PATH = 'something'
process.env.ARTIFACT_NAME = 'github-pages'
jest.spyOn(core, 'setOutput').mockImplementation(param => {
return param
@@ -209,7 +218,7 @@ describe('check', () => {
`https://api.github.com/repos/${repositoryNwo}/pages/deployment/status/${buildVersion}`,
{
headers: {
Authorization: 'token '
Authorization: 'token gha-token'
}
}
)

View File

@@ -21,7 +21,7 @@ const {Deployment} = require('./deployment')
async function emitTelemetry() {
// All variables we need from the runtime are set in the Deployment constructor
const deployment = new Deployment()
const telemetryUrl = `https://api.github.com/repos/${deployment.repositoryNwo}/pages/telemetry`
const telemetryUrl = `${deployment.githubApiUrl}/repos/${deployment.repositoryNwo}/pages/telemetry`
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
await axios
.post(