Merge branch 'dev' into dev-v4

This commit is contained in:
James Ives 2022-01-06 10:10:17 -05:00
commit 709df6ce47
44 changed files with 2239 additions and 1908 deletions

View File

@ -1,2 +1,2 @@
ARG VARIANT=12 ARG VARIANT=14
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:${VARIANT} FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:${VARIANT}

View File

@ -1,4 +1,4 @@
ARG VARIANT=12-buster ARG VARIANT=14-buster
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:dev-${VARIANT} FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:dev-${VARIANT}
# Install tslint, typescript. eslint is installed by javascript image # Install tslint, typescript. eslint is installed by javascript image

View File

@ -4,7 +4,7 @@
"build": { "build": {
"dockerfile": "Dockerfile", "dockerfile": "Dockerfile",
"args": { "args": {
"VARIANT": "12" "VARIANT": "14"
} }
}, },
"settings": { "settings": {
@ -14,4 +14,4 @@
"dbaeumer.vscode-eslint" "dbaeumer.vscode-eslint"
], ],
"remoteUser": "node" "remoteUser": "node"
} }

View File

@ -1,6 +1,10 @@
{ {
"plugins": ["jest", "@typescript-eslint", "github"], "plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/recommended"], "extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": 9, "ecmaVersion": 9,
@ -10,57 +14,61 @@
"globals": { "globals": {
"fetch": true "fetch": true
}, },
"rules": {
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"camelcase": "off",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "default",
"format": ["camelCase", "UPPER_CASE", "StrictPascalCase"]
}
],
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"semi": "off",
"@typescript-eslint/semi": ["error", "never"],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error",
"no-console": "off",
"no-shadow": "off", // replaced by ts-eslint rule below
"@typescript-eslint/no-shadow": "error"
},
"env": { "env": {
"node": true, "node": true,
"es6": true, "es6": true,
"jest/globals": true "jest/globals": true
},
"rules": {
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"Number": {
"message": "Use number instead",
"fixWith": "number"
},
"String": {
"message": "Use string instead",
"fixWith": "string"
},
"Boolean": {
"message": "Use boolean instead",
"fixWith": "boolean"
},
"Object": {
"message": "Use object instead",
"fixWith": "object"
},
"{}": {
"message": "Use object instead",
"fixWith": "object"
},
"Symbol": {
"message": "Use symbol instead",
"fixWith": "symbol"
}
}
}
],
"@typescript-eslint/array-type": ["error", {"default": "array"}],
"@typescript-eslint/explicit-module-boundary-types": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"object-shorthand": ["error", "always"],
"prefer-destructuring": [
"error",
{
"array": false,
"object": true
},
{
"enforceForRenamedProperties": false
}
],
"no-console": ["error", {"allow": ["warn", "error"]}],
"no-alert": "error",
"no-debugger": "error"
} }
} }

View File

@ -2,26 +2,27 @@
name: Bug Report name: Bug Report
about: Create a bug report to help us improve the action. about: Create a bug report to help us improve the action.
labels: labels:
- bug - triage ⚠️
--- ---
<!-- Please check the Q&A before posting an issue: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A --> <!-- Please check the Q&A before posting an issue: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A -->
### Describe the bug ## Describe the bug
<!-- Please provide a clear and concise description of what the bug is. --> <!-- Please provide a clear and concise description of what the bug is. -->
--- ## Reproduction Steps
### Reproduction Steps
<!-- Steps to reproduce the behavior. --> <!-- Steps to reproduce the behavior. -->
--- ## Logs
### Logs <!-- Please provide your deployment logs. If the error message isn't revealing the problem please set ACTIONS_STEP_DEBUG to true in your repository's secrets menu and run the workflow again. -->
<!-- Please provide your deployment logs and a link or sample to/of your workflow. If the error message isn't revealing the problem please set ACTIONS_STEP_DEBUG to true in your repository's secrets menu and run the workflow again. -->
--- ## Workflow
<!-- Please provide a link or snippet of your workflow yml file. -->
## Additional Comments
### Additional Comments
<!--Add any other context about the problem here. --> <!--Add any other context about the problem here. -->

View File

@ -3,8 +3,7 @@ contact_links:
- name: Feature Request and Ideas - name: Feature Request and Ideas
url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AIdeas url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AIdeas
about: If you have an idea or would like to make a feature request please open a discussion thread. about: If you have an idea or would like to make a feature request please open a discussion thread.
- name: Support and Questions - name: Support and Questions
url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A url: https://github.com/JamesIves/github-pages-deploy-action/discussions?discussions_q=category%3AQ%26A
about: Need help or just have a general question? Please open a discussion thread. about: Need help or just have a general question? Please open a discussion thread.

View File

@ -1,12 +1,11 @@
### Description ## Description
<!-- Provide a description of what your changes do. --> <!-- Provide a description of what your changes do. -->
--- ## Testing Instructions
### Testing Instructions
<!-- Give us step by step instructions on how to test your changes. --> <!-- Give us step by step instructions on how to test your changes. -->
--- ## Additional Notes
### Additional Notes <!-- Anything else that will help us test the pull request. -->
<!-- Anything else that will help us test the pull request. -->

BIN
.github/assets/icon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,8 +1,15 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: npm - package-ecosystem: npm
directory: "/" directory: '/'
schedule: schedule:
interval: daily interval: daily
time: "10:00" time: '10:00'
open-pull-requests-limit: 10 open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: '/'
schedule:
interval: daily
time: '10:00'
open-pull-requests-limit: 10

View File

@ -14,11 +14,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: 'v12.18.4' node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Install Yarn - name: Install Yarn
@ -31,7 +31,7 @@ jobs:
yarn test yarn test
- name: Uploade CodeCov Report - name: Uploade CodeCov Report
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2.1.0
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
@ -39,11 +39,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: 'v12.18.4' node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Install Yarn - name: Install Yarn
@ -72,17 +72,18 @@ jobs:
needs: build needs: build
strategy: strategy:
matrix: matrix:
branch: ["gh-pages", "no-pages"] branch: ['gh-pages', 'no-pages']
commit: ["singleCommit", "add commits"] commit: ['singleCommit', 'add commits']
max-parallel: 1
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: 'v12.18.4' node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Download artifact - name: Download artifact
@ -119,7 +120,7 @@ jobs:
if: ${{ matrix.branch == 'gh-pages' }} if: ${{ matrix.branch == 'gh-pages' }}
with: with:
folder: integration folder: integration
branch: ${{ matrix.branch }} branch: ${{ matrix.branch }}
single-commit: ${{ matrix.commit == 'singleCommit' }} single-commit: ${{ matrix.commit == 'singleCommit' }}
dry-run: true dry-run: true

View File

@ -1,4 +1,4 @@
name: "CodeQL" name: 'CodeQL'
on: on:
push: push:
branches: branches:
@ -6,7 +6,6 @@ on:
- 'dev-v*' - 'dev-v*'
- 'releases/v*' - 'releases/v*'
pull_request: pull_request:
# The branches below must be a subset of the branches above
branches: branches:
- dev - dev
- 'dev-v*' - 'dev-v*'
@ -19,31 +18,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
# Initializes the CodeQL tools for scanning. - name: Initialize CodeQL
- name: Initialize CodeQL uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - name: Autobuild
# If this step fails, then you should remove it and run the build manually (see below) uses: github/codeql-action/autobuild@v1
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell. - name: Perform CodeQL Analysis
# 📚 https://git.io/JvXDl uses: github/codeql-action/analyze@v1
# ✏️ 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@v1

21
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Deploy Code to Release Branch
on:
workflow_dispatch:
jobs:
build:
name: Push to Release Branch
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.4.0
# Workflow dispatch event that pushes the current version to the release branch.
# From here the secondary production deployment workflow will trigger to build the dependencies.
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: releases/v4
folder: .
clean: false
single-commit: true

View File

