mirror of
https://github.com/JamesIves/github-pages-deploy-action.git
synced 2023-12-15 20:03:39 +08:00
Merge branch 'dev' into releases/v3
This commit is contained in:
commit
e45a9df141
@ -1,6 +1,6 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"plugins": ["jest", "@typescript-eslint", "github"],
|
||||
"extends": ["plugin:github/recommended"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
@ -19,13 +19,17 @@
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"@typescript-eslint/ban-ts-comment": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@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/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
@ -50,7 +54,8 @@
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error",
|
||||
"no-console": "off"
|
||||
"no-console": "off",
|
||||
"no-shadow": ["error", { "builtinGlobals": false, "hoist": "all", "allow": ["Status"] }]
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
|
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [JamesIves]
|
2
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
2
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
@ -6,7 +6,7 @@ labels:
|
||||
|
||||
---
|
||||
|
||||
<!-- Please check the FAQ before posting an issue: https://github.com/JamesIves/github-pages-deploy-action/wiki -->
|
||||
<!-- 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**
|
||||
<!-- Please provide a clear and concise description of what the bug is. -->
|
||||
|
18
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
18
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: If you'd like to make a suggestion please fill out the form below.
|
||||
labels:
|
||||
- feature request
|
||||
|
||||
---
|
||||
|
||||
<!-- Please check the FAQ before posting an issue: https://github.com/JamesIves/github-pages-deploy-action/wiki -->
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
<!-- Please provide a clear and concise description of what the problem is. Please be sure to read the README first! -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
<!-- Please provide a clear and concise description of what you want to happen. -->
|
||||
|
||||
**Additional Comments**
|
||||
<!-- Add any other context about the feature request here. -->
|
18
.github/ISSUE_TEMPLATE/SUPPORT.md
vendored
18
.github/ISSUE_TEMPLATE/SUPPORT.md
vendored
@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Support
|
||||
about: If you're having problems setting up the action you can make a request for support here.
|
||||
labels:
|
||||
- support
|
||||
|
||||
---
|
||||
|
||||
<!-- Please check the FAQ before posting an issue: https://github.com/JamesIves/github-pages-deploy-action/wiki -->
|
||||
|
||||
**Describe the Issue**
|
||||
<!-- Please provide a clear and concise description of what the problem is. Please be sure to read the README first! -->
|
||||
|
||||
**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. -->
|
||||
|
||||
**Additional Comments**
|
||||
<!-- Add any other context about the issue here. -->
|
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request and Ideas
|
||||
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.
|
||||
|
||||
- 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.
|
||||
|
8
.github/dependabot.yml
vendored
Normal file
8
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "10:00"
|
||||
open-pull-requests-limit: 10
|
@ -1,7 +1,7 @@
|
||||
# Contributing ✏️
|
||||
|
||||
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.
|
||||
[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 🎒
|
||||
|
||||
|
48
README.md
48
README.md
@ -17,16 +17,16 @@
|
||||
<img src="https://github.com/JamesIves/github-pages-deploy-action/workflows/integration-tests/badge.svg">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/marketplace/actions/deploy-to-github-pages">
|
||||
<img src="https://img.shields.io/badge/action-marketplace-blue.svg?logo=github&color=orange">
|
||||
<a href="https://codecov.io/gh/JamesIves/github-pages-deploy-action/branch/dev">
|
||||
<img src="https://codecov.io/gh/JamesIves/github-pages-deploy-action/branch/dev/graph/badge.svg">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/JamesIves/github-pages-deploy-action/releases">
|
||||
<img src="https://img.shields.io/github/v/release/JamesIves/github-pages-deploy-action.svg?logo=github">
|
||||
</a>
|
||||
|
||||
<a href="https://codecov.io/gh/JamesIves/github-pages-deploy-action/branch/dev">
|
||||
<img src="https://codecov.io/gh/JamesIves/github-pages-deploy-action/branch/dev/graph/badge.svg">
|
||||
<a href="https://github.com/marketplace/actions/deploy-to-github-pages">
|
||||
<img src="https://img.shields.io/badge/action-marketplace-blue.svg?logo=github&color=orange">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@ -62,7 +62,7 @@ jobs:
|
||||
npm run build
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.1
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BRANCH: gh-pages # The branch the action should deploy to.
|
||||
@ -83,21 +83,20 @@ It's recommended that you use [Dependabot](https://dependabot.com/github-actions
|
||||
|
||||
#### 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/) by running the following command.
|
||||
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).
|
||||
|
||||
```
|
||||
yarn add @jamesives/github-pages-deploy-action
|
||||
```
|
||||
|
||||
```
|
||||
npm install @jamesives/github-pages-deploy-action
|
||||
```
|
||||
|
||||
It can then be imported into your project like so.
|
||||
|
||||
```javascript
|
||||
import run, {
|
||||
init,
|
||||
deploy,
|
||||
generateBranch,
|
||||
ActionInterface
|
||||
} from "github-pages-deploy-action";
|
||||
import run from "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.
|
||||
@ -110,11 +109,12 @@ run({
|
||||
branch: "gh-pages",
|
||||
folder: "build",
|
||||
repositoryName: "JamesIves/github-pages-deploy-action",
|
||||
silent: true,
|
||||
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). You can find the npm registry listing for the module [here](https://www.npmjs.com/package/@jamesives/github-pages-deploy-action), and the GitHub registry listing [here](https://github.com/JamesIves/github-pages-deploy-action/packages/229985).
|
||||
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 📁
|
||||
|
||||
@ -135,7 +135,7 @@ In addition to the deployment options you must also configure the following.
|
||||
| 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. **Folder paths cannot have a leading `/` or `./`**. If you wish to deploy the root directory you can place a `.` here. | `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** |
|
||||
|
||||
#### Optional Choices
|
||||
|
||||
@ -174,7 +174,7 @@ The action will export an environment variable called `DEPLOYMENT_STATUS` that y
|
||||
If you'd prefer to use an SSH deploy key as opposed to a token you must first generate a new SSH key by running the following terminal command, replacing the email with one connected to your GitHub account.
|
||||
|
||||
```bash
|
||||
ssh-keygen -t rsa -b 4096 -C "youremailhere@example.com" -N ""
|
||||
ssh-keygen -t rsa -m pem -b 4096 -C "youremailhere@example.com" -N ""
|
||||
```
|
||||
|
||||
Once you've generated the key pair you must add the contents of the public key within your repository's [deploy keys menu](https://developer.github.com/v3/guides/managing-deploy-keys/). You can find this option by going to `Settings > Deploy Keys`, you can name the public key whatever you want, but you **do** need to give it write access. Afterwards add the contents of the private key to the `Settings > Secrets` menu as `DEPLOY_KEY`.
|
||||
@ -183,12 +183,12 @@ With this configured you must add the `ssh-agent` step to your workflow and set
|
||||
|
||||
```yml
|
||||
- name: Install SSH Client 🔑
|
||||
uses: webfactory/ssh-agent@v0.2.0
|
||||
uses: webfactory/ssh-agent@v0.4.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.1
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||
with:
|
||||
SSH: true
|
||||
BRANCH: gh-pages
|
||||
@ -224,7 +224,7 @@ jobs:
|
||||
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.1
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||
with:
|
||||
BASE_BRANCH: master
|
||||
BRANCH: gh-pages
|
||||
@ -291,7 +291,7 @@ jobs:
|
||||
name: site
|
||||
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.1
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||
with:
|
||||
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
@ -313,7 +313,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@3.6.1
|
||||
uses: JamesIves/github-pages-deploy-action@3.6.2
|
||||
```
|
||||
|
||||
---
|
||||
@ -329,3 +329,11 @@ If you wish to remove these files you must go into the deployment branch directl
|
||||
### Debugging 🐝
|
||||
|
||||
If you'd like to enable action debugging you can set the `ACTIONS_STEP_DEBUG` environment variable to true within the [Settings/Secrets](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets) menu. If you're using this action in your own project as a node module via yarn or npm **you may expose your secrets if you toggle this on in a production environment**. You can learn more about debugging GitHub actions [here](https://github.com/actions/toolkit/blob/master/docs/action-debugging.md).
|
||||
|
||||
---
|
||||
|
||||
## Support 💖
|
||||
|
||||
This project would not be possible without all of our fantastic [contributors](https://github.com/JamesIves/github-pages-deploy-action/graphs/contributors).
|
||||
|
||||
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.
|
@ -23,6 +23,7 @@ jest.mock('@actions/io', () => ({
|
||||
}))
|
||||
|
||||
jest.mock('../src/execute', () => ({
|
||||
__esModule: true,
|
||||
execute: jest.fn()
|
||||
}))
|
||||
|
||||
@ -32,216 +33,6 @@ describe('git', () => {
|
||||
})
|
||||
|
||||
describe('init', () => {
|
||||
it('should execute commands if a GitHub token is provided', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
await init(action)
|
||||
expect(execute).toBeCalledTimes(6)
|
||||
})
|
||||
|
||||
it('should execute commands if an Access Token is provided', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
accessToken: '123',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
await init(action)
|
||||
expect(execute).toBeCalledTimes(6)
|
||||
})
|
||||
|
||||
it('should execute commands if SSH is true', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
ssh: true,
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
await init(action)
|
||||
|
||||
expect(execute).toBeCalledTimes(6)
|
||||
})
|
||||
|
||||
it('should fail if there is no provided GitHub Token, Access Token or SSH bool', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: null,
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
'There was an error initializing the repository: 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. ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if access token is defined but it is an empty string', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: null,
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
accessToken: ''
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
'There was an error initializing the repository: 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. ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if there is no folder', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
gitHubToken: '123',
|
||||
branch: 'branch',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
folder: null,
|
||||
ssh: true
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
'There was an error initializing the repository: You must provide the action with a folder to deploy. ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if there is no provided repository path', async () => {
|
||||
Object.assign(action, {
|
||||
silent: true,
|
||||
repositoryPath: null,
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
gitHubToken: '123',
|
||||
accessToken: null,
|
||||
ssh: null
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
'There was an error initializing the repository: 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. '
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if the build folder begins with a /', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
accessToken: '123',
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
branch: 'branch',
|
||||
folder: '/',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
"There was an error initializing the repository: Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly. ❌"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if the build folder begins with a ./', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
accessToken: '123',
|
||||
branch: 'branch',
|
||||
folder: './',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
"There was an error initializing the repository: Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly. ❌"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should not fail if root is used', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
accessToken: '123',
|
||||
branch: 'branch',
|
||||
folder: '.',
|
||||
root: '.',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
await init(action)
|
||||
|
||||
expect(execute).toBeCalledTimes(6)
|
||||
})
|
||||
|
||||
it('should stash changes if preserve is true', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
@ -258,9 +49,36 @@ describe('git', () => {
|
||||
})
|
||||
|
||||
await init(action)
|
||||
|
||||
expect(execute).toBeCalledTimes(7)
|
||||
})
|
||||
|
||||
it('should catch when a function throws an error', async () => {
|
||||
;(execute as jest.Mock).mockImplementationOnce(() => {
|
||||
throw new Error('Mocked throw')
|
||||
})
|
||||
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
repositoryPath: 'JamesIves/github-pages-deploy-action',
|
||||
accessToken: '123',
|
||||
branch: 'branch',
|
||||
folder: '.',
|
||||
preserve: true,
|
||||
isTest: true,
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
await init(action)
|
||||
} catch (error) {
|
||||
expect(error.message).toBe(
|
||||
'There was an error initializing the repository: Mocked throw ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('generateBranch', () => {
|
||||
@ -280,11 +98,15 @@ describe('git', () => {
|
||||
expect(execute).toBeCalledTimes(6)
|
||||
})
|
||||
|
||||
it('should fail if there is no branch', async () => {
|
||||
it('should catch when a function throws an error', async () => {
|
||||
;(execute as jest.Mock).mockImplementationOnce(() => {
|
||||
throw new Error('Mocked throw')
|
||||
})
|
||||
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
accessToken: '123',
|
||||
branch: null,
|
||||
branch: 'branch',
|
||||
folder: '.',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
@ -294,9 +116,9 @@ describe('git', () => {
|
||||
|
||||
try {
|
||||
await generateBranch(action)
|
||||
} catch (e) {
|
||||
expect(e.message).toMatch(
|
||||
'There was an error creating the deployment branch: Branch is required. ❌'
|
||||
} catch (error) {
|
||||
expect(error.message).toBe(
|
||||
'There was an error creating the deployment branch: There was an error switching to the base branch: Mocked throw ❌ ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
@ -336,15 +158,17 @@ describe('git', () => {
|
||||
expect(execute).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should fail if one of the required parameters is not available', async () => {
|
||||
it('should catch when a function throws an error', async () => {
|
||||
;(execute as jest.Mock).mockImplementationOnce(() => {
|
||||
throw new Error('Mocked throw')
|
||||
})
|
||||
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
baseBranch: '123',
|
||||
accessToken: null,
|
||||
gitHubToken: null,
|
||||
ssh: null,
|
||||
accessToken: '123',
|
||||
branch: 'branch',
|
||||
folder: null,
|
||||
folder: '.',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
@ -353,10 +177,9 @@ describe('git', () => {
|
||||
|
||||
try {
|
||||
await switchToBaseBranch(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(0)
|
||||
expect(e.message).toMatch(
|
||||
'There was an error switching to the base branch: 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. ❌'
|
||||
} catch (error) {
|
||||
expect(error.message).toBe(
|
||||
'There was an error switching to the base branch: Mocked throw ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
@ -388,6 +211,7 @@ describe('git', () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folderPath: 'assets',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
lfs: true,
|
||||
@ -407,26 +231,33 @@ describe('git', () => {
|
||||
expect(response).toBe(Status.SUCCESS)
|
||||
})
|
||||
|
||||
it('should not ignore CNAME or nojekyll if they exist in the deployment folder', async () => {
|
||||
it('should appropriately move along if git stash errors', async () => {
|
||||
;(execute as jest.Mock).mockImplementation(cmd => {
|
||||
if (cmd === 'git stash apply') {
|
||||
// Mocks the case where git stash apply errors.
|
||||
throw new Error()
|
||||
}
|
||||
})
|
||||
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folderPath: 'assets',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
lfs: true,
|
||||
preserve: true,
|
||||
isTest: true,
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
clean: true
|
||||
}
|
||||
})
|
||||
|
||||
const response = await deploy(action)
|
||||
|
||||
fs.createWriteStream('assets/.nojekyll')
|
||||
fs.createWriteStream('assets/CNAME')
|
||||
|
||||
// Includes the call to generateBranch
|
||||
expect(execute).toBeCalledTimes(12)
|
||||
expect(execute).toBeCalledTimes(14)
|
||||
expect(rmRF).toBeCalledTimes(1)
|
||||
expect(response).toBe(Status.SUCCESS)
|
||||
})
|
||||
@ -434,14 +265,16 @@ describe('git', () => {
|
||||
it('should execute commands with single commit toggled', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folder: 'other',
|
||||
folderPath: 'other',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
singleCommit: true,
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
}
|
||||
},
|
||||
clean: true
|
||||
})
|
||||
|
||||
await deploy(action)
|
||||
@ -451,11 +284,37 @@ describe('git', () => {
|
||||
expect(rmRF).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should not ignore CNAME or nojekyll if they exist in the deployment folder', async () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folderPath: 'assets',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
clean: true
|
||||
})
|
||||
|
||||
fs.createWriteStream('assets/.nojekyll')
|
||||
fs.createWriteStream('assets/CNAME')
|
||||
|
||||
const response = await deploy(action)
|
||||
|
||||
// Includes the call to generateBranch
|
||||
expect(execute).toBeCalledTimes(12)
|
||||
expect(rmRF).toBeCalledTimes(1)
|
||||
expect(response).toBe(Status.SUCCESS)
|
||||
})
|
||||
|
||||
it('should execute commands with clean options, ommits sha commit message', async () => {
|
||||
process.env.GITHUB_SHA = ''
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folder: 'other',
|
||||
folderPath: 'other',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
pusher: {
|
||||
@ -463,7 +322,8 @@ describe('git', () => {
|
||||
email: 'as@cat'
|
||||
},
|
||||
clean: true,
|
||||
cleanExclude: '["cat", "montezuma"]'
|
||||
cleanExclude: '["cat", "montezuma"]',
|
||||
workspace: 'other'
|
||||
})
|
||||
|
||||
await deploy(action)
|
||||
@ -477,6 +337,7 @@ describe('git', () => {
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
folderPath: 'assets',
|
||||
branch: 'branch',
|
||||
gitHubToken: '123',
|
||||
pusher: {
|
||||
@ -534,28 +395,28 @@ describe('git', () => {
|
||||
expect(response).toBe(Status.SKIPPED)
|
||||
})
|
||||
|
||||
it('should throw an error if one of the required parameters is not available', async () => {
|
||||
it('should catch when a function throws an error', async () => {
|
||||
;(execute as jest.Mock).mockImplementationOnce(() => {
|
||||
throw new Error('Mocked throw')
|
||||
})
|
||||
|
||||
Object.assign(action, {
|
||||
silent: false,
|
||||
folder: 'assets',
|
||||
branch: 'branch',
|
||||
ssh: null,
|
||||
accessToken: null,
|
||||
gitHubToken: null,
|
||||
gitHubToken: '123',
|
||||
lfs: true,
|
||||
pusher: {
|
||||
name: 'asd',
|
||||
email: 'as@cat'
|
||||
},
|
||||
isTest: false // Setting this env variable to false means there will never be anything to commit and the action will exit early.
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
await deploy(action)
|
||||
} catch (e) {
|
||||
expect(execute).toBeCalledTimes(1)
|
||||
expect(rmRF).toBeCalledTimes(1)
|
||||
expect(e.message).toMatch(
|
||||
'The deploy step encountered an error: 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. ❌'
|
||||
} catch (error) {
|
||||
expect(error.message).toBe(
|
||||
'The deploy step encountered an error: Mocked throw ❌'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -1,8 +1,11 @@
|
||||
import {ActionInterface} from '../src/constants'
|
||||
import {
|
||||
isNullOrUndefined,
|
||||
generateTokenType,
|
||||
generateRepositoryPath,
|
||||
suppressSensitiveInformation
|
||||
generateFolderPath,
|
||||
suppressSensitiveInformation,
|
||||
checkParameters
|
||||
} from '../src/util'
|
||||
|
||||
describe('util', () => {
|
||||
@ -21,13 +24,17 @@ describe('util', () => {
|
||||
const value = 'montezuma'
|
||||
expect(isNullOrUndefined(value)).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should return false if the value is empty string', async () => {
|
||||
const value = ''
|
||||
expect(isNullOrUndefined(value)).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('generateTokenType', () => {
|
||||
it('should return ssh if ssh is provided', async () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
@ -41,7 +48,6 @@ describe('util', () => {
|
||||
it('should return access token if access token is provided', async () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
@ -55,7 +61,6 @@ describe('util', () => {
|
||||
it('should return github token if github token is provided', async () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: '123',
|
||||
@ -69,7 +74,6 @@ describe('util', () => {
|
||||
it('should return ... if no token is provided', async () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
@ -86,7 +90,6 @@ describe('util', () => {
|
||||
const action = {
|
||||
repositoryName: 'JamesIves/github-pages-deploy-action',
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
@ -103,7 +106,6 @@ describe('util', () => {
|
||||
const action = {
|
||||
repositoryName: 'JamesIves/github-pages-deploy-action',
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
@ -120,7 +122,6 @@ describe('util', () => {
|
||||
const action = {
|
||||
repositoryName: 'JamesIves/github-pages-deploy-action',
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: '123',
|
||||
@ -140,7 +141,6 @@ describe('util', () => {
|
||||
repositoryPath:
|
||||
'https://x-access-token:supersecret999%%%@github.com/anothersecret123333',
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
accessToken: 'supersecret999%%%',
|
||||
@ -160,7 +160,6 @@ describe('util', () => {
|
||||
repositoryPath:
|
||||
'https://x-access-token:supersecret999%%%@github.com/anothersecret123333',
|
||||
branch: '123',
|
||||
root: '.',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
accessToken: 'supersecret999%%%',
|
||||
@ -177,4 +176,154 @@ describe('util', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('generateFolderPath', () => {
|
||||
it('should return absolute path if folder name is provided', () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
workspace: 'src/',
|
||||
folder: 'build',
|
||||
gitHubToken: null,
|
||||
accessToken: null,
|
||||
ssh: null,
|
||||
silent: false
|
||||
}
|
||||
expect(generateFolderPath(action)).toEqual('src/build')
|
||||
})
|
||||
|
||||
it('should return original path if folder name begins with /', () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
workspace: 'src/',
|
||||
folder: '/home/user/repo/build',
|
||||
gitHubToken: null,
|
||||
accessToken: null,
|
||||
ssh: null,
|
||||
silent: false
|
||||
}
|
||||
expect(generateFolderPath(action)).toEqual('/home/user/repo/build')
|
||||
})
|
||||
|
||||
it('should process as relative path if folder name begins with ./', () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
workspace: 'src/',
|
||||
folder: './build',
|
||||
gitHubToken: null,
|
||||
accessToken: null,
|
||||
ssh: null,
|
||||
silent: false
|
||||
}
|
||||
expect(generateFolderPath(action)).toEqual('src/build')
|
||||
})
|
||||
|
||||
it('should return absolute path if folder name begins with ~', () => {
|
||||
const action = {
|
||||
branch: '123',
|
||||
workspace: 'src/',
|
||||
folder: '~/repo/build',
|
||||
gitHubToken: null,
|
||||
accessToken: null,
|
||||
ssh: null,
|
||||
silent: false
|
||||
}
|
||||
process.env.HOME = '/home/user'
|
||||
expect(generateFolderPath(action)).toEqual('/home/user/repo/build')
|
||||
})
|
||||
})
|
||||
|
||||
describe('hasRequiredParameters', () => {
|
||||
it('should fail if there is no provided GitHub Token, Access Token or SSH bool', () => {
|
||||
const action = {
|
||||
silent: false,
|
||||
repositoryPath: undefined,
|
||||
branch: 'branch',
|
||||
folder: 'build',
|
||||
workspace: 'src/'
|
||||
}
|
||||
|
||||
try {
|
||||
checkParameters(action)
|
||||
} catch (e) {
|
||||
expect(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.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if access token is defined but it is an empty string', () => {
|
||||
const action = {
|
||||
silent: false,
|
||||
repositoryPath: undefined,
|
||||
accessToken: '',
|
||||
branch: 'branch',
|
||||
folder: 'build',
|
||||
workspace: 'src/'
|
||||
}
|
||||
|
||||
try {
|
||||
checkParameters(action)
|
||||
} catch (e) {
|
||||
expect(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.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if there is no branch', () => {
|
||||
const action = {
|
||||
silent: false,
|
||||
repositoryPath: undefined,
|
||||
accessToken: '123',
|
||||
branch: '',
|
||||
folder: 'build',
|
||||
workspace: 'src/'
|
||||
}
|
||||
|
||||
try {
|
||||
checkParameters(action)
|
||||
} catch (e) {
|
||||
expect(e.message).toMatch('Branch is required.')
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if there is no folder', () => {
|
||||
const action = {
|
||||
silent: false,
|
||||
repositoryPath: undefined,
|
||||
gitHubToken: '123',
|
||||
branch: 'branch',
|
||||
folder: '',
|
||||
workspace: 'src/'
|
||||
}
|
||||
|
||||
try {
|
||||
checkParameters(action)
|
||||
} catch (e) {
|
||||
expect(e.message).toMatch(
|
||||
'You must provide the action with a folder to deploy.'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should fail if the folder does not exist in the tree', () => {
|
||||
const action: ActionInterface = {
|
||||
silent: false,
|
||||
repositoryPath: undefined,
|
||||
gitHubToken: '123',
|
||||
branch: 'branch',
|
||||
folder: 'notARealFolder',
|
||||
workspace: '.'
|
||||
}
|
||||
|
||||
try {
|
||||
action.folderPath = generateFolderPath(action)
|
||||
checkParameters(action)
|
||||
} catch (e) {
|
||||
expect(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. ❗`
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
15
package.json
15
package.json
@ -2,12 +2,12 @@
|
||||
"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.6.1",
|
||||
"version": "3.6.2",
|
||||
"license": "MIT",
|
||||
"main": "lib/lib.js",
|
||||
"types": "lib/lib.d.ts",
|
||||
"scripts": {
|
||||
"build": "rm -rf lib && tsc --declaration",
|
||||
"build": "rimraf lib && tsc --declaration",
|
||||
"test": "jest",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"format": "prettier --write './**/*.ts'"
|
||||
@ -40,14 +40,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "26.0.14",
|
||||
"@types/node": "14.11.2",
|
||||
"eslint": "7.9.0",
|
||||
"eslint-plugin-github": "3.4.1",
|
||||
"eslint-plugin-jest": "24.0.2",
|
||||
"@types/node": "14.11.8",
|
||||
"eslint": "7.11.0",
|
||||
"eslint-plugin-github": "4.1.1",
|
||||
"eslint-plugin-jest": "24.1.0",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"jest": "25.5.4",
|
||||
"jest-circus": "26.4.2",
|
||||
"jest-circus": "26.5.3",
|
||||
"prettier": "2.1.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "25.5.1",
|
||||
"typescript": "3.9.7"
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ export interface ActionInterface {
|
||||
email?: string
|
||||
/** The folder to deploy. */
|
||||
folder: string
|
||||
/** The auto generated folder path. */
|
||||
folderPath?: string
|
||||
/** GitHub deployment token. */
|
||||
gitHubToken?: string | null
|
||||
/** Determines if the action is running in test mode or not. */
|
||||
@ -38,8 +40,6 @@ export interface ActionInterface {
|
||||
repositoryName?: string
|
||||
/** The fully qualified repositpory path, this gets auto generated if repositoryName is provided. */
|
||||
repositoryPath?: string
|
||||
/** The root directory where your project lives. */
|
||||
root?: string
|
||||
/** Wipes the commit history from the deployment branch in favor of a single commit. */
|
||||
singleCommit?: boolean | null
|
||||
/** Determines if the action should run in silent mode or not. */
|
||||
@ -54,6 +54,26 @@ export interface ActionInterface {
|
||||
workspace: string
|
||||
}
|
||||
|
||||
/** The minimum required values to run the action as a node module. */
|
||||
export interface NodeActionInterface {
|
||||
/** Deployment access token. */
|
||||
accessToken?: string | null
|
||||
/** The branch that the action should deploy to. */
|
||||
branch: string
|
||||
/** The folder to deploy. */
|
||||
folder: string
|
||||
/** GitHub deployment token. */
|
||||
gitHubToken?: string | null
|
||||
/** The repository path, for example JamesIves/github-pages-deploy-action. */
|
||||
repositoryName: string
|
||||
/** Determines if the action should run in silent mode or not. */
|
||||
silent: boolean
|
||||
/** Set to true if you're using an ssh client in your build step. */
|
||||
ssh?: boolean | null
|
||||
/** The folder where your deployment project lives. */
|
||||
workspace: string
|
||||
}
|
||||
|
||||
/* Required action data that gets initialized when running within the GitHub Actions environment. */
|
||||
export const action: ActionInterface = {
|
||||
accessToken: getInput('ACCESS_TOKEN'),
|
||||
@ -95,7 +115,6 @@ export const action: ActionInterface = {
|
||||
: repository && repository.full_name
|
||||
? repository.full_name
|
||||
: process.env.GITHUB_REPOSITORY,
|
||||
root: '.',
|
||||
singleCommit: !isNullOrUndefined(getInput('SINGLE_COMMIT'))
|
||||
? getInput('SINGLE_COMMIT').toLowerCase() === 'true'
|
||||
: false,
|
||||
@ -109,6 +128,12 @@ export const action: ActionInterface = {
|
||||
workspace: process.env.GITHUB_WORKSPACE || ''
|
||||
}
|
||||
|
||||
/** Types for the required action parameters. */
|
||||
export type RequiredActionParameters = Pick<
|
||||
ActionInterface,
|
||||
'accessToken' | 'gitHubToken' | 'ssh' | 'branch' | 'folder'
|
||||
>
|
||||
|
||||
/** Status codes for the action. */
|
||||
export enum Status {
|
||||
SUCCESS = 'success',
|
||||
|
28
src/git.ts
28
src/git.ts
@ -3,17 +3,11 @@ import {mkdirP, rmRF} from '@actions/io'
|
||||
import fs from 'fs'
|
||||
import {ActionInterface, Status} from './constants'
|
||||
import {execute} from './execute'
|
||||
import {
|
||||
hasRequiredParameters,
|
||||
isNullOrUndefined,
|
||||
suppressSensitiveInformation
|
||||
} from './util'
|
||||
import {isNullOrUndefined, suppressSensitiveInformation} from './util'
|
||||
|
||||
/* Initializes git in the workspace. */
|
||||
export async function init(action: ActionInterface): Promise<void | Error> {
|
||||
try {
|
||||
hasRequiredParameters(action)
|
||||
|
||||
info(`Deploying using ${action.tokenType}… 🔑`)
|
||||
info('Configuring git…')
|
||||
|
||||
@ -72,8 +66,6 @@ export async function switchToBaseBranch(
|
||||
action: ActionInterface
|
||||
): Promise<void> {
|
||||
try {
|
||||
hasRequiredParameters(action)
|
||||
|
||||
await execute(
|
||||
`git checkout --progress --force ${
|
||||
action.baseBranch ? action.baseBranch : action.defaultBranch
|
||||
@ -94,8 +86,6 @@ export async function switchToBaseBranch(
|
||||
/* Generates the branch if it doesn't exist on the remote. */
|
||||
export async function generateBranch(action: ActionInterface): Promise<void> {
|
||||
try {
|
||||
hasRequiredParameters(action)
|
||||
|
||||
info(`Creating the ${action.branch} branch…`)
|
||||
|
||||
await switchToBaseBranch(action)
|
||||
@ -139,8 +129,6 @@ export async function deploy(action: ActionInterface): Promise<Status> {
|
||||
info('Starting to commit changes…')
|
||||
|
||||
try {
|
||||
hasRequiredParameters(action)
|
||||
|
||||
const commitMessage = !isNullOrUndefined(action.commitMessage)
|
||||
? (action.commitMessage as string)
|
||||
: `Deploying to ${action.branch} from ${action.baseBranch} ${
|
||||
@ -185,10 +173,6 @@ export async function deploy(action: ActionInterface): Promise<Status> {
|
||||
|
||||
try {
|
||||
await execute(`git stash apply`, action.workspace, action.silent)
|
||||
|
||||
if (action.isTest) {
|
||||
throw new Error()
|
||||
}
|
||||
} catch {
|
||||
info('Unable to apply from stash, continuing…')
|
||||
}
|
||||
@ -229,22 +213,24 @@ export async function deploy(action: ActionInterface): Promise<Status> {
|
||||
Allows the user to specify the root if '.' is provided.
|
||||
rsync is used to prevent file duplication. */
|
||||
await execute(
|
||||
`rsync -q -av --checksum --progress ${action.folder}/. ${
|
||||
`rsync -q -av --checksum --progress ${action.folderPath}/. ${
|
||||
action.targetFolder
|
||||
? `${temporaryDeploymentDirectory}/${action.targetFolder}`
|
||||
: temporaryDeploymentDirectory
|
||||
} ${
|
||||
action.clean
|
||||
? `--delete ${excludes} ${
|
||||
!fs.existsSync(`${action.folder}/CNAME`) ? '--exclude CNAME' : ''
|
||||
!fs.existsSync(`${action.folderPath}/CNAME`)
|
||||
? '--exclude CNAME'
|
||||
: ''
|
||||
} ${
|
||||
!fs.existsSync(`${action.folder}/.nojekyll`)
|
||||
!fs.existsSync(`${action.folderPath}/.nojekyll`)
|
||||
? '--exclude .nojekyll'
|
||||
: ''
|
||||
}`
|
||||
: ''
|
||||
} --exclude .ssh --exclude .git --exclude .github ${
|
||||
action.folder === action.root
|
||||
action.folderPath === action.workspace
|
||||
? `--exclude ${temporaryDeploymentDirectory}`
|
||||
: ''
|
||||
}`,
|
||||
|
33
src/lib.ts
33
src/lib.ts
@ -1,14 +1,19 @@
|
||||
import {exportVariable, info, setFailed} from '@actions/core'
|
||||
import {action, ActionInterface, Status} from './constants'
|
||||
import {deploy, generateBranch, init} from './git'
|
||||
import {generateRepositoryPath, generateTokenType} from './util'
|
||||
import {ActionInterface, Status, NodeActionInterface} from './constants'
|
||||
import {deploy, init} from './git'
|
||||
import {
|
||||
generateFolderPath,
|
||||
checkParameters,
|
||||
generateRepositoryPath,
|
||||
generateTokenType
|
||||
} from './util'
|
||||
|
||||
/** Initializes and runs the action.
|
||||
*
|
||||
* @param {object} configuration - The action configuration.
|
||||
*/
|
||||
export default async function run(
|
||||
configuration: ActionInterface
|
||||
configuration: ActionInterface | NodeActionInterface
|
||||
): Promise<void> {
|
||||
let status: Status = Status.RUNNING
|
||||
|
||||
@ -17,20 +22,24 @@ export default async function run(
|
||||
GitHub Pages Deploy Action 🚀
|
||||
|
||||
🚀 Getting Started Guide: https://github.com/marketplace/actions/deploy-to-github-pages
|
||||
❓ FAQ/Wiki: https://github.com/JamesIves/github-pages-deploy-action/wiki
|
||||
🔧 Support: https://github.com/JamesIves/github-pages-deploy-action/issues
|
||||
⭐ Contribute: https://github.com/JamesIves/github-pages-deploy-action/blob/dev/CONTRIBUTING.md
|
||||
❓ 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`)
|
||||
|
||||
info('Checking configuration and starting deployment… 🚦')
|
||||
|
||||
const settings = {
|
||||
...action,
|
||||
const settings: ActionInterface = {
|
||||
...configuration
|
||||
}
|
||||
|
||||
// Defines the repository paths and token types.
|
||||
// Defines the repository/folder paths and token types.
|
||||
// Also verifies that the action has all of the required parameters.
|
||||
settings.folderPath = generateFolderPath(settings)
|
||||
|
||||
checkParameters(settings)
|
||||
|
||||
settings.repositoryPath = generateRepositoryPath(settings)
|
||||
settings.tokenType = generateTokenType(settings)
|
||||
|
||||
@ -53,5 +62,3 @@ export default async function run(
|
||||
exportVariable('DEPLOYMENT_STATUS', status)
|
||||
}
|
||||
}
|
||||
|
||||
export {init, deploy, generateBranch, ActionInterface}
|
||||
|
44
src/util.ts
44
src/util.ts
@ -1,6 +1,9 @@
|
||||
import {existsSync} from 'fs'
|
||||
import path from 'path'
|
||||
import {isDebug} from '@actions/core'
|
||||
import {ActionInterface} from './constants'
|
||||
import {ActionInterface, RequiredActionParameters} 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)
|
||||
|
||||
@ -26,31 +29,46 @@ export const generateRepositoryPath = (action: ActionInterface): string =>
|
||||
action.accessToken || `x-access-token:${action.gitHubToken}`
|
||||
}@github.com/${action.repositoryName}.git`
|
||||
|
||||
/* Genetate absolute folder path by the provided folder name */
|
||||
export const generateFolderPath = (action: ActionInterface): string => {
|
||||
const folderName = action['folder']
|
||||
return path.isAbsolute(folderName)
|
||||
? folderName
|
||||
: folderName.startsWith('~')
|
||||
? folderName.replace('~', process.env.HOME as string)
|
||||
: path.join(action.workspace, folderName)
|
||||
}
|
||||
|
||||
/* Checks for the required tokens and formatting. Throws an error if any case is matched. */
|
||||
export const hasRequiredParameters = (action: ActionInterface): void => {
|
||||
if (
|
||||
(isNullOrUndefined(action.accessToken) &&
|
||||
isNullOrUndefined(action.gitHubToken) &&
|
||||
isNullOrUndefined(action.ssh)) ||
|
||||
isNullOrUndefined(action.repositoryPath) ||
|
||||
(action.accessToken && action.accessToken === '')
|
||||
) {
|
||||
const hasRequiredParameters = <K extends keyof RequiredActionParameters>(
|
||||
action: ActionInterface,
|
||||
params: K[]
|
||||
): boolean => {
|
||||
const nonNullParams = params.filter(
|
||||
param => !isNullOrUndefined(action[param])
|
||||
)
|
||||
return Boolean(nonNullParams.length)
|
||||
}
|
||||
|
||||
/* Verifies the action has the required parameters to run, otherwise throw an error. */
|
||||
export const checkParameters = (action: ActionInterface): void => {
|
||||
if (!hasRequiredParameters(action, ['accessToken', 'gitHubToken', 'ssh'])) {
|
||||
throw new Error(
|
||||
'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.'
|
||||
)
|
||||
}
|
||||
|
||||
if (isNullOrUndefined(action.branch)) {
|
||||
if (!hasRequiredParameters(action, ['branch'])) {
|
||||
throw new Error('Branch is required.')
|
||||
}
|
||||
|
||||
if (!action.folder || isNullOrUndefined(action.folder)) {
|
||||
if (!hasRequiredParameters(action, ['folder'])) {
|
||||
throw new Error('You must provide the action with a folder to deploy.')
|
||||
}
|
||||
|
||||
if (action.folder.startsWith('/') || action.folder.startsWith('./')) {
|
||||
if (!existsSync(action.folderPath as string)) {
|
||||
throw new Error(
|
||||
"Incorrectly formatted build folder. The deployment folder cannot be prefixed with '/' or './'. Instead reference the folder name directly."
|
||||
`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. ❗`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user