mirror of
https://github.com/actions/deploy-pages.git
synced 2026-03-28 17:04:53 +00:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e490850a64 | ||
|
|
5743579482 | ||
|
|
5fd268dcdd | ||
|
|
fbb46fa661 | ||
|
|
eaaccf9fc5 | ||
|
|
8daa1e0ead | ||
|
|
99f9079292 | ||
|
|
06d025f427 | ||
|
|
7f629c4ce0 | ||
|
|
35e615a00c | ||
|
|
462df77e16 | ||
|
|
9ebae0d26b | ||
|
|
d0b379e44d | ||
|
|
225abf7840 | ||
|
|
1f0422c0df | ||
|
|
85b0d1617e | ||
|
|
3e976523d7 | ||
|
|
38e42fe573 | ||
|
|
44ea2ec0c1 | ||
|
|
b4e423ab11 | ||
|
|
58b7d54130 | ||
|
|
974e2a6ded | ||
|
|
f5d172a561 | ||
|
|
33bba0fd45 | ||
|
|
1f18c7a3ba | ||
|
|
86843fdbb5 | ||
|
|
4d0af465be | ||
|
|
bea9114e88 | ||
|
|
41f0a8ab89 | ||
|
|
b918908973 | ||
|
|
1ae5d2452b | ||
|
|
e2219a89b1 | ||
|
|
72b116b825 | ||
|
|
11a13019c2 | ||
|
|
801d74db09 | ||
|
|
64c69a5fdf | ||
|
|
03d70e4a19 | ||
|
|
64e33b2a0d | ||
|
|
c3d24faf75 | ||
|
|
2b0c6eaf67 | ||
|
|
358b034ef8 | ||
|
|
13ef0cb0a0 | ||
|
|
2bf05927ae | ||
|
|
0745e9700c | ||
|
|
43dced9e8c | ||
|
|
fce105b3ea | ||
|
|
148e2ea9dd | ||
|
|
506f839b97 | ||
|
|
f7a158aceb | ||
|
|
ca23c7917e | ||
|
|
0c60998bd5 | ||
|
|
4154a47b87 | ||
|
|
17fd28439d | ||
|
|
0f19a8f78c | ||
|
|
595c840e2a | ||
|
|
57f2f8bd29 | ||
|
|
68c14dcd2c | ||
|
|
a7af90c328 | ||
|
|
ef910bd895 | ||
|
|
53f4e898cd | ||
|
|
62c650c70d | ||
|
|
eaf36f48c9 | ||
|
|
01f6ae5af2 | ||
|
|
82cb77089c | ||
|
|
ad36b7023a | ||
|
|
32b8b86ff0 | ||
|
|
a598b2af14 | ||
|
|
f511fa4665 | ||
|
|
0e157789db | ||
|
|
12940a5b99 | ||
|
|
6afc4f2884 | ||
|
|
a68b5a4ae1 | ||
|
|
171a8a05dd | ||
|
|
7a1dc4e394 | ||
|
|
92f6725bee | ||
|
|
e1279a88ef |
2
.github/release-drafter.yml
vendored
2
.github/release-drafter.yml
vendored
@@ -4,7 +4,7 @@ tag-template: 'v$RESOLVED_VERSION'
|
|||||||
template: |
|
template: |
|
||||||
# Changelog
|
# Changelog
|
||||||
$CHANGES
|
$CHANGES
|
||||||
See details of [all code changes](https://github.com/actions/jekyll-build-pages/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release
|
See details of [all code changes](https://github.com/actions/deploy-pages/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release
|
||||||
categories:
|
categories:
|
||||||
- title: '🚀 Features'
|
- title: '🚀 Features'
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
9
.github/workflows/check-dist.yml
vendored
9
.github/workflows/check-dist.yml
vendored
@@ -37,8 +37,13 @@ jobs:
|
|||||||
- name: Compare the expected and actual dist/ directories
|
- name: Compare the expected and actual dist/ directories
|
||||||
run: |
|
run: |
|
||||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
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
|
git diff
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
id: diff
|
|
||||||
|
|||||||
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
70
.github/workflows/codeql-analysis.yml
vendored
Normal 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
|
||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Set Node.JS
|
- name: Set Node.JS
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 12.x
|
node-version: 16.x
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|||||||
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @actions/pages
|
||||||
72
README.md
72
README.md
@@ -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).
|
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
|
||||||
|
|||||||
20
action.yml
20
action.yml
@@ -1,10 +1,14 @@
|
|||||||
name: 'Deploy to GitHub Pages'
|
name: 'Deploy GitHub Pages site'
|
||||||
description: 'A GitHub Action to deploy an artifact to GitHub Pages'
|
description: 'A GitHub Action to deploy an artifact as a GitHub Pages site'
|
||||||
|
author: 'GitHub'
|
||||||
runs:
|
runs:
|
||||||
using: 'node16'
|
using: 'node16'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
pre: 'pre/index.js'
|
|
||||||
inputs:
|
inputs:
|
||||||
|
emit_telemetry:
|
||||||
|
description: 'Should this action only emit build telemetry instead of deploying the build artifact?'
|
||||||
|
required: false
|
||||||
|
default: "false"
|
||||||
token:
|
token:
|
||||||
description: 'GitHub token'
|
description: 'GitHub token'
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
@@ -18,9 +22,13 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: "10"
|
default: "10"
|
||||||
reporting_interval:
|
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
|
required: false
|
||||||
default: "1000"
|
default: "5000"
|
||||||
|
artifact_name:
|
||||||
|
description: 'Name of the artifact to deploy'
|
||||||
|
required: false
|
||||||
|
default: "github-pages"
|
||||||
outputs:
|
outputs:
|
||||||
page_url:
|
page_url:
|
||||||
description: 'URL to deployed Github Pages'
|
description: 'URL to deployed GitHub Pages'
|
||||||
|
|||||||
291
dist/index.js
vendored
291
dist/index.js
vendored
@@ -5068,7 +5068,7 @@ events.forEach(function (event) {
|
|||||||
// Error types with codes
|
// Error types with codes
|
||||||
var RedirectionError = createErrorType(
|
var RedirectionError = createErrorType(
|
||||||
"ERR_FR_REDIRECTION_FAILURE",
|
"ERR_FR_REDIRECTION_FAILURE",
|
||||||
""
|
"Redirected request failed"
|
||||||
);
|
);
|
||||||
var TooManyRedirectsError = createErrorType(
|
var TooManyRedirectsError = createErrorType(
|
||||||
"ERR_FR_TOO_MANY_REDIRECTS",
|
"ERR_FR_TOO_MANY_REDIRECTS",
|
||||||
@@ -5219,10 +5219,16 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|||||||
|
|
||||||
// Stops a timeout from triggering
|
// Stops a timeout from triggering
|
||||||
function clearTimer() {
|
function clearTimer() {
|
||||||
|
// Clear the timeout
|
||||||
if (self._timeout) {
|
if (self._timeout) {
|
||||||
clearTimeout(self._timeout);
|
clearTimeout(self._timeout);
|
||||||
self._timeout = null;
|
self._timeout = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up all attached listeners
|
||||||
|
self.removeListener("abort", clearTimer);
|
||||||
|
self.removeListener("error", clearTimer);
|
||||||
|
self.removeListener("response", clearTimer);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
self.removeListener("timeout", callback);
|
self.removeListener("timeout", callback);
|
||||||
}
|
}
|
||||||
@@ -5246,8 +5252,9 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|||||||
|
|
||||||
// Clean up on events
|
// Clean up on events
|
||||||
this.on("socket", destroyOnTimeout);
|
this.on("socket", destroyOnTimeout);
|
||||||
this.once("response", clearTimer);
|
this.on("abort", clearTimer);
|
||||||
this.once("error", clearTimer);
|
this.on("error", clearTimer);
|
||||||
|
this.on("response", clearTimer);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@@ -5379,84 +5386,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|||||||
// the user agent MAY automatically redirect its request to the URI
|
// the user agent MAY automatically redirect its request to the URI
|
||||||
// referenced by the Location field value,
|
// referenced by the Location field value,
|
||||||
// even if the specific status code is not understood.
|
// 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;
|
var location = response.headers.location;
|
||||||
if (location && this._options.followRedirects !== false &&
|
if (!location || this._options.followRedirects === false ||
|
||||||
statusCode >= 300 && statusCode < 400) {
|
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.2–3: 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
|
|
||||||
response.responseUrl = this._currentUrl;
|
response.responseUrl = this._currentUrl;
|
||||||
response.redirects = this._redirects;
|
response.redirects = this._redirects;
|
||||||
this.emit("response", response);
|
this.emit("response", response);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
this._requestBodyBuffers = [];
|
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.2–3: 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];
|
delete headers[header];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lastValue;
|
return (lastValue === null || typeof lastValue === "undefined") ?
|
||||||
|
undefined : String(lastValue).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createErrorType(code, defaultMessage) {
|
function createErrorType(code, defaultMessage) {
|
||||||
function CustomError(message) {
|
function CustomError(cause) {
|
||||||
Error.captureStackTrace(this, this.constructor);
|
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 = new Error();
|
||||||
CustomError.prototype.constructor = CustomError;
|
CustomError.prototype.constructor = CustomError;
|
||||||
@@ -5583,6 +5614,11 @@ function abortRequest(request) {
|
|||||||
request.abort();
|
request.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSubdomain(subdomain, domain) {
|
||||||
|
const dot = subdomain.length - domain.length - 1;
|
||||||
|
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
||||||
|
}
|
||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
module.exports = wrap({ http: http, https: https });
|
module.exports = wrap({ http: http, https: https });
|
||||||
module.exports.wrap = wrap;
|
module.exports.wrap = wrap;
|
||||||
@@ -7021,7 +7057,9 @@ function getRequiredVars() {
|
|||||||
buildVersion: process.env.GITHUB_SHA,
|
buildVersion: process.env.GITHUB_SHA,
|
||||||
buildActor: process.env.GITHUB_ACTOR,
|
buildActor: process.env.GITHUB_ACTOR,
|
||||||
actionsId: process.env.GITHUB_ACTION,
|
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.workflowRun = context.workflowRun
|
||||||
this.requestedDeployment = false
|
this.requestedDeployment = false
|
||||||
this.deploymentInfo = null
|
this.deploymentInfo = null
|
||||||
|
this.githubApiUrl = context.githubApiUrl
|
||||||
|
this.artifactName = context.artifactName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||||
@@ -7077,7 +7117,7 @@ class Deployment {
|
|||||||
try {
|
try {
|
||||||
core.info(`Actor: ${this.buildActor}`)
|
core.info(`Actor: ${this.buildActor}`)
|
||||||
core.info(`Action ID: ${this.actionsId}`)
|
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`
|
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
|
||||||
core.info(`Artifact URL: ${artifactExgUrl}`)
|
core.info(`Artifact URL: ${artifactExgUrl}`)
|
||||||
const {data} = await axios.get(artifactExgUrl, {
|
const {data} = await axios.get(artifactExgUrl, {
|
||||||
@@ -7087,10 +7127,12 @@ class Deployment {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
core.info(JSON.stringify(data))
|
core.info(JSON.stringify(data))
|
||||||
if (data.value.length == 0) {
|
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.artifactName)?.url
|
||||||
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
|
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 = {
|
const payload = {
|
||||||
artifact_url: artifactUrl,
|
artifact_url: artifactUrl,
|
||||||
pages_build_version: this.buildVersion,
|
pages_build_version: this.buildVersion,
|
||||||
@@ -7106,15 +7148,41 @@ class Deployment {
|
|||||||
})
|
})
|
||||||
this.requestedDeployment = true
|
this.requestedDeployment = true
|
||||||
core.info(`Created deployment for ${this.buildVersion}`)
|
core.info(`Created deployment for ${this.buildVersion}`)
|
||||||
core.info(JSON.stringify(response.data))
|
if (response && response.data) {
|
||||||
this.deploymentInfo = response.data
|
core.info(JSON.stringify(response.data))
|
||||||
} catch (error) {
|
this.deploymentInfo = response.data
|
||||||
core.info(`Failed to create deployment for ${this.buildVersion}.`)
|
}
|
||||||
if (error.response && error.response.data) {
|
} catch (error) {
|
||||||
core.info(JSON.stringify(error.response.data))
|
|
||||||
|
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 {
|
try {
|
||||||
const statusUrl = this.deploymentInfo != null ?
|
const statusUrl = this.deploymentInfo != null ?
|
||||||
this.deploymentInfo["status_url"] :
|
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"] : "")
|
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 reportingInterval = Number(core.getInput('reporting_interval'))
|
||||||
const maxErrorCount = core.getInput('error_count')
|
const maxErrorCount = Number(core.getInput('error_count'))
|
||||||
var startTime = Date.now()
|
var startTime = Date.now()
|
||||||
var errorCount = 0
|
var errorCount = 0
|
||||||
|
|
||||||
@@ -7182,12 +7250,13 @@ class Deployment {
|
|||||||
core.setFailed('Failed with status code: ' + res.status)
|
core.setFailed('Failed with status code: ' + res.status)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Handle timeout
|
// Handle timeout
|
||||||
if (Date.now() - startTime >= timeout) {
|
if (Date.now() - startTime >= timeout) {
|
||||||
core.info('Timeout reached, aborting!')
|
core.info('Timeout reached, aborting!')
|
||||||
core.setFailed('Timeout reached, aborting!')
|
core.setFailed('Timeout reached, aborting!')
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error)
|
core.setFailed(error)
|
||||||
@@ -7227,7 +7296,7 @@ const {Deployment} = __nccwpck_require__(2877)
|
|||||||
async function emitTelemetry() {
|
async function emitTelemetry() {
|
||||||
// All variables we need from the runtime are set in the Deployment constructor
|
// All variables we need from the runtime are set in the Deployment constructor
|
||||||
const deployment = new Deployment()
|
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}`)
|
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
|
||||||
await axios
|
await axios
|
||||||
.post(
|
.post(
|
||||||
@@ -7437,14 +7506,14 @@ const deployment = new Deployment()
|
|||||||
async function cancelHandler(evtOrExitCodeOrError) {
|
async function cancelHandler(evtOrExitCodeOrError) {
|
||||||
try {
|
try {
|
||||||
if (deployment.requestedDeployment) {
|
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(
|
await axios.put(
|
||||||
pagesCancelDeployEndpoint,
|
pagesCancelDeployEndpoint,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/vnd.github.v3+json',
|
Accept: 'application/vnd.github.v3+json',
|
||||||
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
Authorization: `Bearer ${deployment.githubToken}`,
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7452,14 +7521,21 @@ async function cancelHandler(evtOrExitCodeOrError) {
|
|||||||
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
|
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.info('Deployment cancellation failed', e)
|
console.log('Deployment cancellation failed', e)
|
||||||
}
|
}
|
||||||
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
|
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
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 {
|
try {
|
||||||
const idToken = await core.getIDToken()
|
|
||||||
await deployment.create(idToken)
|
await deployment.create(idToken)
|
||||||
await deployment.check()
|
await deployment.check()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -7472,7 +7548,12 @@ process.on('SIGINT', cancelHandler)
|
|||||||
process.on('SIGTERM', cancelHandler)
|
process.on('SIGTERM', cancelHandler)
|
||||||
|
|
||||||
// Main
|
// 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
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
45
package-lock.json
generated
45
package-lock.json
generated
@@ -4211,9 +4211,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.14.4",
|
"version": "1.14.9",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||||
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
|
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -5975,9 +5975,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||||
},
|
},
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "3.1.5",
|
"version": "3.1.5",
|
||||||
@@ -7123,6 +7123,20 @@
|
|||||||
"is-typedarray": "^1.0.0"
|
"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": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
||||||
@@ -10546,9 +10560,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.14.4",
|
"version": "1.14.9",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||||
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
|
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -11859,9 +11873,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "3.1.5",
|
"version": "3.1.5",
|
||||||
@@ -12709,6 +12723,13 @@
|
|||||||
"is-typedarray": "^1.0.0"
|
"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": {
|
"unbox-primitive": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
||||||
|
|||||||
269
pre/index.js
269
pre/index.js
@@ -5068,7 +5068,7 @@ events.forEach(function (event) {
|
|||||||
// Error types with codes
|
// Error types with codes
|
||||||
var RedirectionError = createErrorType(
|
var RedirectionError = createErrorType(
|
||||||
"ERR_FR_REDIRECTION_FAILURE",
|
"ERR_FR_REDIRECTION_FAILURE",
|
||||||
""
|
"Redirected request failed"
|
||||||
);
|
);
|
||||||
var TooManyRedirectsError = createErrorType(
|
var TooManyRedirectsError = createErrorType(
|
||||||
"ERR_FR_TOO_MANY_REDIRECTS",
|
"ERR_FR_TOO_MANY_REDIRECTS",
|
||||||
@@ -5219,10 +5219,16 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|||||||
|
|
||||||
// Stops a timeout from triggering
|
// Stops a timeout from triggering
|
||||||
function clearTimer() {
|
function clearTimer() {
|
||||||
|
// Clear the timeout
|
||||||
if (self._timeout) {
|
if (self._timeout) {
|
||||||
clearTimeout(self._timeout);
|
clearTimeout(self._timeout);
|
||||||
self._timeout = null;
|
self._timeout = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up all attached listeners
|
||||||
|
self.removeListener("abort", clearTimer);
|
||||||
|
self.removeListener("error", clearTimer);
|
||||||
|
self.removeListener("response", clearTimer);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
self.removeListener("timeout", callback);
|
self.removeListener("timeout", callback);
|
||||||
}
|
}
|
||||||
@@ -5246,8 +5252,9 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|||||||
|
|
||||||
// Clean up on events
|
// Clean up on events
|
||||||
this.on("socket", destroyOnTimeout);
|
this.on("socket", destroyOnTimeout);
|
||||||
this.once("response", clearTimer);
|
this.on("abort", clearTimer);
|
||||||
this.once("error", clearTimer);
|
this.on("error", clearTimer);
|
||||||
|
this.on("response", clearTimer);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@@ -5379,84 +5386,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|||||||
// the user agent MAY automatically redirect its request to the URI
|
// the user agent MAY automatically redirect its request to the URI
|
||||||
// referenced by the Location field value,
|
// referenced by the Location field value,
|
||||||
// even if the specific status code is not understood.
|
// 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;
|
var location = response.headers.location;
|
||||||
if (location && this._options.followRedirects !== false &&
|
if (!location || this._options.followRedirects === false ||
|
||||||
statusCode >= 300 && statusCode < 400) {
|
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.2–3: 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
|
|
||||||
response.responseUrl = this._currentUrl;
|
response.responseUrl = this._currentUrl;
|
||||||
response.redirects = this._redirects;
|
response.redirects = this._redirects;
|
||||||
this.emit("response", response);
|
this.emit("response", response);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
this._requestBodyBuffers = [];
|
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.2–3: 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];
|
delete headers[header];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lastValue;
|
return (lastValue === null || typeof lastValue === "undefined") ?
|
||||||
|
undefined : String(lastValue).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createErrorType(code, defaultMessage) {
|
function createErrorType(code, defaultMessage) {
|
||||||
function CustomError(message) {
|
function CustomError(cause) {
|
||||||
Error.captureStackTrace(this, this.constructor);
|
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 = new Error();
|
||||||
CustomError.prototype.constructor = CustomError;
|
CustomError.prototype.constructor = CustomError;
|
||||||
@@ -5583,6 +5614,11 @@ function abortRequest(request) {
|
|||||||
request.abort();
|
request.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isSubdomain(subdomain, domain) {
|
||||||
|
const dot = subdomain.length - domain.length - 1;
|
||||||
|
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
||||||
|
}
|
||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
module.exports = wrap({ http: http, https: https });
|
module.exports = wrap({ http: http, https: https });
|
||||||
module.exports.wrap = wrap;
|
module.exports.wrap = wrap;
|
||||||
@@ -7021,7 +7057,9 @@ function getRequiredVars() {
|
|||||||
buildVersion: process.env.GITHUB_SHA,
|
buildVersion: process.env.GITHUB_SHA,
|
||||||
buildActor: process.env.GITHUB_ACTOR,
|
buildActor: process.env.GITHUB_ACTOR,
|
||||||
actionsId: process.env.GITHUB_ACTION,
|
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.workflowRun = context.workflowRun
|
||||||
this.requestedDeployment = false
|
this.requestedDeployment = false
|
||||||
this.deploymentInfo = null
|
this.deploymentInfo = null
|
||||||
|
this.githubApiUrl = context.githubApiUrl
|
||||||
|
this.artifactName = context.artifactName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||||
@@ -7077,7 +7117,7 @@ class Deployment {
|
|||||||
try {
|
try {
|
||||||
core.info(`Actor: ${this.buildActor}`)
|
core.info(`Actor: ${this.buildActor}`)
|
||||||
core.info(`Action ID: ${this.actionsId}`)
|
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`
|
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
|
||||||
core.info(`Artifact URL: ${artifactExgUrl}`)
|
core.info(`Artifact URL: ${artifactExgUrl}`)
|
||||||
const {data} = await axios.get(artifactExgUrl, {
|
const {data} = await axios.get(artifactExgUrl, {
|
||||||
@@ -7087,10 +7127,12 @@ class Deployment {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
core.info(JSON.stringify(data))
|
core.info(JSON.stringify(data))
|
||||||
if (data.value.length == 0) {
|
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.artifactName)?.url
|
||||||
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
|
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 = {
|
const payload = {
|
||||||
artifact_url: artifactUrl,
|
artifact_url: artifactUrl,
|
||||||
pages_build_version: this.buildVersion,
|
pages_build_version: this.buildVersion,
|
||||||
@@ -7106,15 +7148,41 @@ class Deployment {
|
|||||||
})
|
})
|
||||||
this.requestedDeployment = true
|
this.requestedDeployment = true
|
||||||
core.info(`Created deployment for ${this.buildVersion}`)
|
core.info(`Created deployment for ${this.buildVersion}`)
|
||||||
core.info(JSON.stringify(response.data))
|
if (response && response.data) {
|
||||||
this.deploymentInfo = response.data
|
core.info(JSON.stringify(response.data))
|
||||||
} catch (error) {
|
this.deploymentInfo = response.data
|
||||||
core.info(`Failed to create deployment for ${this.buildVersion}.`)
|
}
|
||||||
if (error.response && error.response.data) {
|
} catch (error) {
|
||||||
core.info(JSON.stringify(error.response.data))
|
|
||||||
|
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 {
|
try {
|
||||||
const statusUrl = this.deploymentInfo != null ?
|
const statusUrl = this.deploymentInfo != null ?
|
||||||
this.deploymentInfo["status_url"] :
|
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"] : "")
|
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 reportingInterval = Number(core.getInput('reporting_interval'))
|
||||||
const maxErrorCount = core.getInput('error_count')
|
const maxErrorCount = Number(core.getInput('error_count'))
|
||||||
var startTime = Date.now()
|
var startTime = Date.now()
|
||||||
var errorCount = 0
|
var errorCount = 0
|
||||||
|
|
||||||
@@ -7182,12 +7250,13 @@ class Deployment {
|
|||||||
core.setFailed('Failed with status code: ' + res.status)
|
core.setFailed('Failed with status code: ' + res.status)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Handle timeout
|
// Handle timeout
|
||||||
if (Date.now() - startTime >= timeout) {
|
if (Date.now() - startTime >= timeout) {
|
||||||
core.info('Timeout reached, aborting!')
|
core.info('Timeout reached, aborting!')
|
||||||
core.setFailed('Timeout reached, aborting!')
|
core.setFailed('Timeout reached, aborting!')
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error)
|
core.setFailed(error)
|
||||||
@@ -7227,7 +7296,7 @@ const {Deployment} = __nccwpck_require__(2877)
|
|||||||
async function emitTelemetry() {
|
async function emitTelemetry() {
|
||||||
// All variables we need from the runtime are set in the Deployment constructor
|
// All variables we need from the runtime are set in the Deployment constructor
|
||||||
const deployment = new Deployment()
|
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}`)
|
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
|
||||||
await axios
|
await axios
|
||||||
.post(
|
.post(
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -10,7 +10,9 @@ function getRequiredVars() {
|
|||||||
buildVersion: process.env.GITHUB_SHA,
|
buildVersion: process.env.GITHUB_SHA,
|
||||||
buildActor: process.env.GITHUB_ACTOR,
|
buildActor: process.env.GITHUB_ACTOR,
|
||||||
actionsId: process.env.GITHUB_ACTION,
|
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'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class Deployment {
|
|||||||
this.workflowRun = context.workflowRun
|
this.workflowRun = context.workflowRun
|
||||||
this.requestedDeployment = false
|
this.requestedDeployment = false
|
||||||
this.deploymentInfo = null
|
this.deploymentInfo = null
|
||||||
|
this.githubApiUrl = context.githubApiUrl
|
||||||
|
this.artifactName = context.artifactName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
// Ask the runtime for the unsigned artifact URL and deploy to GitHub Pages
|
||||||
@@ -33,7 +35,7 @@ class Deployment {
|
|||||||
try {
|
try {
|
||||||
core.info(`Actor: ${this.buildActor}`)
|
core.info(`Actor: ${this.buildActor}`)
|
||||||
core.info(`Action ID: ${this.actionsId}`)
|
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`
|
const artifactExgUrl = `${this.runTimeUrl}_apis/pipelines/workflows/${this.workflowRun}/artifacts?api-version=6.0-preview`
|
||||||
core.info(`Artifact URL: ${artifactExgUrl}`)
|
core.info(`Artifact URL: ${artifactExgUrl}`)
|
||||||
const {data} = await axios.get(artifactExgUrl, {
|
const {data} = await axios.get(artifactExgUrl, {
|
||||||
@@ -43,10 +45,12 @@ class Deployment {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
core.info(JSON.stringify(data))
|
core.info(JSON.stringify(data))
|
||||||
if (data.value.length == 0) {
|
const artifactRawUrl = data?.value?.find(artifact => artifact.name === this.artifactName)?.url
|
||||||
throw new Error('No uploaded artifact was found! Please check if there are any errors at build step.')
|
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 = {
|
const payload = {
|
||||||
artifact_url: artifactUrl,
|
artifact_url: artifactUrl,
|
||||||
pages_build_version: this.buildVersion,
|
pages_build_version: this.buildVersion,
|
||||||
@@ -62,15 +66,41 @@ class Deployment {
|
|||||||
})
|
})
|
||||||
this.requestedDeployment = true
|
this.requestedDeployment = true
|
||||||
core.info(`Created deployment for ${this.buildVersion}`)
|
core.info(`Created deployment for ${this.buildVersion}`)
|
||||||
core.info(JSON.stringify(response.data))
|
if (response && response.data) {
|
||||||
this.deploymentInfo = response.data
|
core.info(JSON.stringify(response.data))
|
||||||
} catch (error) {
|
this.deploymentInfo = response.data
|
||||||
core.info(`Failed to create deployment for ${this.buildVersion}.`)
|
}
|
||||||
if (error.response && error.response.data) {
|
} catch (error) {
|
||||||
core.info(JSON.stringify(error.response.data))
|
|
||||||
|
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 {
|
try {
|
||||||
const statusUrl = this.deploymentInfo != null ?
|
const statusUrl = this.deploymentInfo != null ?
|
||||||
this.deploymentInfo["status_url"] :
|
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"] : "")
|
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 reportingInterval = Number(core.getInput('reporting_interval'))
|
||||||
const maxErrorCount = core.getInput('error_count')
|
const maxErrorCount = Number(core.getInput('error_count'))
|
||||||
var startTime = Date.now()
|
var startTime = Date.now()
|
||||||
var errorCount = 0
|
var errorCount = 0
|
||||||
|
|
||||||
@@ -138,12 +168,13 @@ class Deployment {
|
|||||||
core.setFailed('Failed with status code: ' + res.status)
|
core.setFailed('Failed with status code: ' + res.status)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Handle timeout
|
// Handle timeout
|
||||||
if (Date.now() - startTime >= timeout) {
|
if (Date.now() - startTime >= timeout) {
|
||||||
core.info('Timeout reached, aborting!')
|
core.info('Timeout reached, aborting!')
|
||||||
core.setFailed('Timeout reached, aborting!')
|
core.setFailed('Timeout reached, aborting!')
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error)
|
core.setFailed(error)
|
||||||
|
|||||||
22
src/index.js
22
src/index.js
@@ -17,14 +17,14 @@ const deployment = new Deployment()
|
|||||||
async function cancelHandler(evtOrExitCodeOrError) {
|
async function cancelHandler(evtOrExitCodeOrError) {
|
||||||
try {
|
try {
|
||||||
if (deployment.requestedDeployment) {
|
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(
|
await axios.put(
|
||||||
pagesCancelDeployEndpoint,
|
pagesCancelDeployEndpoint,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/vnd.github.v3+json',
|
Accept: 'application/vnd.github.v3+json',
|
||||||
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
Authorization: `Bearer ${deployment.githubToken}`,
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,14 +32,21 @@ async function cancelHandler(evtOrExitCodeOrError) {
|
|||||||
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
|
core.info(`Deployment cancelled with ${pagesCancelDeployEndpoint}`)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.info('Deployment cancellation failed', e)
|
console.log('Deployment cancellation failed', e)
|
||||||
}
|
}
|
||||||
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
|
process.exit(isNaN(+evtOrExitCodeOrError) ? 1 : +evtOrExitCodeOrError)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
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 {
|
try {
|
||||||
const idToken = await core.getIDToken()
|
|
||||||
await deployment.create(idToken)
|
await deployment.create(idToken)
|
||||||
await deployment.check()
|
await deployment.check()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -52,4 +59,9 @@ process.on('SIGINT', cancelHandler)
|
|||||||
process.on('SIGTERM', cancelHandler)
|
process.on('SIGTERM', cancelHandler)
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
main().then(() => require('./pre'))
|
const emitTelemetry = core.getInput("emit_telemetry")
|
||||||
|
if (emitTelemetry === "true") {
|
||||||
|
require('./pre')
|
||||||
|
} else {
|
||||||
|
main()
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ describe('create', () => {
|
|||||||
process.env.GITHUB_ACTOR = 'monalisa'
|
process.env.GITHUB_ACTOR = 'monalisa'
|
||||||
process.env.GITHUB_ACTION = '__monalisa/octocat'
|
process.env.GITHUB_ACTION = '__monalisa/octocat'
|
||||||
process.env.GITHUB_ACTION_PATH = 'something'
|
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 => {
|
jest.spyOn(core, 'setOutput').mockImplementation(param => {
|
||||||
return param
|
return param
|
||||||
@@ -75,7 +83,7 @@ describe('create', () => {
|
|||||||
const fakeJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
|
const fakeJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w'
|
||||||
const scope = nock(`http://my-url`)
|
const scope = nock(`http://my-url`)
|
||||||
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
|
.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)
|
core.getIDToken = jest.fn().mockResolvedValue(fakeJwt)
|
||||||
axios.post = jest.fn().mockResolvedValue('test')
|
axios.post = jest.fn().mockResolvedValue('test')
|
||||||
@@ -94,7 +102,7 @@ describe('create', () => {
|
|||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/vnd.github.v3+json',
|
Accept: 'application/vnd.github.v3+json',
|
||||||
Authorization: 'Bearer ',
|
Authorization: `Bearer gha-token`,
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +120,7 @@ describe('create', () => {
|
|||||||
process.env.GITHUB_SHA = 'invalid-build-version'
|
process.env.GITHUB_SHA = 'invalid-build-version'
|
||||||
const scope = nock(`http://my-url`)
|
const scope = nock(`http://my-url`)
|
||||||
.get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview')
|
.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({
|
axios.post = jest.fn().mockRejectedValue({
|
||||||
status: 400
|
status: 400
|
||||||
@@ -161,6 +169,7 @@ describe('check', () => {
|
|||||||
process.env.GITHUB_ACTOR = 'monalisa'
|
process.env.GITHUB_ACTOR = 'monalisa'
|
||||||
process.env.GITHUB_ACTION = '__monalisa/octocat'
|
process.env.GITHUB_ACTION = '__monalisa/octocat'
|
||||||
process.env.GITHUB_ACTION_PATH = 'something'
|
process.env.GITHUB_ACTION_PATH = 'something'
|
||||||
|
process.env.ARTIFACT_NAME = 'github-pages'
|
||||||
|
|
||||||
jest.spyOn(core, 'setOutput').mockImplementation(param => {
|
jest.spyOn(core, 'setOutput').mockImplementation(param => {
|
||||||
return param
|
return param
|
||||||
@@ -209,7 +218,7 @@ describe('check', () => {
|
|||||||
`https://api.github.com/repos/${repositoryNwo}/pages/deployment/status/${buildVersion}`,
|
`https://api.github.com/repos/${repositoryNwo}/pages/deployment/status/${buildVersion}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'token '
|
Authorization: 'token gha-token'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const {Deployment} = require('./deployment')
|
|||||||
async function emitTelemetry() {
|
async function emitTelemetry() {
|
||||||
// All variables we need from the runtime are set in the Deployment constructor
|
// All variables we need from the runtime are set in the Deployment constructor
|
||||||
const deployment = new Deployment()
|
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}`)
|
core.info(`Sending telemetry for run id ${deployment.workflowRun}`)
|
||||||
await axios
|
await axios
|
||||||
.post(
|
.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user