@ -1,24 +1,50 @@
name: integration-tests name: integration-tests
on: on:
workflow_dispatch:
inputs:
branch:
description: 'Specifies the branch which the integration tests should run on.'
required: true
default: 'releases/v4'
schedule: schedule:
- cron: 30 15 * * 0-6 - cron: 30 15 * * 0-6
push: push:
tags-ignore: tags-ignore:
- '*.*' - '*.*'
branches: branches:
- dev
- releases/v4 - releases/v4
jobs: jobs:
# Deploys cross repo with an access token.
integration-cross-repo-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.4.0
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
git-config-name: Montezuma
git-config-email: montezuma@jamesiv.es
repository-name: MontezumaIves/lab
token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages
folder: integration
single-commit: true
clean: true
silent: true
# Deploys using checkout@v1 with an ACCESS_TOKEN. # Deploys using checkout@v1 with an ACCESS_TOKEN.
integration-checkout-v1: integration-checkout-v1:
needs: integration-cross-repo-push
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
token: ${{ secrets.ACCESS_TOKEN }} token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages branch: gh-pages
@ -26,9 +52,10 @@ jobs:
target-folder: cat/montezuma target-folder: cat/montezuma
git-config-name: Montezuma git-config-name: Montezuma
git-config-email: montezuma@jamesiv.es git-config-email: montezuma@jamesiv.es
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
@ -39,24 +66,24 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages branch: gh-pages
folder: integration folder: integration
target-folder: cat/montezuma2 target-folder: cat/montezuma2
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
# Deploys using a container that requires you to install rsync. # Deploys using a container that requires you to install rsync.
integration-container: integration-container:
needs: integration-checkout-v2 needs: integration-checkout-v2
@ -67,7 +94,7 @@ jobs:
LANG: C.UTF-8 LANG: C.UTF-8
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
@ -76,14 +103,15 @@ jobs:
apt-get update && apt-get install -y rsync apt-get update && apt-get install -y rsync
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages branch: gh-pages
folder: integration folder: integration
target-folder: cat/montezuma2 target-folder: cat/montezuma2
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
@ -94,136 +122,151 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
ssh-key: ${{ secrets.DEPLOY_KEY }} ssh-key: ${{ secrets.DEPLOY_KEY }}
branch: gh-pages branch: gh-pages
folder: integration folder: integration
target-folder: cat/montezuma3 target-folder: cat/montezuma3
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
# Deploys cross repo with an access token.
integration-cross-repo-push:
needs: integration-container
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
with:
repository-name: MontezumaIves/lab
token: ${{ secrets.CROSS_REPO_PUSH_TOKEN }}
branch: gh-pages
folder: integration
single-commit: true
# Deploys using an SSH key. # Deploys using an SSH key.
integration-ssh-third-party-client: integration-ssh-third-party-client:
needs: integration-container needs: integration-ssh
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Install SSH Client - name: Install SSH Client
uses: webfactory/ssh-agent@v0.4.1 uses: webfactory/ssh-agent@v0.5.4
with: with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }} ssh-private-key: ${{ secrets.DEPLOY_KEY }}
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
ssh: true ssh-key: true
branch: gh-pages branch: gh-pages
folder: integration folder: integration
target-folder: cat/montezuma4 target-folder: cat/montezuma4
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
# Deploys using a custom env. # Deploys using a custom env. (Includes subsequent commit)
integration-env: integration-env:
needs: integration-ssh needs: integration-ssh-third-party-client
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: '10.x' node-version: 'v14.18.1'
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
ssh-key: ${{ secrets.DEPLOY_KEY }} ssh-key: ${{ secrets.DEPLOY_KEY }}
branch: gh-pages branch: gh-pages
folder: integration folder: integration
target-folder: cat/montezuma4 target-folder: cat/montezuma4
silent: true
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
branch: gh-pages
folder: integration
target-folder: cat/subsequent
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages branches: gh-pages
# Deploys using the CLEAN option. # Deploys using the CLEAN option.
integration-clean: integration-clean:
needs: [integration-checkout-v1, integration-checkout-v2, integration-container, integration-ssh, integration-env] needs:
[
integration-checkout-v1,
integration-checkout-v2,
integration-container,
integration-ssh,
integration-ssh-third-party-client,
integration-env,
]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
token: ${{ secrets.ACCESS_TOKEN }} token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages branch: gh-pages
folder: integration folder: integration
clean: true clean: true
silent: true
# Deploys to a branch that doesn't exist with SINGLE_COMMIT. # Deploys to a branch that doesn't exist with SINGLE_COMMIT. (Includes subsequent commit)
integration-branch-creation: integration-branch-creation:
needs: integration-clean needs: integration-clean
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
with: with:
persist-credentials: false persist-credentials: false
- name: Build and Deploy - name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
token: ${{ secrets.ACCESS_TOKEN }} token: ${{ secrets.ACCESS_TOKEN }}
branch: integration-test-delete-prod branch: integration-test-delete-prod
folder: integration folder: integration
single-commit: true single-commit: true
silent: true
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
token: ${{ secrets.ACCESS_TOKEN }}
branch: integration-test-delete-prod
folder: integration
single-commit: true
target-folder: jives
silent: true
- name: Cleanup Generated Branch - name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1 uses: dawidd6/action-delete-branch@v3.1.0
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
branches: integration-test-delete-prod branches: integration-test-delete-prod

View File

@ -9,22 +9,22 @@ on:
jobs: jobs:
build: build:
name: Build production name: Build Production
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2.4.0
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: 'v12.18.4' node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- name: Install Yarn - name: Install Yarn
run: npm install -g yarn run: npm install -g yarn
- name: Clobber lib - name: Clobber lib
run: rm -rf lib run: rm -rf lib
- name: Set up .gitignore - name: Set up .gitignore
run: | run: |

View File

@ -1,54 +1,58 @@
name: publish-to-npm name: publish-to-npm
on: on:
release: workflow_dispatch:
types: [created] inputs:
version:
description: 'The updated registry version number.'
required: true
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2.4.0
with: with:
ref: dev ref: dev
# Setup .npmrc file to publish to npm # Setup .npmrc file to publish to npm
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: '10.15.1' node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
scope: '@jamesives' scope: '@jamesives'
- name: Configure git - name: Configure Git
run: | run: |
git config user.email "iam@jamesiv.es" git config user.email "iam@jamesiv.es"
git config user.name "James Ives" git config user.name "James Ives"
- name: Install Yarn - name: Install Yarn
run: npm install -g yarn run: npm install -g yarn
- run: yarn install --frozen-lockfile - run: yarn install --frozen-lockfile
- run: yarn build - run: yarn build
- run: npm version patch -m "Release %s 📣" - run: git stash
- run: git push - run: npm version ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }} 📣"
- run: git push
# Publish to npm # Publish to npm
- run: npm publish --access public - run: npm publish --access public
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Setup .npmrc file to publish to GitHub Packages # Setup .npmrc file to publish to GitHub Packages
- uses: actions/setup-node@v1.4.4 - uses: actions/setup-node@v2.5.1
with: with:
node-version: 12 node-version: 'v14.18.1'
registry-url: 'https://npm.pkg.github.com' registry-url: 'https://npm.pkg.github.com'
scope: '@jamesives' scope: '@jamesives'
- name: Authenticate with the GitHub Package Registry - name: Authenticate with the GitHub Package Registry
run: run:
echo "//npm.pkg.github.com:_authToken=${{ secrets.GITHUB_TOKEN }}" > echo "//npm.pkg.github.com:_authToken=${{ secrets.GITHUB_TOKEN }}" >
~/.npmrc ~/.npmrc
# Publish to GitHub Packages # Publish to GitHub Packages
- run: npm publish - run: npm publish
env: env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

26
.github/workflows/sponsors.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: publish-sponsors
on:
workflow_dispatch:
schedule:
- cron: 30 15 * * 0-6
jobs:
generate-sponsors:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2.4.0
- name: Generate Sponsors 💖
uses: JamesIves/github-sponsors-readme-action@1.0.6
with:
token: ${{ secrets.PAT }}
file: 'README.md'
template: '<a href="https://github.com/{{{ login }}}"><img src="https://github.com/{{{ login }}}.png" width="50px" alt="" /></a>'
minimum: 500
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: dev
folder: '.'

2
.nvmrc
View File

@ -1 +1 @@
v12.18.4 v14.18.1

View File

@ -6,6 +6,5 @@
"singleQuote": true, "singleQuote": true,
"trailingComma": "none", "trailingComma": "none",
"bracketSpacing": false, "bracketSpacing": false,
"arrowParens": "avoid", "arrowParens": "avoid"
"parser": "typescript" }
}

View File

@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment Examples of behavior that contributes to creating a positive environment
include: include:
* Using welcoming and inclusive language - Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences - Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism - Gracefully accepting constructive criticism
* Focusing on what is best for the community - Focusing on what is best for the community
* Showing empathy towards other community members - Showing empathy towards other community members
Examples of unacceptable behavior by participants include: Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or - The use of sexualized language or imagery and unwelcome sexual attention or
advances advances
* Trolling, insulting/derogatory comments, and personal or political attacks - Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment - Public or private harassment
* Publishing others' private information, such as a physical or electronic - Publishing others' private information, such as a physical or electronic
address, without explicit permission address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a - Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
## Our Responsibilities ## Our Responsibilities

View File

