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}

View File

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

View File

@ -4,7 +4,7 @@
"build": {
"dockerfile": "Dockerfile",
"args": {
"VARIANT": "12"
"VARIANT": "14"
}
},
"settings": {

View File

@ -1,6 +1,10 @@
{
"plugins": ["jest", "@typescript-eslint", "github"],
"extends": ["plugin:github/recommended"],
"plugins": ["jest", "@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
@ -10,57 +14,61 @@
"globals": {
"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": {
"node": true,
"es6": 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
about: Create a bug report to help us improve the action.
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 -->
### Describe the bug
## Describe the bug
<!-- Please provide a clear and concise description of what the bug is. -->
---
## Reproduction Steps
### Reproduction Steps
<!-- Steps to reproduce the behavior. -->
---
## Logs
### Logs
<!-- 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. -->
<!-- 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. -->
---
## Workflow
<!-- Please provide a link or snippet of your workflow yml file. -->
## Additional Comments
### Additional Comments
<!--Add any other context about the problem here. -->

View File

@ -7,4 +7,3 @@ contact_links:
- name: Support and Questions
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.

View File

@ -1,12 +1,11 @@
### Description
## Description
<!-- Provide a description of what your changes do. -->
---
## Testing Instructions
### Testing Instructions
<!-- 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. -->

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
updates:
- package-ecosystem: npm
directory: "/"
directory: '/'
schedule:
interval: daily
time: "10:00"
time: '10:00'
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
steps:
- 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:
node-version: 'v12.18.4'
node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org'
- name: Install Yarn
@ -31,7 +31,7 @@ jobs:
yarn test
- name: Uploade CodeCov Report
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v2.1.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
@ -39,11 +39,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- 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:
node-version: 'v12.18.4'
node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org'
- name: Install Yarn
@ -72,17 +72,18 @@ jobs:
needs: build
strategy:
matrix:
branch: ["gh-pages", "no-pages"]
commit: ["singleCommit", "add commits"]
branch: ['gh-pages', 'no-pages']
commit: ['singleCommit', 'add commits']
max-parallel: 1
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- uses: actions/setup-node@v1.4.4
- uses: actions/setup-node@v2.5.1
with:
node-version: 'v12.18.4'
node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org'
- name: Download artifact

View File

@ -1,4 +1,4 @@
name: "CodeQL"
name: 'CodeQL'
on:
push:
branches:
@ -6,7 +6,6 @@ on:
- 'dev-v*'
- 'releases/v*'
pull_request:
# The branches below must be a subset of the branches above
branches:
- dev
- 'dev-v*'
@ -20,30 +19,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
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).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@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
on:
workflow_dispatch:
inputs:
branch:
description: 'Specifies the branch which the integration tests should run on.'
required: true
default: 'releases/v4'
schedule:
- cron: 30 15 * * 0-6
push:
tags-ignore:
- '*.*'
branches:
- dev
- releases/v4
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.
integration-checkout-v1:
needs: integration-cross-repo-push
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages
@ -26,9 +52,10 @@ jobs:
target-folder: cat/montezuma
git-config-name: Montezuma
git-config-email: montezuma@jamesiv.es
silent: true
- name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages
@ -39,24 +66,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages
folder: integration
target-folder: cat/montezuma2
silent: true
- name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages
# Deploys using a container that requires you to install rsync.
integration-container:
needs: integration-checkout-v2
@ -67,7 +94,7 @@ jobs:
LANG: C.UTF-8
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
@ -76,14 +103,15 @@ jobs:
apt-get update && apt-get install -y rsync
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages
folder: integration
target-folder: cat/montezuma2
silent: true
- name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages
@ -94,136 +122,151 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
branch: gh-pages
folder: integration
target-folder: cat/montezuma3
silent: true
- name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
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.
integration-ssh-third-party-client:
needs: integration-container
needs: integration-ssh
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Install SSH Client
uses: webfactory/ssh-agent@v0.4.1
uses: webfactory/ssh-agent@v0.5.4
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
ssh: true
ssh-key: true
branch: gh-pages
folder: integration
target-folder: cat/montezuma4
silent: true
- name: Cleanup Generated Branch
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages
# Deploys using a custom env.
# Deploys using a custom env. (Includes subsequent commit)
integration-env:
needs: integration-ssh
needs: integration-ssh-third-party-client
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1.4.4
- uses: actions/setup-node@v2.5.1
with:
node-version: '10.x'
node-version: 'v14.18.1'
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
branch: gh-pages
folder: integration
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
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: gh-pages
# Deploys using the CLEAN option.
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
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
token: ${{ secrets.ACCESS_TOKEN }}
branch: gh-pages
folder: integration
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:
needs: integration-clean
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v2.4.0
with:
persist-credentials: false
- name: Build and Deploy
uses: JamesIves/github-pages-deploy-action@releases/v4
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
token: ${{ secrets.ACCESS_TOKEN }}
branch: integration-test-delete-prod
folder: integration
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
uses: dawidd6/action-delete-branch@v2.0.1
uses: dawidd6/action-delete-branch@v3.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branches: integration-test-delete-prod

View File

@ -9,15 +9,15 @@ on:
jobs:
build:
name: Build production
name: Build Production
runs-on: ubuntu-latest
steps:
- 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:
node-version: 'v12.18.4'
node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org'
- name: Install Yarn

View File

@ -1,24 +1,27 @@
name: publish-to-npm
on:
release:
types: [created]
workflow_dispatch:
inputs:
version:
description: 'The updated registry version number.'
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2.4.0
with:
ref: dev
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v1.4.4
- uses: actions/setup-node@v2.5.1
with:
node-version: '10.15.1'
node-version: 'v14.18.1'
registry-url: 'https://registry.npmjs.org'
scope: '@jamesives'
- name: Configure git
- name: Configure Git
run: |
git config user.email "iam@jamesiv.es"
git config user.name "James Ives"
@ -28,7 +31,8 @@ jobs:
- run: yarn install --frozen-lockfile
- run: yarn build
- run: npm version patch -m "Release %s 📣"
- run: git stash
- run: npm version ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }} 📣"
- run: git push
# Publish to npm
@ -37,9 +41,9 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Setup .npmrc file to publish to GitHub Packages
- uses: actions/setup-node@v1.4.4
- uses: actions/setup-node@v2.5.1
with:
node-version: 12
node-version: 'v14.18.1'
registry-url: 'https://npm.pkg.github.com'
scope: '@jamesives'

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,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
"arrowParens": "avoid"
}

View File

@ -14,21 +14,21 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
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
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
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
## Our Responsibilities

View File

@ -49,6 +49,6 @@ The `node_modules` and `lib` folders should _not_ be included when making a pull
## Resources 💡
* [TypeScript](https://www.typescriptlang.org/)
* [Jest](https://jestjs.io/)
* [GitHub Actions Documentation](https://help.github.com/en/actions)
- [TypeScript](https://www.typescriptlang.org/)
- [Jest](https://jestjs.io/)
- [GitHub Actions Documentation](https://help.github.com/en/actions)

View File

@ -1,6 +1,6 @@
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
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
<p align="center">
<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>
</p>
@ -31,11 +31,11 @@
</p>
<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 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>
## 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.
run: |
npm install
npm ci
npm run build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages # The branch the action should deploy to.
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:
push:
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 📦
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
@ -92,22 +92,22 @@ npm install @jamesives/github-pages-deploy-action
It can then be imported into your project like so.
```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.
```javascript
import run from "github-pages-deploy-action";
import run from '@jamesives/github-pages-deploy-action'
run({
token: process.env["ACCESS_TOKEN"],
branch: "gh-pages",
folder: "build",
repositoryName: "JamesIves/github-pages-deploy-action",
token: process.env['ACCESS_TOKEN'],
branch: 'gh-pages',
folder: 'build',
repositoryName: 'JamesIves/github-pages-deploy-action',
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).
@ -121,29 +121,29 @@ 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.
| Key | Value Information | Type | Required |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- |
| `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** |
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 |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- |
| `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** |
#### Optional Choices
| 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-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** |
| `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** |
| `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** |
| `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** |
| `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** |
@ -155,7 +155,7 @@ 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.
| Status | Description |
| ------------- |-------------|
| --------- | ----------------------------------------------------------------------------------------------- |
| `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. |
| `skipped` | The `skipped` status indicates that the action exited early as there was nothing new to deploy. |
@ -178,7 +178,7 @@ With this configured you can then set the `ssh-key` part of the action to your p
```yml
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages
folder: site
@ -193,7 +193,7 @@ name: Build and Deploy
on:
push:
branches:
- master
- main
jobs:
deploy:
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.
run: |
npm install
npm ci
npm run build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages
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.
run: |
npm install
npm ci
npm run build
- name: Upload Artifacts 🔺 # The project is then uploaded as an artifact named 'site'.
@ -274,11 +274,10 @@ jobs:
name: site
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
token: ${{ secrets.ACCESS_TOKEN }}
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>
@ -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
- 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.
<details><summary>Click here to view an exmaple of this.</summary>
<details><summary>Click here to view an example of this.</summary>
<p>
```yml
@ -314,7 +312,7 @@ name: Build and Deploy
on:
push:
branches:
- master
- main
jobs:
deploy:
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.
run: |
npm install
npm ci
npm run build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.0.0
uses: JamesIves/github-pages-deploy-action@4.1.9
with:
branch: gh-pages
folder: build
@ -337,6 +335,7 @@ jobs:
special-file.txt
some/*.txt
```
</p>
</details>
@ -346,6 +345,6 @@ If you wish to remove these files you must go into the deployment branch directl
## 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 |
| ------- | ------------------ |
| 4.0.x | :white_check_mark: |
| < 3.0 | :x: |
| < 4.0.0 | :x: |
## 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.
process.env['INPUT_FOLDER'] = 'build'
process.env['GITHUB_SHA'] = '123'
@ -42,6 +41,7 @@ describe('git', () => {
describe('init', () => {
it('should execute commands', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123',
@ -55,7 +55,7 @@ describe('git', () => {
})
await init(action)
expect(execute).toBeCalledTimes(5)
expect(execute).toBeCalledTimes(6)
})
it('should catch when a function throws an error', async () => {
@ -64,6 +64,7 @@ describe('git', () => {
})
Object.assign(action, {
hostname: 'github.com',
silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123',
@ -79,7 +80,7 @@ describe('git', () => {
try {
await init(action)
} catch (error) {
expect(error.message).toBe(
expect(error instanceof Error && error.message).toBe(
'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 () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123',
@ -100,7 +102,7 @@ describe('git', () => {
})
await init(action)
expect(execute).toBeCalledTimes(5)
expect(execute).toBeCalledTimes(6)
})
it('should not unset git config if a user is using ssh', async () => {
@ -108,6 +110,7 @@ describe('git', () => {
process.env.CI = 'true'
Object.assign(action, {
hostname: 'github.com',
silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action',
sshKey: true,
@ -121,13 +124,14 @@ describe('git', () => {
})
await init(action)
expect(execute).toBeCalledTimes(4)
expect(execute).toBeCalledTimes(5)
process.env.CI = undefined
})
it('should correctly continue when it cannot remove origin', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
repositoryPath: 'JamesIves/github-pages-deploy-action',
token: '123',
@ -141,13 +145,14 @@ describe('git', () => {
})
await init(action)
expect(execute).toBeCalledTimes(5)
expect(execute).toBeCalledTimes(6)
})
})
describe('deploy', () => {
it('should execute commands', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'assets',
branch: 'branch',
@ -163,13 +168,14 @@ describe('git', () => {
const response = await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(11)
expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SUCCESS)
})
it('should not push when asked to dryRun', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
dryRun: true,
folder: 'assets',
@ -185,13 +191,14 @@ describe('git', () => {
const response = await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(10)
expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SUCCESS)
})
it('should execute commands with single commit toggled', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'other',
folderPath: 'other',
@ -209,12 +216,13 @@ describe('git', () => {
await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(10)
expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1)
})
it('should execute commands with single commit toggled and existing branch', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'other',
folderPath: 'other',
@ -232,12 +240,13 @@ describe('git', () => {
await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(9)
expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1)
})
it('should execute commands with single commit and dryRun toggled', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'other',
folderPath: 'other',
@ -256,7 +265,7 @@ describe('git', () => {
await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(9)
expect(execute).toBeCalledTimes(12)
expect(rmRF).toBeCalledTimes(1)
})
@ -270,6 +279,7 @@ describe('git', () => {
})
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'assets',
folderPath: 'assets',
@ -286,7 +296,7 @@ describe('git', () => {
const response = await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(11)
expect(execute).toBeCalledTimes(13)
expect(rmRF).toBeCalledTimes(1)
expect(fs.existsSync).toBeCalledTimes(2)
expect(response).toBe(Status.SUCCESS)
@ -300,6 +310,7 @@ describe('git', () => {
it('should execute commands with clean options', async () => {
process.env.GITHUB_SHA = ''
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'other',
folderPath: 'other',
@ -317,13 +328,14 @@ describe('git', () => {
await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(8)
expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1)
})
})
it('should execute commands with clean options stored as an array', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'assets',
folderPath: 'assets',
@ -341,12 +353,13 @@ describe('git', () => {
await deploy(action)
// Includes the call to generateWorktree
expect(execute).toBeCalledTimes(8)
expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1)
})
it('should gracefully handle target folder', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: '.',
branch: 'branch',
@ -360,13 +373,14 @@ describe('git', () => {
await deploy(action)
expect(execute).toBeCalledTimes(8)
expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1)
expect(mkdirP).toBeCalledTimes(1)
})
it('should stop early if there is nothing to commit', async () => {
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'assets',
branch: 'branch',
@ -379,7 +393,7 @@ describe('git', () => {
})
const response = await deploy(action)
expect(execute).toBeCalledTimes(8)
expect(execute).toBeCalledTimes(10)
expect(rmRF).toBeCalledTimes(1)
expect(response).toBe(Status.SKIPPED)
})
@ -390,6 +404,7 @@ describe('git', () => {
})
Object.assign(action, {
hostname: 'github.com',
silent: false,
folder: 'assets',
branch: 'branch',
@ -404,7 +419,7 @@ describe('git', () => {
try {
await deploy(action)
} catch (error) {
expect(error.message).toBe(
expect(error instanceof Error && error.message).toBe(
'The deploy step encountered an error: Mocked throw ❌'
)
}

View File

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

View File

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

View File

@ -5,7 +5,9 @@ import {
generateRepositoryPath,
generateFolderPath,
suppressSensitiveInformation,
checkParameters
checkParameters,
stripProtocolFromUrl,
extractErrorMessage
} from '../src/util'
describe('util', () => {
@ -79,11 +81,13 @@ describe('util', () => {
branch: '123',
workspace: 'src/',
folder: 'build',
hostname: 'github.com',
token: null,
sshKey: 'real_token',
silent: false,
isTest: TestFlag.NONE
}
expect(generateRepositoryPath(action)).toEqual(
'git@github.com:JamesIves/github-pages-deploy-action'
)
@ -95,13 +99,15 @@ describe('util', () => {
branch: '123',
workspace: 'src/',
folder: 'build',
hostname: 'enterprise.github.com',
token: '123',
sshKey: null,
silent: false,
isTest: TestFlag.NONE
}
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 {
checkParameters(action)
} 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.'
)
}
@ -237,7 +243,7 @@ describe('util', () => {
try {
checkParameters(action)
} 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.'
)
}
@ -257,7 +263,7 @@ describe('util', () => {
try {
checkParameters(action)
} 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 {
checkParameters(action)
} catch (e) {
expect(e.message).toMatch(
expect(e instanceof Error && e.message).toMatch(
'You must provide the action with a folder to deploy.'
)
}
@ -296,10 +302,48 @@ describe('util', () => {
action.folderPath = generateFolderPath(action)
checkParameters(action)
} 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. ❗`
)
}
})
})
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 {
await generateWorktree(
{
hostname: 'github.com',
workspace: 'somewhere',
singleCommit: false,
branch: 'gh-pages',
@ -27,7 +28,7 @@ describe('generateWorktree', () => {
true
)
} catch (error) {
expect(error.message).toBe(
expect(error instanceof Error && error.message).toBe(
'There was an error creating the worktree: Mocked throw ❌'
)
}

View File

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

View File

@ -53,23 +53,23 @@ inputs:
default: true
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
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
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
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
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
workspace:
@ -81,7 +81,7 @@ inputs:
required: false
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
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",
"description": "GitHub action for building a project and deploying it to GitHub pages.",
"author": "James Ives <iam@jamesiv.es> (https://jamesiv.es)",
"version": "3.7.1",
"version": "4.1.9",
"license": "MIT",
"main": "lib/lib.js",
"types": "lib/lib.d.ts",
@ -10,7 +10,7 @@
"build": "rimraf lib && tsc --declaration",
"test": "jest",
"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": {
"type": "git",
@ -33,23 +33,25 @@
"deployment"
],
"dependencies": {
"@actions/core": "1.2.6",
"@actions/exec": "1.0.4",
"@actions/github": "4.0.0",
"@actions/io": "1.0.2"
"@actions/core": "1.6.0",
"@actions/exec": "1.1.0",
"@actions/github": "5.0.0",
"@actions/io": "1.1.1"
},
"devDependencies": {
"@types/jest": "26.0.20",
"@types/node": "14.14.25",
"eslint": "7.19.0",
"eslint-plugin-github": "4.1.1",
"eslint-plugin-jest": "24.1.3",
"eslint-plugin-prettier": "^3.1.2",
"jest": "25.5.4",
"jest-circus": "26.6.3",
"prettier": "2.2.1",
"rimraf": "^3.0.2",
"ts-jest": "25.5.1",
"typescript": "3.9.7"
"@types/jest": "27.4.0",
"@types/node": "17.0.8",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "25.3.4",
"eslint-plugin-prettier": "4.0.0",
"jest": "26.6.3",
"jest-circus": "27.4.6",
"prettier": "2.5.1",
"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 * as github from '@actions/github'
import {isNullOrUndefined} from './util'
import {isNullOrUndefined, stripProtocolFromUrl} from './util'
const {pusher, repository} = github.context.payload
@ -25,6 +25,8 @@ export interface ActionInterface {
cleanExclude?: string[]
/** If you need to customize the commit message for an integration you can do so. */
commitMessage?: string
/** The hostname of which the GitHub Workflow is being run on, ie: github.com */
hostname?: string
/** The git config email. */
email?: string
/** The folder to deploy. */
@ -89,6 +91,9 @@ export const action: ActionInterface = {
cleanExclude: (getInput('clean-exclude') || '')
.split('\n')
.filter(l => l !== ''),
hostname: process.env.GITHUB_SERVER_URL
? stripProtocolFromUrl(process.env.GITHUB_SERVER_URL)
: 'github.com',
isTest: TestFlag.NONE,
email: !isNullOrUndefined(getInput('git-config-email'))
? getInput('git-config-email')
@ -96,7 +101,11 @@ export const action: ActionInterface = {
? pusher.email
: `${
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'))
? getInput('git-config-name')
: pusher && pusher.name
@ -139,3 +148,21 @@ export enum Status {
SKIPPED = 'skipped',
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 buffer from 'buffer'
let output: string
let output = ''
/** Wrapper around the GitHub toolkit exec command which returns the output.
* Also allows you to easily toggle the current working directory.
@ -13,7 +14,7 @@ export async function execute(
cmd: string,
cwd: string,
silent: boolean
): Promise<any> {
): Promise<string> {
output = ''
await exec(cmd, [], {
@ -28,6 +29,9 @@ export async function execute(
return Promise.resolve(output)
}
export function stdout(data: any): string | void {
output += data.toString().trim()
export function stdout(data: Buffer | string): void {
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 {mkdirP, rmRF} from '@actions/io'
import fs from 'fs'
import {ActionInterface, Status, TestFlag} from './constants'
import {
ActionInterface,
DefaultExcludedFiles,
Status,
TestFlag
} from './constants'
import {execute} from './execute'
import {generateWorktree} from './worktree'
import {isNullOrUndefined, suppressSensitiveInformation} from './util'
import {
extractErrorMessage,
isNullOrUndefined,
suppressSensitiveInformation
} from './util'
/* Initializes git in the workspace. */
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.silent
)
await execute(
`git config user.email "${action.email}"`,
action.workspace,
action.silent
)
await execute(
`git config core.ignorecase false`,
action.workspace,
action.silent
)
try {
if ((process.env.CI && !action.sshKey) || action.isTest) {
/* 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.
*/
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.silent
)
@ -63,7 +79,7 @@ export async function init(action: ActionInterface): Promise<void | Error> {
} catch (error) {
throw new Error(
`There was an error initializing the repository: ${suppressSensitiveInformation(
error.message,
extractErrorMessage(error),
action
)} `
)
@ -93,7 +109,7 @@ export async function deploy(action: ActionInterface): Promise<Status> {
const branchExists =
action.isTest & TestFlag.HAS_REMOTE_BRANCH ||
(await execute(
`git ls-remote --heads ${action.repositoryPath} ${action.branch}`,
`git ls-remote --heads ${action.repositoryPath} refs/heads/${action.branch}`,
action.workspace,
action.silent
))
@ -125,16 +141,22 @@ export async function deploy(action: ActionInterface): Promise<Status> {
} ${
action.clean
? `--delete ${excludes} ${
!fs.existsSync(`${action.folderPath}/CNAME`)
? '--exclude CNAME'
!fs.existsSync(
`${action.folderPath}/${DefaultExcludedFiles.CNAME}`
)
? `--exclude ${DefaultExcludedFiles.CNAME}`
: ''
} ${
!fs.existsSync(`${action.folderPath}/.nojekyll`)
? '--exclude .nojekyll'
!fs.existsSync(
`${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
? `--exclude ${temporaryDeploymentDirectory}`
: ''
@ -143,6 +165,14 @@ export async function deploy(action: ActionInterface): Promise<Status> {
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.
// Special case is singleCommit with existing history, when
// 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
? `git diff origin/${action.branch}`
: `git status --porcelain`
info(`Checking if there are files to commit…`)
const hasFilesToCommit =
action.isTest & TestFlag.HAS_CHANGED_FILES ||
(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.
))
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
}
@ -194,18 +230,32 @@ export async function deploy(action: ActionInterface): Promise<Status> {
} catch (error) {
throw new Error(
`The deploy step encountered an error: ${suppressSensitiveInformation(
error.message,
extractErrorMessage(error),
action
)} `
)
} finally {
// Cleans up temporary files/folders and restores the git state.
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(
`git worktree remove ${temporaryDeploymentDirectory} --force`,
action.workspace,
action.silent
)
await rmRF(temporaryDeploymentDirectory)
}
}

View File

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

View File

@ -3,7 +3,7 @@ import {mkdirP} from '@actions/io'
import {execFileSync, execSync} from 'child_process'
import {appendFileSync} from 'fs'
import {ActionInterface} from './constants'
import {suppressSensitiveInformation} from './util'
import {extractErrorMessage, suppressSensitiveInformation} from './util'
export async function configureSSH(action: ActionInterface): Promise<void> {
try {
@ -12,10 +12,8 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
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
const sshGitHubKnownHostRsa =
'\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\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'
const sshGitHubKnownHostRsa = `\n${action.hostname} 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`
info(`Configuring SSH client… 🔑`)
@ -28,9 +26,8 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
const agentOutput = execFileSync('ssh-agent').toString().split('\n')
agentOutput.map(line => {
const exportableVariables = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(
line
)
const exportableVariables =
/^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(line)
if (exportableVariables && exportableVariables.length) {
exportVariable(exportableVariables[1], exportableVariables[2])
@ -49,7 +46,7 @@ export async function configureSSH(action: ActionInterface): Promise<void> {
} catch (error) {
throw new Error(
`The ssh client configuration encountered an error: ${suppressSensitiveInformation(
error.message,
extractErrorMessage(error),
action
)} `
)

View File

@ -1,14 +1,20 @@
import {isDebug} from '@actions/core'
import {isDebug, info} from '@actions/core'
import {existsSync} from 'fs'
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. */
const replaceAll = (input: string, find: string, replace: string): string =>
input.split(find).join(replace)
/* Utility function that checks to see if a value is undefined or not. */
export const isNullOrUndefined = (value: any): boolean =>
/* Utility function that checks to see if a value is undefined or not.
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 === ''
/* 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. */
export const generateRepositoryPath = (action: ActionInterface): string =>
action.sshKey
? `git@github.com:${action.repositoryName}`
: `https://${`x-access-token:${action.token}`}@github.com/${
? `git@${action.hostname}:${action.repositoryName}`
: `https://${`x-access-token:${action.token}`}@${action.hostname}/${
action.repositoryName
}.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. ❗`
)
}
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. */
@ -79,9 +95,9 @@ export const suppressSensitiveInformation = (
return value
}
const orderedByLength = ([action.token, action.repositoryPath].filter(
Boolean
) as string[]).sort((a, b) => b.length - a.length)
const orderedByLength = (
[action.token, action.repositoryPath].filter(Boolean) as string[]
).sort((a, b) => b.length - a.length)
for (const find of orderedByLength) {
value = replaceAll(value, find, '***')
@ -89,3 +105,14 @@ export const suppressSensitiveInformation = (
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 {ActionInterface} from './constants'
import {execute} from './execute'
import {suppressSensitiveInformation} from './util'
import {extractErrorMessage, suppressSensitiveInformation} from './util'
export class GitCheckout {
orphan = false
@ -25,7 +25,7 @@ export class GitCheckout {
export async function generateWorktree(
action: ActionInterface,
worktreedir: string,
branchExists: boolean
branchExists: unknown
): Promise<void> {
try {
info('Creating worktree…')
@ -43,28 +43,39 @@ export async function generateWorktree(
action.workspace,
action.silent
)
const checkout = new GitCheckout(action.branch)
if (branchExists) {
// There's existing data on the branch to check out
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
}
await execute(
checkout.toString(),
`${action.workspace}/${worktreedir}`,
action.silent
)
if (!branchExists) {
info(`Created the ${action.branch} branch… 🔧`)
// Our index is in HEAD state, reset
await execute(
'git reset --hard',
`${action.workspace}/${worktreedir}`,
action.silent
)
if (!action.singleCommit) {
// New history isn't singleCommit, create empty initial commit
await execute(
@ -77,7 +88,7 @@ export async function generateWorktree(
} catch (error) {
throw new Error(
`There was an error creating the worktree: ${suppressSensitiveInformation(
error.message,
extractErrorMessage(error),
action
)} `
)

View File

@ -1,63 +1,12 @@
{
"compilerOptions": {
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "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. */
"target": "es6",
"module": "commonjs",
"outDir": "./lib",
"rootDir": "./src",
"strict": true,
"noImplicitAny": false,
"esModuleInterop": true
},
"exclude": ["node_modules", "**/*.test.ts"]
}

2984
yarn.lock

File diff suppressed because it is too large Load Diff