@ -1,15 +1,15 @@
# Contributing ✏️ # Contributing ✏️
When contributing to this repository, please first discuss the change you wish to make via issue, When contributing to this repository, please first discuss the change you wish to make via issue,
[email, or any other method with the owners of this repository](https://jamesiv.es) before making a change. If you are planning to work on an issue that already exists please let us know before writing any code incase it's already in flight! [email, or any other method with the owners of this repository](https://jamesiv.es) before making a change. If you are planning to work on an issue that already exists please let us know before writing any code incase it's already in flight!
## Before Making a Pull Request 🎒 ## Before Making a Pull Request 🎒
1. Ensure that you've tested your feature/change yourself. As the primary focus of this project is deployment, providing a link to a deployed repository using your branch is preferred. You can reference the forked action using your GitHub username, for example `yourname/github-pages-deplpy-action@dev`. 1. Ensure that you've tested your feature/change yourself. As the primary focus of this project is deployment, providing a link to a deployed repository using your branch is preferred. You can reference the forked action using your GitHub username, for example `yourname/github-pages-deplpy-action@dev`.
2. Ensure your change passes all of the integration tests. 2. Ensure your change passes all of the integration tests.
3. Make sure you update the README if you've made a change that requires documentation. 3. Make sure you update the README if you've made a change that requires documentation.
4. When making a pull request, highlight any areas that may cause a breaking change so the maintainer can update the version number accordingly on the GitHub marketplace and package registries. 4. When making a pull request, highlight any areas that may cause a breaking change so the maintainer can update the version number accordingly on the GitHub marketplace and package registries.
5. Make sure you've formatted and linted your code. You can do this by running `yarn format` and `yarn lint`. 5. Make sure you've formatted and linted your code. You can do this by running `yarn format` and `yarn lint`.
6. Fix or add any tests where applicable. You can run `yarn test` to run the suite. As this action is small in scope it's important that a high level of test coverage is maintained. All tests are written using [Jest](https://jestjs.io/). 6. Fix or add any tests where applicable. You can run `yarn test` to run the suite. As this action is small in scope it's important that a high level of test coverage is maintained. All tests are written using [Jest](https://jestjs.io/).
7. As this package is written in [TypeScript](https://www.typescriptlang.org/) please ensure all typing is accurate and the action compiles correctly by running `yarn build`. 7. As this package is written in [TypeScript](https://www.typescriptlang.org/) please ensure all typing is accurate and the action compiles correctly by running `yarn build`.
@ -32,7 +32,7 @@ Comment out the following in distribution branches:
# lib/ # lib/
``` ```
Build the project: Build the project:
``` ```
yarn build yarn build
@ -49,6 +49,6 @@ The `node_modules` and `lib` folders should _not_ be included when making a pull
## Resources 💡 ## Resources 💡
* [TypeScript](https://www.typescriptlang.org/) - [TypeScript](https://www.typescriptlang.org/)
* [Jest](https://jestjs.io/) - [Jest](https://jestjs.io/)
* [GitHub Actions Documentation](https://help.github.com/en/actions) - [GitHub Actions Documentation](https://help.github.com/en/actions)

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020 James Ives Copyright (c) 2021 James Ives
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

115
README.md
View File

@ -1,6 +1,6 @@
<p align="center"> <p align="center">
<a href="https://github.com/marketplace/actions/deploy-to-github-pages"> <a href="https://github.com/marketplace/actions/deploy-to-github-pages">
<img alt="" width="300px" src="https://github.com/JamesIves/github-pages-deploy-action/raw/dev-v4/assets/icon.png"> <img alt="" width="200px" src="https://github.com/JamesIves/github-pages-deploy-action/raw/dev/.github/assets/icon.png">
</a> </a>
</p> </p>
@ -31,11 +31,11 @@
</p> </p>
<p align="center"> <p align="center">
This <a href="https://github.com/features/actions">GitHub Action</a> will automatically deploy your project to <a href="https://pages.github.com/">GitHub Pages</a>. It can be configured to push your production-ready code into any branch you'd like, including <b>gh-pages</b> and <b>docs</b>. It can also handle cross repository deployments too. This <a href="https://github.com/features/actions">GitHub Action</a> will automatically deploy your project to <a href="https://pages.github.com/">GitHub Pages</a>. It can be configured to push your production-ready code into any branch you'd like, including <b>gh-pages</b> and <b>docs</b>. It can also handle cross repository deployments and works with <a href="https://github.com/enterprise">GitHub Enterprise</a> too.
</p> </p>
<p align="center"> <p align="center">
<img src="https://github.com/JamesIves/github-pages-deploy-action/raw/dev-v4/assets/screenshot.png"> <img src="https://github.com/JamesIves/github-pages-deploy-action/raw/dev/.github/assets/screenshot.png">
</p> </p>
## Getting Started :airplane: ## Getting Started :airplane:
@ -56,11 +56,11 @@ jobs:
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: | run: |
npm install npm ci
npm run build npm run build
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages # The branch the action should deploy to. branch: gh-pages # The branch the action should deploy to.
folder: build # The folder the action should deploy. folder: build # The folder the action should deploy.
@ -72,14 +72,14 @@ If you'd like to make it so the workflow only triggers on push events to specifi
on: on:
push: push:
branches: branches:
- master - main
``` ```
It's recommended that you use [Dependabot](https://dependabot.com/github-actions/) to keep your workflow up-to-date. You can find the latest tagged version on the [GitHub Marketplace](https://github.com/marketplace/actions/deploy-to-github-pages) or on the [releases page](https://github.com/JamesIves/github-pages-deploy-action/releases). It's recommended that you use [Dependabot](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically) to keep your workflow up-to-date and [secure](https://github.com/features/security). You can find the latest tagged version on the [GitHub Marketplace](https://github.com/marketplace/actions/deploy-to-github-pages) or on the [releases page](https://github.com/JamesIves/github-pages-deploy-action/releases).
#### Install as a Node Module 📦 #### Install as a Node Module 📦
If you'd like to use the functionality provided by this action in your own action you can install it using [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/get-npm) by running the following commands. It's available on both the [npm](https://www.npmjs.com/package/@jamesives/github-pages-deploy-action) and [GitHub registry](https://github.com/JamesIves/github-pages-deploy-action/packages/229985). If you'd like to use the functionality provided by this action in your own action you can either [create a composite action](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action), or you can install it using [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/get-npm) by running the following commands. It's available on both the [npm](https://www.npmjs.com/package/@jamesives/github-pages-deploy-action) and [GitHub registry](https://github.com/JamesIves/github-pages-deploy-action/packages/229985).
``` ```
yarn add @jamesives/github-pages-deploy-action yarn add @jamesives/github-pages-deploy-action
@ -92,25 +92,25 @@ npm install @jamesives/github-pages-deploy-action
It can then be imported into your project like so. It can then be imported into your project like so.
```javascript ```javascript
import run from "github-pages-deploy-action"; import run from '@jamesives/github-pages-deploy-action'
``` ```
Calling the functions directly will require you to pass in an object containing the variables found in the configuration section, you'll also need to provide a `workspace` with a path to your project. Calling the functions directly will require you to pass in an object containing the variables found in the configuration section, you'll also need to provide a `workspace` with a path to your project.
```javascript ```javascript
import run from "github-pages-deploy-action"; import run from '@jamesives/github-pages-deploy-action'
run({ run({
token: process.env["ACCESS_TOKEN"], token: process.env['ACCESS_TOKEN'],
branch: "gh-pages", branch: 'gh-pages',
folder: "build", folder: 'build',
repositoryName: "JamesIves/github-pages-deploy-action", repositoryName: 'JamesIves/github-pages-deploy-action',
silent: true, silent: true,
workspace: "src/project/location", workspace: 'src/project/location'
}); })
``` ```
For more information regarding the [action interface please click here](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/src/constants.ts#L7). For more information regarding the [action interface please click here](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/src/constants.ts#L7).
## Configuration 📁 ## Configuration 📁
@ -120,33 +120,33 @@ The `with` portion of the workflow **must** be configured before the action will
The following options must be configured in order to make a deployment. The following options must be configured in order to make a deployment.
| Key | Value Information | Type | Required | | Key | Value Information | Type | Required |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- |
| `branch` | This is the branch you wish to deploy to, for example `gh-pages` or `docs`. | `with` | **Yes** | | `branch` | This is the branch you wish to deploy to, for example `gh-pages` or `docs`. | `with` | **Yes** |
| `folder` | The folder in your repository that you want to deploy. If your build script compiles into a directory named `build` you'd put it here. If you wish to deploy the root directory you can place a `.` here. You can also utilize absolute file paths by appending `~` to your folder path. | `with` | **Yes** | | `folder` | The folder in your repository that you want to deploy. If your build script compiles into a directory named `build` you'd put it here. If you wish to deploy the root directory you can place a `.` here. You can also utilize absolute file paths by appending `~` to your folder path. | `with` | **Yes** |
By default the action does not need any token configuration and uses the provided repository scoped GitHub token to make the deployment. If you require more customization you can modify the deployment type using the following options. By default the action does not need any token configuration and uses the provided repository scoped GitHub token to make the deployment. If you require more customization you can modify the deployment type using the following options.
| Key | Value Information | Type | Required | | Key | Value Information | Type | Required |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- |
| `token` | This option defaults to the repository scoped GitHub Token. However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. We reccomend using a service account with the least permissions neccersary and recommend when generating a new PAT that you select the least permission scopes neccersary. [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) | `with` | **No** | | `token` | This option defaults to the repository scoped GitHub Token. However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. We recommend using a service account with the least permissions necessary and recommend when generating a new PAT that you select the least permission scopes necessary. [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) | `with` | **No** |
| `ssh-key` | You can configure the action to deploy using SSH by setting this option to a private SSH key stored **as a secret**. It can also be set to `true` to use an existing SSH client configuration. For more detailed information on how to add your public/private ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **No** | | `ssh-key` | You can configure the action to deploy using SSH by setting this option to a private SSH key stored **as a secret**. It can also be set to `true` to use an existing SSH client configuration. For more detailed information on how to add your public/private ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **No** |
#### Optional Choices #### Optional Choices
| Key | Value Information | Type | Required | | Key | Value Information | Type | Required |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- |
| `git-config-name` | Allows you to customize the name that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action. | `with` | **No** | | `git-config-name` | Allows you to customize the name that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action. | `with` | **No** |
| `git-config-email` | Allows you to customize the email that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email. | `with` | **No** | | `git-config-email` | Allows you to customize the email that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email. You can include `<>` for the value if you wish to omit this field altogether and push the commits without an email. | `with` | **No** |
| `repository-name` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use a PAT in the `token` input for this configuration option to work properly. | `with` | **No** | | `repository-name` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use a PAT in the `token` input for this configuration option to work properly. | `with` | **No** |
| `target-folder` | If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. | `with` | **No** | | `target-folder` | If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. | `with` | **No** |
| `commit-message` | If you need to customize the commit message for an integration you can do so. | `with` | **No** | | `commit-message` | If you need to customize the commit message for an integration you can do so. | `with` | **No** |
| `clean` | If your project generates hashed files on build you can use this option to automatically delete them from the target folder on the deployment branch with each deploy. This option is turned on by default, and can be toggled off by setting it to `false`. | `with` | **No** | | `clean` | You can use this option to delete files from your deployment destination that no longer exist in your deployment source. One use case is if your project generates hashed files that vary from build to build. Using `clean` will not affect `.git`, `.github`, or `.ssh` directories. This option is turned on by default, and can be toggled off by setting it to `false`. | `with` | **No** |
| `clean-exclude` | If you need to use `clean` but you'd like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string. | `with` | **No** | | `clean-exclude` | If you need to use `clean` but you'd like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string. | `with` | **No** |
| `dry-run` | Do not actually push back, but use `--dry-run` on `git push` invocations insead. | `with` | **No** | | `dry-run` | Do not actually push back, but use `--dry-run` on `git push` invocations instead. | `with` | **No** |
| `single-commit` | This option can be toggled to `true` if you'd prefer to have a single commit on the deployment branch instead of maintaining the full history. **Using this option will also cause any existing history to be wiped from the deployment branch**. | `with` | **No** | | `single-commit` | This option can be toggled to `true` if you'd prefer to have a single commit on the deployment branch instead of maintaining the full history. **Using this option will also cause any existing history to be wiped from the deployment branch**. | `with` | **No** |
| `silent` | Silences the action output preventing it from displaying git messages. | `with` | **No** | | `silent` | Silences the action output preventing it from displaying git messages. | `with` | **No** |
| `workspace` | This should point to where your project lives on the virtual machine. The GitHub Actions environment will set this for you. It is only necessary to set this variable if you're using the node module. | `with` | **No** | | `workspace` | This should point to where your project lives on the virtual machine. The GitHub Actions environment will set this for you. It is only necessary to set this variable if you're using the node module. | `with` | **No** |
With the action correctly configured you should see the workflow trigger the deployment under the configured conditions. With the action correctly configured you should see the workflow trigger the deployment under the configured conditions.
@ -154,11 +154,11 @@ With the action correctly configured you should see the workflow trigger the dep
The action will export an environment variable called `deployment_status` that you can use in your workflow to determine if the deployment was successful or not. You can find an explanation of each status type below. The action will export an environment variable called `deployment_status` that you can use in your workflow to determine if the deployment was successful or not. You can find an explanation of each status type below.
| Status | Description | | Status | Description |
| ------------- |-------------| | --------- | ----------------------------------------------------------------------------------------------- |
| `success` | The `success` status indicates that the action was able to successfully deploy to the branch. | | `success` | The `success` status indicates that the action was able to successfully deploy to the branch. |
| `failed` | The `failed` status indicates that the action encountered an error while trying to deploy. | | `failed` | The `failed` status indicates that the action encountered an error while trying to deploy. |
| `skipped` | The `skipped` status indicates that the action exited early as there was nothing new to deploy. | | `skipped` | The `skipped` status indicates that the action exited early as there was nothing new to deploy. |
This value is also set as a step output as `deployment-status`. This value is also set as a step output as `deployment-status`.
@ -178,7 +178,7 @@ With this configured you can then set the `ssh-key` part of the action to your p
```yml ```yml
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages branch: gh-pages
folder: site folder: site
@ -193,7 +193,7 @@ name: Build and Deploy
on: on:
push: push:
branches: branches:
- master - main
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -203,11 +203,11 @@ jobs:
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: | run: |
npm install npm ci
npm run build npm run build
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages branch: gh-pages
folder: build folder: build
@ -252,7 +252,7 @@ jobs:
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: | run: |
npm install npm ci
npm run build npm run build
- name: Upload Artifacts 🔺 # The project is then uploaded as an artifact named 'site'. - name: Upload Artifacts 🔺 # The project is then uploaded as an artifact named 'site'.
@ -274,11 +274,10 @@ jobs:
name: site name: site
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages branch: gh-pages
folder: "site" # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here. folder: 'site' # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here.
``` ```
</p> </p>
@ -296,7 +295,7 @@ If you use a [container](https://help.github.com/en/actions/automating-your-work
apt-get update && apt-get install -y rsync apt-get update && apt-get install -y rsync
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
``` ```
--- ---
@ -305,8 +304,7 @@ If you use a [container](https://help.github.com/en/actions/automating-your-work
If you're using a custom domain and require a `CNAME` file, or if you require the use of a `.nojekyll` file, you can safely commit these files directly into deployment branch without them being overridden after each deployment, additionally you can include these files in your deployment folder to update them. If you need to add additional files to the deployment that should be ignored by the build clean-up steps you can utilize the `clean-exclude` option. If you're using a custom domain and require a `CNAME` file, or if you require the use of a `.nojekyll` file, you can safely commit these files directly into deployment branch without them being overridden after each deployment, additionally you can include these files in your deployment folder to update them. If you need to add additional files to the deployment that should be ignored by the build clean-up steps you can utilize the `clean-exclude` option.
<details><summary>Click here to view an example of this.</summary>
<details><summary>Click here to view an exmaple of this.</summary>
<p> <p>
```yml ```yml
@ -314,7 +312,7 @@ name: Build and Deploy
on: on:
push: push:
branches: branches:
- master - main
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -324,11 +322,11 @@ jobs:
- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: | run: |
npm install npm ci
npm run build npm run build
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0 uses: JamesIves/github-pages-deploy-action@4.1.9
with: with:
branch: gh-pages branch: gh-pages
folder: build folder: build
@ -337,6 +335,7 @@ jobs:
special-file.txt special-file.txt
some/*.txt some/*.txt
``` ```
</p> </p>
</details> </details>
@ -346,6 +345,6 @@ If you wish to remove these files you must go into the deployment branch directl
## Support 💖 ## Support 💖
This project would not be possible without all of our fantastic [contributors](https://github.com/JamesIves/github-pages-deploy-action/graphs/contributors). The project logo was created by [Paganini](https://twitter.com/paganiniart). This project would not be possible without all of our fantastic [contributors](https://github.com/JamesIves/github-pages-deploy-action/graphs/contributors) and [sponsors](https://github.com/sponsors/JamesIves). If you'd like to support the maintenance and upkeep of this project you can [donate via GitHub Sponsors](https://github.com/sponsors/JamesIves).
If you'd like to support the maintenance and upkeep of this project you can [donate via GitHub Sponsors](https://github.com/sponsors/JamesIves). This project is distributed under the [MIT](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/LICENSE) license. <!-- sponsors --><a href="https://github.com/milanpollock"><img src="https://github.com/milanpollock.png" width="50px" alt="" /></a><a href="https://github.com/raoulvdberge"><img src="https://github.com/raoulvdberge.png" width="50px" alt="" /></a><!-- sponsors -->

View File

@ -7,8 +7,8 @@ The current version is actively maintained and will receive frequent updates and
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 4.0.x | :white_check_mark: | | 4.0.x | :white_check_mark: |
| < 3.0 | :x: | | < 4.0.0 | :x: |
## Reporting a Vulnerability ## Reporting a Vulnerability
Please disclose any security vulnerabilities either through the issues interface (as a bug) or by [emailing the project maintainer](https://jamesiv.es). Please disclose any security vulnerabilities either through the issues interface (as a bug) or by [emailing the project maintainer](https://jamesiv.es). Please bare in mind that this project is voluntarily maintained and updates will be worked on based on availability.

View File

@ -1,4 +1,3 @@
/* eslint-disable import/first */
// Initial env variable setup for tests. // Initial env variable setup for tests.
process.env['INPUT_FOLDER'] = 'build' process.env['INPUT_FOLDER'] = 'build'
process.env['GITHUB_SHA'] = '123' process.env['GITHUB_SHA'] = '123'
@ -42,6 +41,7 @@ describe('git', () => {
describe('init', () => { describe('init', () => {
it('should execute commands', async () => { it('should execute commands', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123', token: '123',
@ -55,7 +55,7 @@ describe('git', () => {
}) })
await init(action) await init(action)
expect(execute).toBeCalledTimes(5) expect(execute).toBeCalledTimes(6)
}) })
it('should catch when a function throws an error', async () => { it('should catch when a function throws an error', async () => {
@ -64,6 +64,7 @@ describe('git', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123', token: '123',
@ -79,7 +80,7 @@ describe('git', () => {
try { try {
await init(action) await init(action)
} catch (error) { } catch (error) {
expect(error.message).toBe( expect(error instanceof Error && error.message).toBe(
'There was an error initializing the repository: Mocked throw ❌' 'There was an error initializing the repository: Mocked throw ❌'
) )
} }
@ -87,6 +88,7 @@ describe('git', () => {
it('should correctly continue when it cannot unset a git config value', async () => { it('should correctly continue when it cannot unset a git config value', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123', token: '123',
@ -100,7 +102,7 @@ describe('git', () => {
}) })
await init(action) await init(action)
expect(execute).toBeCalledTimes(5) expect(execute).toBeCalledTimes(6)
}) })
it('should not unset git config if a user is using ssh', async () => { it('should not unset git config if a user is using ssh', async () => {
@ -108,6 +110,7 @@ describe('git', () => {
process.env.CI = 'true' process.env.CI = 'true'
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
sshKey: true, sshKey: true,
@ -121,13 +124,14 @@ describe('git', () => {
}) })
await init(action) await init(action)
expect(execute).toBeCalledTimes(4) expect(execute).toBeCalledTimes(5)
process.env.CI = undefined process.env.CI = undefined
}) })
it('should correctly continue when it cannot remove origin', async () => { it('should correctly continue when it cannot remove origin', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123', token: '123',
@ -141,13 +145,14 @@ describe('git', () => {
}) })
await init(action) await init(action)
expect(execute).toBeCalledTimes(5) expect(execute).toBeCalledTimes(6)
}) })
}) })
describe('deploy', () => { describe('deploy', () => {
it('should execute commands', async () => { it('should execute commands', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -163,13 +168,14 @@ describe('git', () => {
const response = await deploy(action) const response = await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(11) expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SUCCESS) expect(response).toBe(Status.SUCCESS)
}) })
it('should not push when asked to dryRun', async () => { it('should not push when asked to dryRun', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
dryRun: true, dryRun: true,
folder: 'assets', folder: 'assets',
@ -185,13 +191,14 @@ describe('git', () => {
const response = await deploy(action) const response = await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(10) expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SUCCESS) expect(response).toBe(Status.SUCCESS)
}) })
it('should execute commands with single commit toggled', async () => { it('should execute commands with single commit toggled', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'other', folder: 'other',
folderPath: 'other', folderPath: 'other',
@ -209,12 +216,13 @@ describe('git', () => {
await deploy(action) await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(10) expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
}) })
it('should execute commands with single commit toggled and existing branch', async () => { it('should execute commands with single commit toggled and existing branch', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'other', folder: 'other',
folderPath: 'other', folderPath: 'other',
@ -232,12 +240,13 @@ describe('git', () => {
await deploy(action) await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(9) expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
}) })
it('should execute commands with single commit and dryRun toggled', async () => { it('should execute commands with single commit and dryRun toggled', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'other', folder: 'other',
folderPath: 'other', folderPath: 'other',
@ -256,7 +265,7 @@ describe('git', () => {
await deploy(action) await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(9) expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
}) })
@ -270,6 +279,7 @@ describe('git', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
folderPath: 'assets', folderPath: 'assets',
@ -286,7 +296,7 @@ describe('git', () => {
const response = await deploy(action) const response = await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(11) expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(fs.existsSync).toBeCalledTimes(2) expect(fs.existsSync).toBeCalledTimes(2)
expect(response).toBe(Status.SUCCESS) expect(response).toBe(Status.SUCCESS)
@ -300,6 +310,7 @@ describe('git', () => {
it('should execute commands with clean options', async () => { it('should execute commands with clean options', async () => {
process.env.GITHUB_SHA = '' process.env.GITHUB_SHA = ''
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'other', folder: 'other',
folderPath: 'other', folderPath: 'other',
@ -317,13 +328,14 @@ describe('git', () => {
await deploy(action) await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(8) expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
}) })
}) })
it('should execute commands with clean options stored as an array', async () => { it('should execute commands with clean options stored as an array', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
folderPath: 'assets', folderPath: 'assets',
@ -341,12 +353,13 @@ describe('git', () => {
await deploy(action) await deploy(action)
// Includes the call to generateWorktree // Includes the call to generateWorktree
expect(execute).toBeCalledTimes(8) expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
}) })
it('should gracefully handle target folder', async () => { it('should gracefully handle target folder', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: '.', folder: '.',
branch: 'branch', branch: 'branch',
@ -360,13 +373,14 @@ describe('git', () => {
await deploy(action) await deploy(action)
expect(execute).toBeCalledTimes(8) expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(mkdirP).toBeCalledTimes(1) expect(mkdirP).toBeCalledTimes(1)
}) })
it('should stop early if there is nothing to commit', async () => { it('should stop early if there is nothing to commit', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -379,7 +393,7 @@ describe('git', () => {
}) })
const response = await deploy(action) const response = await deploy(action)
expect(execute).toBeCalledTimes(8) expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SKIPPED) expect(response).toBe(Status.SKIPPED)
}) })
@ -390,6 +404,7 @@ describe('git', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -404,7 +419,7 @@ describe('git', () => {
try { try {
await deploy(action) await deploy(action)
} catch (error) { } catch (error) {
expect(error.message).toBe( expect(error instanceof Error && error.message).toBe(
'The deploy step encountered an error: Mocked throw ❌' 'The deploy step encountered an error: Mocked throw ❌'
) )
} }

View File

@ -1,8 +1,8 @@
/* eslint-disable import/first */
// Initial env variable setup for tests. // Initial env variable setup for tests.
process.env['INPUT_FOLDER'] = 'build' process.env['INPUT_FOLDER'] = 'build'
process.env['GITHUB_SHA'] = '123' process.env['GITHUB_SHA'] = '123'
process.env['INPUT_DEBUG'] = 'debug' process.env['INPUT_DEBUG'] = 'debug'
process.env['GITHUB_REF_NAME'] = 'test'
import '../src/main' import '../src/main'
import {action, TestFlag} from '../src/constants' import {action, TestFlag} from '../src/constants'
@ -38,9 +38,10 @@ describe('main', () => {
it('should run through the commands', async () => { it('should run through the commands', async () => {
Object.assign(action, { Object.assign(action, {
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
folder: 'assets', folder: '.github/assets',
branch: 'branch', branch: 'branch',
token: '123', token: '123',
hostname: 'github.com',
pusher: { pusher: {
name: 'asd', name: 'asd',
email: 'as@cat' email: 'as@cat'
@ -49,15 +50,16 @@ describe('main', () => {
debug: true debug: true
}) })
await run(action) await run(action)
expect(execute).toBeCalledTimes(13) expect(execute).toBeCalledTimes(16)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(exportVariable).toBeCalledTimes(1) expect(exportVariable).toBeCalledTimes(1)
}) })
it('should run through the commands and succeed', async () => { it('should run through the commands and succeed', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
repositoryPath: 'JamesIves/github-pages-deploy-action', repositoryPath: 'JamesIves/github-pages-deploy-action',
folder: 'assets', folder: '.github/assets',
branch: 'branch', branch: 'branch',
token: '123', token: '123',
sshKey: true, sshKey: true,
@ -68,14 +70,15 @@ describe('main', () => {
isTest: TestFlag.HAS_CHANGED_FILES isTest: TestFlag.HAS_CHANGED_FILES
}) })
await run(action) await run(action)
expect(execute).toBeCalledTimes(16) expect(execute).toBeCalledTimes(19)
expect(rmRF).toBeCalledTimes(1) expect(rmRF).toBeCalledTimes(1)
expect(exportVariable).toBeCalledTimes(1) expect(exportVariable).toBeCalledTimes(1)
}) })
it('should throw if an error is encountered', async () => { it('should throw if an error is encountered', async () => {
Object.assign(action, { Object.assign(action, {
folder: 'assets', hostname: 'github.com',
folder: '.github/assets',
branch: 'branch', branch: 'branch',
token: null, token: null,
sshKey: null, sshKey: null,

View File

@ -43,6 +43,7 @@ describe('configureSSH', () => {
it('should skip client configuration if sshKey is set to true', async () => { it('should skip client configuration if sshKey is set to true', async () => {
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -67,6 +68,7 @@ describe('configureSSH', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -91,6 +93,7 @@ describe('configureSSH', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -115,6 +118,7 @@ describe('configureSSH', () => {
}) })
Object.assign(action, { Object.assign(action, {
hostname: 'github.com',
silent: false, silent: false,
folder: 'assets', folder: 'assets',
branch: 'branch', branch: 'branch',
@ -129,7 +133,7 @@ describe('configureSSH', () => {
try { try {
await configureSSH(action) await configureSSH(action)
} catch (error) { } catch (error) {
expect(error.message).toBe( expect(error instanceof Error && error.message).toBe(
'The ssh client configuration encountered an error: Mocked throw ❌' 'The ssh client configuration encountered an error: Mocked throw ❌'
) )
} }

View File

@ -5,7 +5,9 @@ import {
generateRepositoryPath, generateRepositoryPath,
generateFolderPath, generateFolderPath,
suppressSensitiveInformation, suppressSensitiveInformation,
checkParameters checkParameters,
stripProtocolFromUrl,
extractErrorMessage
} from '../src/util' } from '../src/util'
describe('util', () => { describe('util', () => {
@ -79,11 +81,13 @@ describe('util', () => {
branch: '123', branch: '123',
workspace: 'src/', workspace: 'src/',
folder: 'build', folder: 'build',
hostname: 'github.com',
token: null, token: null,
sshKey: 'real_token', sshKey: 'real_token',
silent: false, silent: false,
isTest: TestFlag.NONE isTest: TestFlag.NONE
} }
expect(generateRepositoryPath(action)).toEqual( expect(generateRepositoryPath(action)).toEqual(
'git@github.com:JamesIves/github-pages-deploy-action' 'git@github.com:JamesIves/github-pages-deploy-action'
) )
@ -95,13 +99,15 @@ describe('util', () => {
branch: '123', branch: '123',
workspace: 'src/', workspace: 'src/',
folder: 'build', folder: 'build',
hostname: 'enterprise.github.com',
token: '123', token: '123',
sshKey: null, sshKey: null,
silent: false, silent: false,
isTest: TestFlag.NONE isTest: TestFlag.NONE
} }
expect(generateRepositoryPath(action)).toEqual( expect(generateRepositoryPath(action)).toEqual(
'https://x-access-token:123@github.com/JamesIves/github-pages-deploy-action.git' 'https://x-access-token:123@enterprise.github.com/JamesIves/github-pages-deploy-action.git'
) )
}) })
@ -217,7 +223,7 @@ describe('util', () => {
try { try {
checkParameters(action) checkParameters(action)
} catch (e) { } catch (e) {
expect(e.message).toMatch( expect(e instanceof Error && e.message).toMatch(
'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.' 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.'
) )
} }
@ -237,7 +243,7 @@ describe('util', () => {
try { try {
checkParameters(action) checkParameters(action)
} catch (e) { } catch (e) {
expect(e.message).toMatch( expect(e instanceof Error && e.message).toMatch(
'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.' 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.'
) )
} }
@ -257,7 +263,7 @@ describe('util', () => {
try { try {
checkParameters(action) checkParameters(action)
} catch (e) { } catch (e) {
expect(e.message).toMatch('Branch is required.') expect(e instanceof Error && e.message).toMatch('Branch is required.')
} }
}) })
@ -275,7 +281,7 @@ describe('util', () => {
try { try {
checkParameters(action) checkParameters(action)
} catch (e) { } catch (e) {
expect(e.message).toMatch( expect(e instanceof Error && e.message).toMatch(
'You must provide the action with a folder to deploy.' 'You must provide the action with a folder to deploy.'
) )
} }
@ -296,10 +302,48 @@ describe('util', () => {
action.folderPath = generateFolderPath(action) action.folderPath = generateFolderPath(action)
checkParameters(action) checkParameters(action)
} catch (e) { } catch (e) {
expect(e.message).toMatch( expect(e instanceof Error && e.message).toMatch(
`The directory you're trying to deploy named notARealFolder doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗` `The directory you're trying to deploy named notARealFolder doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗`
) )
} }
}) })
}) })
describe('stripProtocolFromUrl', () => {
it('removes https', () => {
expect(stripProtocolFromUrl('https://github.com')).toBe('github.com')
})
it('removes http', () => {
expect(stripProtocolFromUrl('http://github.com')).toBe('github.com')
})
it('removes https|http and www.', () => {
expect(stripProtocolFromUrl('http://www.github.com')).toBe('github.com')
})
it('works with a url that is not github.com', () => {
expect(stripProtocolFromUrl('http://github.enterprise.jamesiv.es')).toBe(
'github.enterprise.jamesiv.es'
)
})
})
describe('extractErrorMessage', () => {
it('gets the message of a Error', () => {
expect(extractErrorMessage(new Error('a error message'))).toBe(
'a error message'
)
})
it('gets the message of a string', () => {
expect(extractErrorMessage('a error message')).toBe('a error message')
})
it('gets the message of a object', () => {
expect(extractErrorMessage({special: 'a error message'})).toBe(
`{"special":"a error message"}`
)
})
})
}) })

View File

@ -16,6 +16,7 @@ describe('generateWorktree', () => {
try { try {
await generateWorktree( await generateWorktree(
{ {
hostname: 'github.com',
workspace: 'somewhere', workspace: 'somewhere',
singleCommit: false, singleCommit: false,
branch: 'gh-pages', branch: 'gh-pages',
@ -27,7 +28,7 @@ describe('generateWorktree', () => {
true true
) )
} catch (error) { } catch (error) {
expect(error.message).toBe( expect(error instanceof Error && error.message).toBe(
'There was an error creating the worktree: Mocked throw ❌' 'There was an error creating the worktree: Mocked throw ❌'
) )
} }

View File

@ -81,6 +81,7 @@ describe('generateWorktree', () => {
const workspace = clonedir as string const workspace = clonedir as string
await generateWorktree( await generateWorktree(
{ {
hostname: 'github.com',
workspace, workspace,
singleCommit: false, singleCommit: false,
branch: 'gh-pages', branch: 'gh-pages',
@ -111,6 +112,7 @@ describe('generateWorktree', () => {
const workspace = clonedir as string const workspace = clonedir as string
await generateWorktree( await generateWorktree(
{ {
hostname: 'github.com',
workspace, workspace,
singleCommit: false, singleCommit: false,
branch: 'no-pages', branch: 'no-pages',
@ -138,6 +140,7 @@ describe('generateWorktree', () => {
const workspace = clonedir as string const workspace = clonedir as string
await generateWorktree( await generateWorktree(
{ {
hostname: 'github.com',
workspace, workspace,
singleCommit: true, singleCommit: true,
branch: 'gh-pages', branch: 'gh-pages',
@ -169,6 +172,7 @@ describe('generateWorktree', () => {
const workspace = clonedir as string const workspace = clonedir as string
await generateWorktree( await generateWorktree(
{ {
hostname: 'github.com',
workspace, workspace,
singleCommit: true, singleCommit: true,
branch: 'no-pages', branch: 'no-pages',

View File

@ -26,7 +26,7 @@ inputs:
We recommend using a service account with the least permissions neccersary We recommend using a service account with the least permissions neccersary
and when generating a new PAT that you select the least permission scopes required. and when generating a new PAT that you select the least permission scopes required.
[Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
required: false required: false
default: ${{ github.token }} default: ${{ github.token }}
@ -53,23 +53,23 @@ inputs:
default: true default: true
clean-exclude: clean-exclude:
description: "If you need to use clean but you would like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string." description: 'If you need to use clean but you would like to preserve certain files or folders you can use this option. This should contain each pattern as a single line in a multiline string.'
required: false required: false
dry-run: dry-run:
description: "Do not actually push back, but use `--dry-run` on `git push` invocations insead." description: 'Do not actually push back, but use `--dry-run` on `git push` invocations insead.'
required: false required: false
git-config-name: git-config-name:
description: "Allows you to customize the name that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action." description: 'Allows you to customize the name that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action.'
required: false required: false
git-config-email: git-config-email:
description: "Allows you to customize the email that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email." description: 'Allows you to customize the email that is attached to the GitHub config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email.'
required: false required: false
repository-name: repository-name:
description: "Allows you to speicfy a different repository path so long as you have permissions to push to it. This should be formatted like so: JamesIves/github-pages-deploy-action" description: 'Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: JamesIves/github-pages-deploy-action'
required: false required: false
workspace: workspace:
@ -81,7 +81,7 @@ inputs:
required: false required: false
silent: silent:
description: "Silences the action output preventing it from displaying git messages." description: 'Silences the action output preventing it from displaying git messages.'
required: false required: false
outputs: outputs:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

1
integration/.nojekyll Normal file
View File

@ -0,0 +1 @@

View File

@ -2,7 +2,7 @@
"name": "@jamesives/github-pages-deploy-action", "name": "@jamesives/github-pages-deploy-action",
"description": "GitHub action for building a project and deploying it to GitHub pages.", "description": "GitHub action for building a project and deploying it to GitHub pages.",
"author": "James Ives <iam@jamesiv.es> (https://jamesiv.es)", "author": "James Ives <iam@jamesiv.es> (https://jamesiv.es)",
"version": "3.7.1", "version": "4.1.9",
"license": "MIT", "license": "MIT",
"main": "lib/lib.js", "main": "lib/lib.js",
"types": "lib/lib.d.ts", "types": "lib/lib.d.ts",
@ -10,7 +10,7 @@
"build": "rimraf lib && tsc --declaration", "build": "rimraf lib && tsc --declaration",
"test": "jest", "test": "jest",
"lint": "eslint src/**/*.ts __tests__/**/*.ts", "lint": "eslint src/**/*.ts __tests__/**/*.ts",
"format": "prettier --write './**/*.ts'" "lint:format": "prettier --write './**/*.{ts,js,json,yml,md}' './*.{ts,js,json,yml,md}'"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -33,23 +33,25 @@
"deployment" "deployment"
], ],
"dependencies": { "dependencies": {
"@actions/core": "1.2.6", "@actions/core": "1.6.0",
"@actions/exec": "1.0.4", "@actions/exec": "1.1.0",
"@actions/github": "4.0.0", "@actions/github": "5.0.0",
"@actions/io": "1.0.2" "@actions/io": "1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "26.0.20", "@types/jest": "27.4.0",
"@types/node": "14.14.25", "@types/node": "17.0.8",
"eslint": "7.19.0", "@typescript-eslint/eslint-plugin": "4.33.0",
"eslint-plugin-github": "4.1.1", "@typescript-eslint/parser": "4.33.0",
"eslint-plugin-jest": "24.1.3", "eslint": "7.32.0",
"eslint-plugin-prettier": "^3.1.2", "eslint-config-prettier": "8.3.0",
"jest": "25.5.4", "eslint-plugin-jest": "25.3.4",
"jest-circus": "26.6.3", "eslint-plugin-prettier": "4.0.0",
"prettier": "2.2.1", "jest": "26.6.3",
"rimraf": "^3.0.2", "jest-circus": "27.4.6",
"ts-jest": "25.5.1", "prettier": "2.5.1",
"typescript": "3.9.7" "rimraf": "3.0.2",
"ts-jest": "26.5.6",
"typescript": "4.5.4"
} }
} }

View File

@ -1,6 +1,6 @@
import {getInput} from '@actions/core' import {getInput} from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import {isNullOrUndefined} from './util' import {isNullOrUndefined, stripProtocolFromUrl} from './util'
const {pusher, repository} = github.context.payload const {pusher, repository} = github.context.payload
@ -25,6 +25,8 @@ export interface ActionInterface {
cleanExclude?: string[] cleanExclude?: string[]
/** If you need to customize the commit message for an integration you can do so. */ /** If you need to customize the commit message for an integration you can do so. */
commitMessage?: string commitMessage?: string
/** The hostname of which the GitHub Workflow is being run on, ie: github.com */
hostname?: string
/** The git config email. */ /** The git config email. */
email?: string email?: string
/** The folder to deploy. */ /** The folder to deploy. */
@ -89,6 +91,9 @@ export const action: ActionInterface = {
cleanExclude: (getInput('clean-exclude') || '') cleanExclude: (getInput('clean-exclude') || '')
.split('\n') .split('\n')
.filter(l => l !== ''), .filter(l => l !== ''),
hostname: process.env.GITHUB_SERVER_URL
? stripProtocolFromUrl(process.env.GITHUB_SERVER_URL)
: 'github.com',
isTest: TestFlag.NONE, isTest: TestFlag.NONE,
email: !isNullOrUndefined(getInput('git-config-email')) email: !isNullOrUndefined(getInput('git-config-email'))
? getInput('git-config-email') ? getInput('git-config-email')
@ -96,7 +101,11 @@ export const action: ActionInterface = {
? pusher.email ? pusher.email
: `${ : `${
process.env.GITHUB_ACTOR || 'github-pages-deploy-action' process.env.GITHUB_ACTOR || 'github-pages-deploy-action'
}@users.noreply.github.com`, }@users.noreply.${
process.env.GITHUB_SERVER_URL
? stripProtocolFromUrl(process.env.GITHUB_SERVER_URL)
: 'github.com'
}`,
name: !isNullOrUndefined(getInput('git-config-name')) name: !isNullOrUndefined(getInput('git-config-name'))
? getInput('git-config-name') ? getInput('git-config-name')
: pusher && pusher.name : pusher && pusher.name
@ -139,3 +148,21 @@ export enum Status {
SKIPPED = 'skipped', SKIPPED = 'skipped',
RUNNING = 'running' RUNNING = 'running'
} }
/* Platform codes. */
export enum OperatingSystems {
LINUX = 'Linux',
WINDOWS = 'Windows',
MACOS = 'macOS'
}
export const SupportedOperatingSystems = [OperatingSystems.LINUX]
/* Excluded files. */
export enum DefaultExcludedFiles {
CNAME = 'CNAME',
NOJEKYLL = '.nojekyll',
SSH = '.ssh',
GIT = '.git',
GITHUB = '.github'
}

View File

@ -1,6 +1,7 @@
import {exec} from '@actions/exec' import {exec} from '@actions/exec'
import buffer from 'buffer'
let output: string let output = ''
/** Wrapper around the GitHub toolkit exec command which returns the output. /** Wrapper around the GitHub toolkit exec command which returns the output.
* Also allows you to easily toggle the current working directory. * Also allows you to easily toggle the current working directory.
@ -13,7 +14,7 @@ export async function execute(
cmd: string, cmd: string,
cwd: string, cwd: string,
silent: boolean silent: boolean
): Promise<any> { ): Promise<string> {
output = '' output = ''
await exec(cmd, [], { await exec(cmd, [], {
@ -28,6 +29,9 @@ export async function execute(
return Promise.resolve(output) return Promise.resolve(output)
} }
export function stdout(data: any): string | void { export function stdout(data: Buffer | string): void {
output += data.toString().trim() const dataString = data.toString().trim()
if (output.length + dataString.length < buffer.constants.MAX_STRING_LENGTH) {
output += dataString
}
} }

View File

@ -1,10 +1,19 @@
import {info} from '@actions/core' import {info} from '@actions/core'
import {mkdirP, rmRF} from '@actions/io' import {mkdirP, rmRF} from '@actions/io'
import fs from 'fs' import fs from 'fs'
import {ActionInterface, Status, TestFlag} from './constants' import {
ActionInterface,
DefaultExcludedFiles,
Status,
TestFlag
} from './constants'
import {execute} from './execute' import {execute} from './execute'
import {generateWorktree} from './worktree' import {generateWorktree} from './worktree'
import {isNullOrUndefined, suppressSensitiveInformation} from './util' import {
extractErrorMessage,
isNullOrUndefined,
suppressSensitiveInformation
} from './util'
/* Initializes git in the workspace. */ /* Initializes git in the workspace. */
export async function init(action: ActionInterface): Promise<void | Error> { export async function init(action: ActionInterface): Promise<void | Error> {
@ -17,19 +26,26 @@ export async function init(action: ActionInterface): Promise<void | Error> {
action.workspace, action.workspace,
action.silent action.silent
) )
await execute( await execute(
`git config user.email "${action.email}"`, `git config user.email "${action.email}"`,
action.workspace, action.workspace,
action.silent action.silent
) )
await execute(
`git config core.ignorecase false`,
action.workspace,
action.silent
)
try { try {
if ((process.env.CI && !action.sshKey) || action.isTest) { if ((process.env.CI && !action.sshKey) || action.isTest) {
/* Ensures that previously set Git configs do not interfere with the deployment. /* Ensures that previously set Git configs do not interfere with the deployment.
Only runs in the GitHub Actions CI environment if a user is not using an SSH key. Only runs in the GitHub Actions CI environment if a user is not using an SSH key.
*/ */
await execute( await execute(
`git config --local --unset-all http.https://github.com/.extraheader`, `git config --local --unset-all http.https://${action.hostname}/.extraheader`,
action.workspace, action.workspace,
action.silent action.silent
) )
@ -63,7 +79,7 @@ export async function init(action: ActionInterface): Promise<void | Error> {
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`There was an error initializing the repository: ${suppressSensitiveInformation( `There was an error initializing the repository: ${suppressSensitiveInformation(
error.message, extractErrorMessage(error),
action action
)} ` )} `
) )
@ -93,7 +109,7 @@ export async function deploy(action: ActionInterface): Promise<Status> {
const branchExists = const branchExists =
action.isTest & TestFlag.HAS_REMOTE_BRANCH || action.isTest & TestFlag.HAS_REMOTE_BRANCH ||
(await execute( (await execute(
`git ls-remote --heads ${action.repositoryPath} ${action.branch}`, `git ls-remote --heads ${action.repositoryPath} refs/heads/${action.branch}`,
action.workspace, action.workspace,
action.silent action.silent
)) ))
@ -125,16 +141,22 @@ export async function deploy(action: ActionInterface): Promise<Status> {
} ${ } ${
action.clean action.clean
? `--delete ${excludes} ${ ? `--delete ${excludes} ${
!fs.existsSync(`${action.folderPath}/CNAME`) !fs.existsSync(
? '--exclude CNAME' `${action.folderPath}/${DefaultExcludedFiles.CNAME}`
)
? `--exclude ${DefaultExcludedFiles.CNAME}`
: '' : ''
} ${ } ${
!fs.existsSync(`${action.folderPath}/.nojekyll`) !fs.existsSync(
? '--exclude .nojekyll' `${action.folderPath}/${DefaultExcludedFiles.NOJEKYLL}`
)
? `--exclude ${DefaultExcludedFiles.NOJEKYLL}`
: '' : ''
}` }`
: '' : ''
} --exclude .ssh --exclude .git --exclude .github ${ } --exclude ${DefaultExcludedFiles.SSH} --exclude ${
DefaultExcludedFiles.GIT
} --exclude ${DefaultExcludedFiles.GITHUB} ${
action.folderPath === action.workspace action.folderPath === action.workspace
? `--exclude ${temporaryDeploymentDirectory}` ? `--exclude ${temporaryDeploymentDirectory}`
: '' : ''
@ -143,6 +165,14 @@ export async function deploy(action: ActionInterface): Promise<Status> {
action.silent action.silent
) )
if (action.singleCommit) {
await execute(
`git add --all .`,
`${action.workspace}/${temporaryDeploymentDirectory}`,
action.silent
)
}
// Use git status to check if we have something to commit. // Use git status to check if we have something to commit.
// Special case is singleCommit with existing history, when // Special case is singleCommit with existing history, when
// we're really interested if the diff against the upstream branch // we're really interested if the diff against the upstream branch
@ -151,7 +181,9 @@ export async function deploy(action: ActionInterface): Promise<Status> {
branchExists && action.singleCommit branchExists && action.singleCommit
? `git diff origin/${action.branch}` ? `git diff origin/${action.branch}`
: `git status --porcelain` : `git status --porcelain`
info(`Checking if there are files to commit…`) info(`Checking if there are files to commit…`)
const hasFilesToCommit = const hasFilesToCommit =
action.isTest & TestFlag.HAS_CHANGED_FILES || action.isTest & TestFlag.HAS_CHANGED_FILES ||
(await execute( (await execute(
@ -160,7 +192,11 @@ export async function deploy(action: ActionInterface): Promise<Status> {
true // This output is always silenced due to the large output it creates. true // This output is always silenced due to the large output it creates.
)) ))
if (!hasFilesToCommit) { if (
(!action.singleCommit && !hasFilesToCommit) ||
// Ignores the case where single commit is true with a target folder to prevent incorrect early exiting.
(action.singleCommit && !action.targetFolder && !hasFilesToCommit)
) {
return Status.SKIPPED return Status.SKIPPED
} }
@ -194,18 +230,32 @@ export async function deploy(action: ActionInterface): Promise<Status> {
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`The deploy step encountered an error: ${suppressSensitiveInformation( `The deploy step encountered an error: ${suppressSensitiveInformation(
error.message, extractErrorMessage(error),
action action
)} ` )} `
) )
} finally { } finally {
// Cleans up temporary files/folders and restores the git state. // Cleans up temporary files/folders and restores the git state.
info('Running post deployment cleanup jobs… 🗑️') info('Running post deployment cleanup jobs… 🗑️')
await execute(
`git checkout -B ${temporaryDeploymentBranch}`,
`${action.workspace}/${temporaryDeploymentDirectory}`,
action.silent
)
await execute(
`chmod -R 777 ${temporaryDeploymentDirectory}`,
action.workspace,
action.silent
)
await execute( await execute(
`git worktree remove ${temporaryDeploymentDirectory} --force`, `git worktree remove ${temporaryDeploymentDirectory} --force`,
action.workspace, action.workspace,
action.silent action.silent
) )
await rmRF(temporaryDeploymentDirectory) await rmRF(temporaryDeploymentDirectory)
} }
} }

View File

@ -4,6 +4,7 @@ import {deploy, init} from './git'
import {configureSSH} from './ssh' import {configureSSH} from './ssh'
import { import {
checkParameters, checkParameters,
extractErrorMessage,
generateFolderPath, generateFolderPath,
generateRepositoryPath, generateRepositoryPath,
generateTokenType generateTokenType
@ -22,12 +23,12 @@ export default async function run(
info(` info(`
GitHub Pages Deploy Action 🚀 GitHub Pages Deploy Action 🚀
🚀 Getting Started Guide: https://github.com/marketplace/actions/deploy-to-github-pages 💖 Support: https://github.com/sponsors/JamesIves
Discussions / Q&A: https://github.com/JamesIves/github-pages-deploy-action/discussions
🔧 Report a Bug: https://github.com/JamesIves/github-pages-deploy-action/issues
📣 Maintained by James Ives: https://jamesiv.es 📣 Maintained by James Ives: https://jamesiv.es
💖 Support: https://github.com/sponsors/JamesIves`)
🚀 Getting Started Guide: https://github.com/JamesIves/github-pages-deploy-action
Discussions / Q&A: https://github.com/JamesIves/github-pages-deploy-action/discussions
🔧 Report a Bug: https://github.com/JamesIves/github-pages-deploy-action/issues`)
info('Checking configuration and starting deployment… 🚦') info('Checking configuration and starting deployment… 🚦')
@ -52,7 +53,7 @@ export default async function run(
status = await deploy(settings) status = await deploy(settings)
} catch (error) { } catch (error) {
status = Status.FAILED status = Status.FAILED
setFailed(error.message) setFailed(extractErrorMessage(error))
} finally { } finally {
info( info(
`${ `${

View File

@ -3,7 +3,7 @@ import {mkdirP} from '@actions/io'
import {execFileSync, execSync} from 'child_process' import {execFileSync, execSync} from 'child_process'
import {appendFileSync} from 'fs' import {appendFileSync} from 'fs'
import {ActionInterface} from './constants' import {ActionInterface} from './constants'
import {suppressSensitiveInformation} from './util' import {extractErrorMessage, suppressSensitiveInformation} from './util'
export async function configureSSH(action: ActionInterface): Promise<void> { export async function configureSSH(action: ActionInterface): Promise<void> {
try { try {
@ -12,10 +12,8 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
const sshKnownHostsDirectory = `${sshDirectory}/known_hosts` const sshKnownHostsDirectory = `${sshDirectory}/known_hosts`
// SSH fingerprints provided by GitHub: https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/githubs-ssh-key-fingerprints // SSH fingerprints provided by GitHub: https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/githubs-ssh-key-fingerprints
const sshGitHubKnownHostRsa = const sshGitHubKnownHostRsa = `\n${action.hostname} ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n`
'\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n' const sshGitHubKnownHostDss = `\n${action.hostname} ssh-dss AAAAB3NzaC1kc3MAAACBANGFW2P9xlGU3zWrymJgI/lKo//ZW2WfVtmbsUZJ5uyKArtlQOT2+WRhcg4979aFxgKdcsqAYW3/LS1T2km3jYW/vr4Uzn+dXWODVk5VlUiZ1HFOHf6s6ITcZvjvdbp6ZbpM+DuJT7Bw+h5Fx8Qt8I16oCZYmAPJRtu46o9C2zk1AAAAFQC4gdFGcSbp5Gr0Wd5Ay/jtcldMewAAAIATTgn4sY4Nem/FQE+XJlyUQptPWMem5fwOcWtSXiTKaaN0lkk2p2snz+EJvAGXGq9dTSWHyLJSM2W6ZdQDqWJ1k+cL8CARAqL+UMwF84CR0m3hj+wtVGD/J4G5kW2DBAf4/bqzP4469lT+dF2FRQ2L9JKXrCWcnhMtJUvua8dvnwAAAIB6C4nQfAA7x8oLta6tT+oCk2WQcydNsyugE8vLrHlogoWEicla6cWPk7oXSspbzUcfkjN3Qa6e74PhRkc7JdSdAlFzU3m7LMkXo1MHgkqNX8glxWNVqBSc0YRdbFdTkL0C6gtpklilhvuHQCdbgB3LBAikcRkDp+FCVkUgPC/7Rw==\n`
const sshGitHubKnownHostDss =
'\ngithub.com ssh-dss AAAAB3NzaC1kc3MAAACBANGFW2P9xlGU3zWrymJgI/lKo//ZW2WfVtmbsUZJ5uyKArtlQOT2+WRhcg4979aFxgKdcsqAYW3/LS1T2km3jYW/vr4Uzn+dXWODVk5VlUiZ1HFOHf6s6ITcZvjvdbp6ZbpM+DuJT7Bw+h5Fx8Qt8I16oCZYmAPJRtu46o9C2zk1AAAAFQC4gdFGcSbp5Gr0Wd5Ay/jtcldMewAAAIATTgn4sY4Nem/FQE+XJlyUQptPWMem5fwOcWtSXiTKaaN0lkk2p2snz+EJvAGXGq9dTSWHyLJSM2W6ZdQDqWJ1k+cL8CARAqL+UMwF84CR0m3hj+wtVGD/J4G5kW2DBAf4/bqzP4469lT+dF2FRQ2L9JKXrCWcnhMtJUvua8dvnwAAAIB6C4nQfAA7x8oLta6tT+oCk2WQcydNsyugE8vLrHlogoWEicla6cWPk7oXSspbzUcfkjN3Qa6e74PhRkc7JdSdAlFzU3m7LMkXo1MHgkqNX8glxWNVqBSc0YRdbFdTkL0C6gtpklilhvuHQCdbgB3LBAikcRkDp+FCVkUgPC/7Rw==\n'
info(`Configuring SSH client… 🔑`) info(`Configuring SSH client… 🔑`)
@ -28,9 +26,8 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
const agentOutput = execFileSync('ssh-agent').toString().split('\n') const agentOutput = execFileSync('ssh-agent').toString().split('\n')
agentOutput.map(line => { agentOutput.map(line => {
const exportableVariables = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec( const exportableVariables =
line /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(line)
)
if (exportableVariables && exportableVariables.length) { if (exportableVariables && exportableVariables.length) {
exportVariable(exportableVariables[1], exportableVariables[2]) exportVariable(exportableVariables[1], exportableVariables[2])
@ -49,7 +46,7 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`The ssh client configuration encountered an error: ${suppressSensitiveInformation( `The ssh client configuration encountered an error: ${suppressSensitiveInformation(
error.message, extractErrorMessage(error),
action action
)} ` )} `
) )

View File

@ -1,14 +1,20 @@
import {isDebug} from '@actions/core' import {isDebug, info} from '@actions/core'
import {existsSync} from 'fs' import {existsSync} from 'fs'
import path from 'path' import path from 'path'
import {ActionInterface, RequiredActionParameters} from './constants' import {
ActionInterface,
OperatingSystems,
RequiredActionParameters,
SupportedOperatingSystems
} from './constants'
/* Replaces all instances of a match in a string. */ /* Replaces all instances of a match in a string. */
const replaceAll = (input: string, find: string, replace: string): string => const replaceAll = (input: string, find: string, replace: string): string =>
input.split(find).join(replace) input.split(find).join(replace)
/* Utility function that checks to see if a value is undefined or not. */ /* Utility function that checks to see if a value is undefined or not.
export const isNullOrUndefined = (value: any): boolean => If allowEmptyString is passed the parameter is allowed to contain an empty string as a valid parameter. */
export const isNullOrUndefined = (value: unknown): boolean =>
typeof value === 'undefined' || value === null || value === '' typeof value === 'undefined' || value === null || value === ''
/* Generates a token type used for the action. */ /* Generates a token type used for the action. */
@ -18,8 +24,8 @@ export const generateTokenType = (action: ActionInterface): string =>
/* Generates a the repository path used to make the commits. */ /* Generates a the repository path used to make the commits. */
export const generateRepositoryPath = (action: ActionInterface): string => export const generateRepositoryPath = (action: ActionInterface): string =>
action.sshKey action.sshKey
? `git@github.com:${action.repositoryName}` ? `git@${action.hostname}:${action.repositoryName}`
: `https://${`x-access-token:${action.token}`}@github.com/${ : `https://${`x-access-token:${action.token}`}@${action.hostname}/${
action.repositoryName action.repositoryName
}.git` }.git`
@ -65,6 +71,16 @@ export const checkParameters = (action: ActionInterface): void => {
`The directory you're trying to deploy named ${action.folderPath} doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗` `The directory you're trying to deploy named ${action.folderPath} doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗`
) )
} }
if (
SupportedOperatingSystems.includes(
process.env.RUNNER_OS as OperatingSystems
)
) {
info(
`The operating system you're using is not supported and results may be varied. Please refer to the documentation for more details. ❗`
)
}
} }
/* Suppresses sensitive information from being exposed in error messages. */ /* Suppresses sensitive information from being exposed in error messages. */
@ -79,9 +95,9 @@ export const suppressSensitiveInformation = (
return value return value
} }
const orderedByLength = ([action.token, action.repositoryPath].filter( const orderedByLength = (
Boolean [action.token, action.repositoryPath].filter(Boolean) as string[]
) as string[]).sort((a, b) => b.length - a.length) ).sort((a, b) => b.length - a.length)
for (const find of orderedByLength) { for (const find of orderedByLength) {
value = replaceAll(value, find, '***') value = replaceAll(value, find, '***')
@ -89,3 +105,14 @@ export const suppressSensitiveInformation = (
return value return value
} }
export const extractErrorMessage = (error: unknown): string =>
error instanceof Error
? error.message
: typeof error == 'string'
? error
: JSON.stringify(error)
/** Strips the protocol from a provided URL. */
export const stripProtocolFromUrl = (url: string): string =>
url.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '').split('/')[0]

View File

@ -1,7 +1,7 @@
import {info} from '@actions/core' import {info} from '@actions/core'
import {ActionInterface} from './constants' import {ActionInterface} from './constants'
import {execute} from './execute' import {execute} from './execute'
import {suppressSensitiveInformation} from './util' import {extractErrorMessage, suppressSensitiveInformation} from './util'
export class GitCheckout { export class GitCheckout {
orphan = false orphan = false
@ -25,7 +25,7 @@ export class GitCheckout {
export async function generateWorktree( export async function generateWorktree(
action: ActionInterface, action: ActionInterface,
worktreedir: string, worktreedir: string,
branchExists: boolean branchExists: unknown
): Promise<void> { ): Promise<void> {
try { try {
info('Creating worktree…') info('Creating worktree…')
@ -43,28 +43,39 @@ export async function generateWorktree(
action.workspace, action.workspace,
action.silent action.silent
) )
const checkout = new GitCheckout(action.branch) const checkout = new GitCheckout(action.branch)
if (branchExists) { if (branchExists) {
// There's existing data on the branch to check out // There's existing data on the branch to check out
checkout.commitish = `origin/${action.branch}` checkout.commitish = `origin/${action.branch}`
} }
if (!branchExists || action.singleCommit) {
// Create a new history if we don't have the branch, or if we want to reset it if (
!branchExists ||
(action.singleCommit && action.branch !== process.env.GITHUB_REF_NAME)
) {
/* Create a new history if we don't have the branch, or if we want to reset it.
If the ref name is the same as the branch name, do not attempt to create an orphan of it. */
checkout.orphan = true checkout.orphan = true
} }
await execute( await execute(
checkout.toString(), checkout.toString(),
`${action.workspace}/${worktreedir}`, `${action.workspace}/${worktreedir}`,
action.silent action.silent
) )
if (!branchExists) { if (!branchExists) {
info(`Created the ${action.branch} branch… 🔧`) info(`Created the ${action.branch} branch… 🔧`)
// Our index is in HEAD state, reset // Our index is in HEAD state, reset
await execute( await execute(
'git reset --hard', 'git reset --hard',
`${action.workspace}/${worktreedir}`, `${action.workspace}/${worktreedir}`,
action.silent action.silent
) )
if (!action.singleCommit) { if (!action.singleCommit) {
// New history isn't singleCommit, create empty initial commit // New history isn't singleCommit, create empty initial commit
await execute( await execute(
@ -77,7 +88,7 @@ export async function generateWorktree(
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`There was an error creating the worktree: ${suppressSensitiveInformation( `There was an error creating the worktree: ${suppressSensitiveInformation(
error.message, extractErrorMessage(error),
action action
)} ` )} `
) )

View File

@ -1,63 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
/* Basic Options */ "target": "es6",
// "incremental": true, /* Enable incremental compilation */ "module": "commonjs",
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "outDir": "./lib",
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "rootDir": "./src",
// "allowJs": true, /* Allow javascript files to be compiled. */ "strict": true,
// "checkJs": true, /* Report errors in .js files. */ "noImplicitAny": false,
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ "esModuleInterop": true
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
}, },
"exclude": ["node_modules", "**/*.test.ts"] "exclude": ["node_modules", "**/*.test.ts"]
} }

View File

@ -1,7 +1,7 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"rootDir": "." "rootDir": "."
}, },
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

2984
yarn.lock

File diff suppressed because it is too large Load Diff