Compare commits

..

No commits in common. "main" and "v2.10.0" have entirely different histories.

91 changed files with 934 additions and 18510 deletions

10
.dependabot/config.yml Normal file
View File

@ -0,0 +1,10 @@
version: 1
update_configs:
- package_manager: "docker"
directory: "/"
update_schedule: "weekly"
default_labels:
- "dependencies"
- "docker"
commit_message:
prefix: "deps"

View File

@ -1,35 +0,0 @@
{
"name": "Node.js",
"image": "docker.pkg.github.com/peaceiris/actions-gh-pages/dev:latest",
// Use 'settings' to set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [
"bungcip.better-toml",
"EditorConfig.EditorConfig",
"donjayamanne.githistory",
"eamodio.gitlens",
"oderwat.indent-rainbow",
"yzhang.markdown-all-in-one",
"shd101wyy.markdown-preview-enhanced",
"christian-kohler.path-intellisense",
"lfs.vscode-emacs-friendly",
"ms-azuretools.vscode-docker",
"dbaeumer.vscode-eslint",
"firsttris.vscode-jest-runner",
"VisualStudioExptTeam.vscodeintellicode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [3000],
// Specifies a command that should be run after the container has been created.
"postCreateCommand": "npm ci",
// Comment out the next line to run as root instead.
// "remoteUser": "runner"
}

View File

@ -1,2 +1,7 @@
.* .git
* .github
.hadolint.yaml
LICENSE
README.md
action.yml
images

View File

@ -1,13 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[Makefile]
indent_size = 4
indent_style = tab

3
.envrc
View File

@ -1,3 +0,0 @@
nvmrc=~/.nvm/nvm.sh
source $nvmrc
nvm use

View File

@ -1,26 +0,0 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"plugin:prettier/recommended"
],
"plugins": ["@typescript-eslint"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2019
},
"rules": {
}
}

View File

@ -1,52 +0,0 @@
name: User Support
description: Questions for this action
title: "support: "
labels: support
assignees: peaceiris
body:
- type: markdown
attributes:
value:
Please note we will close your issue without comment if you do not fill out the issue checklist below and provide ALL the requested information.
- type: checkboxes
attributes:
label: Checklist
description: Checklist before creating an issue.
options:
- label: "I am using the latest version of this action."
required: true
- label: "I have read the latest README and followed the instructions."
required: true
- label: "I have read the latest GitHub Actions official documentation and learned the basic spec and concepts."
required: true
- type: textarea
attributes:
label: Describe your question
description: A clear and concise description of what the question is.
validations:
required: true
- type: textarea
attributes:
label: Relevant links
description:
Links to your public repository, YAML config file, and YAML workflow file.
Please use [a permanent link](https://docs.github.com/en/github/managing-files-in-a-repository/managing-files-on-github/getting-permanent-links-to-files), not a default branch.
render: markdown
value: |
Public repository:
YAML config:
YAML workflow:
validations:
required: true
- type: textarea
attributes:
label: Relevant log output
description: Copy and paste any relevant log output here.
validations:
required: false
- type: textarea
attributes:
label: Additional context.
description: Write any other context about the question here.
validations:
required: false

View File

@ -1,52 +0,0 @@
name: Bug Report
description: Try the User Support Issue Template first.
title: 'bug: '
labels: bug
assignees: peaceiris
body:
- type: markdown
attributes:
value:
Please note we will close your issue without comment if you do not fill out the issue checklist below and provide ALL the requested information.
- type: checkboxes
attributes:
label: Checklist
description: Checklist before creating an issue.
options:
- label: "I am using the latest version of this action."
required: true
- label: "I have read the latest README and followed the instructions."
required: true
- label: "I have read the latest GitHub Actions official documentation and learned the basic spec and concepts."
required: true
- type: textarea
attributes:
label: "Describe the bug"
description: "A clear and concise description of what the bug is."
validations:
required: true
- type: textarea
attributes:
label: Relevant links
description:
Links to your public repository, YAML config file, and YAML workflow file.
Please use [a permanent link](https://docs.github.com/en/github/managing-files-in-a-repository/managing-files-on-github/getting-permanent-links-to-files), not a default branch.
render: markdown
value: |
Public repository:
YAML config:
YAML workflow:
validations:
required: true
- type: textarea
attributes:
label: Relevant log output
description: Copy and paste any relevant log output here.
validations:
required: false
- type: textarea
attributes:
label: Additional context.
description: Write any other context about the question here.
validations:
required: false

View File

@ -1,45 +0,0 @@
name: Proposal
description: Suggest an idea for this project
title: 'proposal: '
labels: proposal
assignees: peaceiris
body:
- type: markdown
attributes:
value:
Please note we will close your issue without comment if you do not fill out the issue checklist below and provide ALL the requested information.
- type: checkboxes
attributes:
label: Checklist
description: Checklist before creating an issue.
options:
- label: "I am using the latest version of this action."
required: true
- label: "I have read the latest README and followed the instructions."
required: true
- label: "I have read the latest GitHub Actions official documentation and learned the basic spec and concepts."
required: true
- type: textarea
attributes:
label: "Describe your proposal"
description: "A clear and concise description of what the proposal is."
validations:
required: true
- type: textarea
attributes:
label: "Describe the solution you'd like"
description: "A clear and concise description of what you want to happen."
validations:
required: true
- type: textarea
attributes:
label: "Describe alternatives you've considered"
description: "A clear and concise description of any alternative solutions or features you've considered."
validations:
required: false
- type: textarea
attributes:
label: "Additional context"
description: "Add any other context or screenshots about the feature request here."
validations:
required: false

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: 'Bug: This is a sample issue title'
labels: bug
assignees: peaceiris
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Your YAML file**
- A link to your repository
- A link to your YAML file
**Additional context**
Add any other context about the problem here.

View File

@ -1,14 +1,8 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Discussions - name: GitHub Actions Community Forum
url: https://github.com/peaceiris/actions-gh-pages/discussions url: https://github.community/t5/GitHub-Actions/bd-p/actions
about: Ask casual questions or share your story about the GitHub Pages Action.
- name: GitHub Actions - GitHub Support Community Forum
url: https://github.community/c/code-to-cloud/github-actions/41
about: Please ask questions about GitHub Actions here. about: Please ask questions about GitHub Actions here.
- name: GitHub Pages Documentation - name: GitHub Pages help
url: https://docs.github.com/en/pages url: https://help.github.com/en/github/working-with-github-pages
about: GitHub Pages official documentation here. about: GitHub Pages documentaion here.
- name: GitHub Actions Documentation
url: https://docs.github.com/en/actions
about: GitHub Actions official documentation here.

20
.github/ISSUE_TEMPLATE/proposal.md vendored Normal file
View File

@ -0,0 +1,20 @@
---
name: Proposal
about: Suggest an idea for this project
title: 'proposal: This is a sample title'
labels: proposal
assignees: peaceiris
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,36 +0,0 @@
labels:
- name: resolved
labeled:
issue:
body: |
This issue has been **LOCKED** because of it being resolved!
The issue has been fixed and is therefore considered resolved.
If you still encounter this or it has changed, open a new issue instead of responding to solved ones.
action: close
locking: lock
lock_reason: resolved
- name: inactive
labeled:
issue:
body: |
This issue has been marked as inactive.
If you still encounter this or it has changed, add a comment to provide further information.
- name: stale
labeled:
issue:
body: |
This issue has been **LOCKED** because of it being old.
If you still encounter this or it has changed, open a new issue.
action: close
locking: lock
lock_reason: resolved
- name: duplicate
labeled:
issue:
body: |
This issue has been closed because of duplication.
action: close
locking: lock
lock_reason: resolved

20
.github/labeler.yml vendored
View File

@ -1,20 +0,0 @@
cicd:
- .github/workflows/*
dependencies:
- .nvmrc
- package.json
- package-lock.json
documentation:
- README.md
test:
- __tests__
docker:
- .devcontainer/*
- .dockerignore
- Dockerfile
- Makefile
- docker-compose.yml

View File

@ -1,24 +0,0 @@
name: "Code Scanning"
on:
push:
branches:
- main
pull_request:
jobs:
CodeQL-Build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

View File

@ -1,16 +0,0 @@
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: 'Dependency Review'
on:
pull_request:
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4

40
.github/workflows/docker-image-ci.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: docker image ci
on:
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
push:
paths-ignore:
- '**.md'
branches:
- master
jobs:
test:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: build
env:
DOCKER_IMAGE: docker.pkg.github.com/${{ github.repository }}/action:latest
run: |
docker build . --file Dockerfile --tag ${DOCKER_IMAGE}
shellcheck:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: shellcheck
run: shellcheck ./entrypoint.sh
hadolint:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: brew install hadolint
- run: hadolint ./Dockerfile

View File

@ -1,27 +0,0 @@
name: Label Commenter
on:
issues:
types:
- labeled
- unlabeled
pull_request_target:
types:
- labeled
- unlabeled
permissions:
contents: read
issues: write
pull-requests: write
jobs:
comment:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Label Commenter
uses: peaceiris/actions-label-commenter@v1
env:
RUNNER_DEBUG: 1

View File

@ -1,22 +0,0 @@
name: "Pull Request Labeler"
on:
pull_request_target:
jobs:
triage:
runs-on: ubuntu-22.04
timeout-minutes: 1
permissions: {}
steps:
# https://github.com/peaceiris/actions-github-app-token
- uses: peaceiris/actions-github-app-token@v1.1.6
id: app
with:
app_id: ${{ secrets.GH_APP_ID }}
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
# https://github.com/actions/labeler
- uses: actions/labeler@v4
with:
repo-token: "${{ steps.app.outputs.token }}"

View File

@ -1,14 +0,0 @@
name: Check Pages Status
on: page_build
jobs:
pages-status-check:
runs-on: ubuntu-22.04
steps:
- name: check status
run: |
status = '${{ github.event.build.status }}'
errormsg = '${{ github.event.build.error.message }}'
assert status == 'built', 'Status: {status}\nError: {errormsg}'.format(status, errormsg)
shell: python

View File

@ -3,11 +3,10 @@ name: Purge image cache
on: on:
schedule: schedule:
- cron: '54 18 * * */7' - cron: '54 18 * * */7'
workflow_dispatch:
jobs: jobs:
purge: purge:
runs-on: ubuntu-22.04 runs-on: ubuntu-18.04
steps: steps:
- run: > - run: >

View File

@ -1,16 +0,0 @@
name: Release
on:
push:
tags:
- 'v3.*.*'
jobs:
release:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
# https://github.com/peaceiris/workflows/blob/main/create-release-npm/action.yml
- uses: peaceiris/workflows/create-release-npm@v0.20.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

17
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: "Stale"
on:
schedule:
- cron: "6 6 * * *"
jobs:
stale:
runs-on: ubuntu-18.04
steps:
- uses: actions/stale@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 21 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'This pull request is stale because it has been open 21 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
days-before-stale: 21
days-before-close: 7

View File

@ -1,182 +0,0 @@
name: 'Test'
on:
push:
branches:
- main
paths-ignore:
- '*.md'
pull_request:
paths-ignore:
- '*.md'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- 'ubuntu-22.04'
- 'ubuntu-20.04'
- 'ubuntu-latest'
- 'macos-latest'
- 'windows-latest'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: peaceiris/workflows/setup-node@v0.20.1
with:
node-version-file: ".nvmrc"
- name: Dump version
run: |
node -v
npm --version
git --version
- run: npm ci --ignore-scripts
- name: npm audit
if: startsWith(matrix.os, 'ubuntu-22.04')
run: |
npm audit > ./audit.log || true
if ! [ "$(cat ./audit.log | wc -l)" = 1 ]; then
echo "::warning::$(cat ./audit.log)"
fi
rm ./audit.log
- name: Run prettier
if: startsWith(matrix.os, 'ubuntu-22.04')
run: npm run format:check
- name: Run eslint
if: startsWith(matrix.os, 'ubuntu-22.04')
run: npm run lint
- run: npm test
- name: Upload test coverage as artifact
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}
path: coverage
- uses: codecov/codecov-action@v4
- name: Run ncc
run: npm run build
- name: Remove lint-staged husky
if: ${{ github.ref == 'refs/heads/main' }}
run: |
npm uninstall lint-staged husky
git checkout package-lock.json package.json
- name: Setup mdBook
if: ${{ github.ref == 'refs/heads/main' }}
uses: peaceiris/actions-mdbook@v1.2.0
with:
mdbook-version: '0.4.5'
- name: Build site
if: ${{ github.ref == 'refs/heads/main' }}
working-directory: ./test_projects/mdbook
run: mdbook build
- name: Deploy
if: |
startsWith(matrix.os, 'ubuntu-latest') &&
github.ref == 'refs/heads/main' && github.event.repository.fork == false
uses: ./
with:
# deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# publish_branch: gh-pages
publish_dir: ./test_projects/mdbook/book
# external_repository: ''
allow_empty_commit: true
# keep_files: true
# force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
# commit_message: ${{ github.event.head_commit.message }}
cname: 'actions-gh-pages.peaceiris.com'
- name: Deploy
if: |
startsWith(matrix.os, 'macos') &&
github.ref == 'refs/heads/main' && github.event.repository.fork == false
uses: ./
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
# github_token: ${{ secrets.GITHUB_TOKEN }}
# personal_token: ${{ secrets.PERSONAL_TOKEN }}
publish_branch: gh-pages-macos
publish_dir: ./test_projects/mdbook/book
# external_repository: ''
allow_empty_commit: true
# keep_files: true
# force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
# commit_message: ${{ github.event.head_commit.message }}
- name: Deploy
if: |
startsWith(matrix.os, 'windows') &&
github.ref == 'refs/heads/main' && github.event.repository.fork == false
uses: ./
with:
# deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# personal_token: ${{ secrets.PERSONAL_TOKEN }}
publish_branch: gh-pages-windows
publish_dir: ./test_projects/mdbook/book
# external_repository: ''
allow_empty_commit: true
# keep_files: true
# force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
# commit_message: ${{ github.event.head_commit.message }}
- name: Deploy
if: |
startsWith(matrix.os, 'ubuntu-20.04') &&
github.ref == 'refs/heads/main' && github.event.repository.fork == false
uses: ./
with:
# deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages-ubuntu-20.04
publish_dir: ./test_projects/mdbook/book
# external_repository: ''
allow_empty_commit: true
# keep_files: true
# force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
# commit_message: ${{ github.event.head_commit.message }}
- name: Deploy
if: |
startsWith(matrix.os, 'ubuntu-22.04') &&
github.ref == 'refs/heads/main' && github.event.repository.fork == false
uses: ./
with:
# deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages-ubuntu-22.04
publish_dir: ./test_projects/mdbook/book
# external_repository: ''
allow_empty_commit: true
# keep_files: true
# force_orphan: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
# commit_message: ${{ github.event.head_commit.message }}

View File

@ -2,21 +2,23 @@ name: Update major tag
on: on:
release: release:
types: [released] types: [published]
jobs: jobs:
update: update:
runs-on: ubuntu-22.04 runs-on: ubuntu-18.04
timeout-minutes: 1
steps: steps:
- uses: actions/checkout@v4
- name: Update major tag - uses: actions/checkout@v2
run: |
git config user.name "${GITHUB_ACTOR}" - name: Update major tag
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" if: github.event.release.prerelease == false
git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git" run: |
export TAG_NAME="${GITHUB_REF##refs/tags/}" git config user.name "${GITHUB_ACTOR}"
export TAG_MAJOR="${TAG_NAME%%.*}" git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git tag --force -a "${TAG_MAJOR}" -m "Release ${TAG_NAME}" git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git"
git push --force origin "${TAG_MAJOR}" export TAG_NAME="${GITHUB_REF##refs/tags/}"
export TAG_MAJOR="${TAG_NAME%%.*}"
git tag "${TAG_MAJOR}" -m "Release ${TAG_NAME}" || git tag -d "${TAG_MAJOR}" ; git push --delete origin "${TAG_MAJOR}"
git tag "${TAG_MAJOR}" -m "Release ${TAG_NAME}" || true
git push origin "${TAG_MAJOR}"

6
.gitignore vendored
View File

@ -1,6 +0,0 @@
.DS_Store
coverage
.npm
.eslintcache
.env
node_modules

2
.hadolint.yaml Normal file
View File

@ -0,0 +1,2 @@
ignored:
- DL3018

1
.husky/.gitignore vendored
View File

@ -1 +0,0 @@
_

View File

@ -1,2 +0,0 @@
npm install
git remote prune origin

View File

@ -1 +0,0 @@
npx lint-staged

1
.npmrc
View File

@ -1 +0,0 @@
engine-strict=true

1
.nvmrc
View File

@ -1 +0,0 @@
20.11.1

View File

@ -1,2 +0,0 @@
node_modules/
lib/

View File

@ -1,11 +0,0 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

1
.vscode/.gitignore vendored
View File

@ -1 +0,0 @@
*.log

View File

@ -1,4 +0,0 @@
{
"git.ignoreLimitWarning": true,
"deno.enable": false
}

File diff suppressed because it is too large Load Diff

10
Dockerfile Normal file
View File

@ -0,0 +1,10 @@
FROM alpine:3.11.2
RUN apk add --no-cache \
bash \
git \
openssh-client \
ca-certificates
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2019 Shohei Ueda (peaceiris) Copyright (c) 2020 Shohei Ueda (peaceiris)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

1553
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
/* CSS */

View File

@ -1 +0,0 @@
// JavaScript

View File

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>

View File

@ -1 +0,0 @@
/* CSS */

View File

@ -1 +0,0 @@
// JavaScript

View File

@ -1 +0,0 @@
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners

View File

@ -1 +0,0 @@
<!-- issue template -->

View File

@ -1,7 +0,0 @@
# dependabot config
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily

View File

@ -1 +0,0 @@
name: 'Test'

View File

@ -1 +0,0 @@
/* CSS */

View File

@ -1 +0,0 @@
// JavaScript

View File

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>

View File

@ -1 +0,0 @@
/* CSS */

View File

@ -1 +0,0 @@
// JavaScript

View File

@ -1,189 +0,0 @@
// import * as main from '../src/main';
import {Inputs} from '../src/interfaces';
import {showInputs, getInputs} from '../src/get-inputs';
import os from 'os';
import fs from 'fs';
import yaml from 'js-yaml';
beforeEach(() => {
jest.resetModules();
process.stdout.write = jest.fn();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const doc: any = yaml.load(fs.readFileSync(__dirname + '/../action.yml', 'utf8'));
Object.keys(doc.inputs).forEach(name => {
const envVar = `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
process.env[envVar] = doc.inputs[name]['default'];
});
});
afterEach(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const doc: any = yaml.load(fs.readFileSync(__dirname + '/../action.yml', 'utf8'));
Object.keys(doc.inputs).forEach(name => {
const envVar = `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
console.debug(`delete ${envVar}\t${process.env[envVar]}`);
delete process.env[envVar];
});
});
// Assert that process.stdout.write calls called only with the given arguments.
// cf. https://github.com/actions/toolkit/blob/8b0300129f08728419263b016de8630f1d426d5f/packages/core/__tests__/core.test.ts
function assertWriteCalls(calls: string[]): void {
expect(process.stdout.write).toHaveBeenCalledTimes(calls.length);
for (let i = 0; i < calls.length; i++) {
expect(process.stdout.write).toHaveBeenNthCalledWith(i + 1, calls[i]);
}
}
function getInputsLog(authMethod: string, inps: Inputs): string {
return `\
[INFO] ${authMethod}: true
[INFO] PublishBranch: ${inps.PublishBranch}
[INFO] PublishDir: ${inps.PublishDir}
[INFO] DestinationDir: ${inps.DestinationDir}
[INFO] ExternalRepository: ${inps.ExternalRepository}
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
[INFO] KeepFiles: ${inps.KeepFiles}
[INFO] ForceOrphan: ${inps.ForceOrphan}
[INFO] UserName: ${inps.UserName}
[INFO] UserEmail: ${inps.UserEmail}
[INFO] CommitMessage: ${inps.CommitMessage}
[INFO] FullCommitMessage: ${inps.FullCommitMessage}
[INFO] TagName: ${inps.TagName}
[INFO] TagMessage: ${inps.TagMessage}
[INFO] EnableJekyll (DisableNoJekyll): ${inps.DisableNoJekyll}
[INFO] CNAME: ${inps.CNAME}
[INFO] ExcludeAssets ${inps.ExcludeAssets}
`;
}
describe('showInputs()', () => {
// eslint-disable-next-line jest/expect-expect
test('print all inputs DeployKey', () => {
process.env['INPUT_DEPLOY_KEY'] = 'test_deploy_key';
const inps: Inputs = getInputs();
showInputs(inps);
const authMethod = 'DeployKey';
const test = getInputsLog(authMethod, inps);
assertWriteCalls([`${test}${os.EOL}`]);
});
// eslint-disable-next-line jest/expect-expect
test('print all inputs GithubToken', () => {
delete process.env['INPUT_DEPLOY_KEY'];
process.env['INPUT_GITHUB_TOKEN'] = 'test_github_token';
const inps: Inputs = getInputs();
showInputs(inps);
const authMethod = 'GithubToken';
const test = getInputsLog(authMethod, inps);
assertWriteCalls([`${test}${os.EOL}`]);
});
// eslint-disable-next-line jest/expect-expect
test('print all inputs PersonalToken', () => {
delete process.env['INPUT_DEPLOY_KEY'];
delete process.env['INPUT_GITHUB_TOKEN'];
process.env['INPUT_PERSONAL_TOKEN'] = 'test_personal_token';
const inps: Inputs = getInputs();
showInputs(inps);
const authMethod = 'PersonalToken';
const test = getInputsLog(authMethod, inps);
assertWriteCalls([`${test}${os.EOL}`]);
});
});
describe('getInputs()', () => {
test('get default inputs', () => {
process.env['INPUT_DEPLOY_KEY'] = 'test_deploy_key';
const inps: Inputs = getInputs();
expect(inps.DeployKey).toMatch('test_deploy_key');
expect(inps.GithubToken).toMatch('');
expect(inps.PersonalToken).toMatch('');
expect(inps.PublishBranch).toMatch('gh-pages');
expect(inps.PublishDir).toMatch('public');
expect(inps.DestinationDir).toMatch('');
expect(inps.ExternalRepository).toMatch('');
expect(inps.AllowEmptyCommit).toBe(false);
expect(inps.KeepFiles).toBe(false);
expect(inps.ForceOrphan).toBe(false);
expect(inps.UserName).toMatch('');
expect(inps.UserEmail).toMatch('');
expect(inps.CommitMessage).toMatch('');
expect(inps.FullCommitMessage).toMatch('');
expect(inps.TagName).toMatch('');
expect(inps.TagMessage).toMatch('');
expect(inps.DisableNoJekyll).toBe(false);
expect(inps.CNAME).toMatch('');
expect(inps.ExcludeAssets).toMatch('.github');
});
test('get spec inputs', () => {
// process.env['INPUT_DEPLOY_KEY'] = 'test_deploy_key';
process.env['INPUT_GITHUB_TOKEN'] = 'test_github_token';
process.env['INPUT_PERSONAL_TOKEN'] = 'test_personal_token';
process.env['INPUT_PUBLISH_BRANCH'] = 'master';
process.env['INPUT_PUBLISH_DIR'] = 'out';
process.env['INPUT_DESTINATION_DIR'] = 'subdir';
process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo';
process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true';
process.env['INPUT_KEEP_FILES'] = 'true';
process.env['INPUT_FORCE_ORPHAN'] = 'true';
process.env['INPUT_USER_NAME'] = 'username';
process.env['INPUT_USER_EMAIL'] = 'github@github.com';
process.env['INPUT_COMMIT_MESSAGE'] = 'feat: Add new feature';
process.env['INPUT_FULL_COMMIT_MESSAGE'] = 'feat: Add new feature';
process.env['INPUT_TAG_NAME'] = 'deploy-v1.2.3';
process.env['INPUT_TAG_MESSAGE'] = 'Deployment v1.2.3';
process.env['INPUT_DISABLE_NOJEKYLL'] = 'true';
process.env['INPUT_CNAME'] = 'github.com';
process.env['INPUT_EXCLUDE_ASSETS'] = '.github';
const inps: Inputs = getInputs();
expect(inps.DeployKey).toMatch('');
expect(inps.GithubToken).toMatch('test_github_token');
expect(inps.PersonalToken).toMatch('test_personal_token');
expect(inps.PublishBranch).toMatch('master');
expect(inps.PublishDir).toMatch('out');
expect(inps.DestinationDir).toMatch('subdir');
expect(inps.ExternalRepository).toMatch('user/repo');
expect(inps.AllowEmptyCommit).toBe(true);
expect(inps.KeepFiles).toBe(true);
expect(inps.ForceOrphan).toBe(true);
expect(inps.UserName).toMatch('username');
expect(inps.UserEmail).toMatch('github@github.com');
expect(inps.CommitMessage).toMatch('feat: Add new feature');
expect(inps.FullCommitMessage).toMatch('feat: Add new feature');
expect(inps.TagName).toMatch('deploy-v1.2.3');
expect(inps.TagMessage).toMatch('Deployment v1.2.3');
expect(inps.DisableNoJekyll).toBe(true);
expect(inps.CNAME).toMatch('github.com');
expect(inps.ExcludeAssets).toMatch('.github');
});
test('get spec inputs enable_jekyll', () => {
process.env['INPUT_ENABLE_JEKYLL'] = 'true';
const inps: Inputs = getInputs();
expect(inps.DisableNoJekyll).toBe(true);
});
test('throw error enable_jekyll or disable_nojekyll', () => {
process.env['INPUT_DEPLOY_KEY'] = 'test_deploy_key';
process.env['INPUT_ENABLE_JEKYLL'] = 'true';
process.env['INPUT_DISABLE_NOJEKYLL'] = 'true';
expect(() => {
getInputs();
}).toThrow('Use either of enable_jekyll or disable_nojekyll');
});
});

View File

@ -1,302 +0,0 @@
import {
copyAssets,
setRepo,
getUserName,
getUserEmail,
setCommitAuthor,
getCommitMessage
} from '../src/git-utils';
import {getInputs} from '../src/get-inputs';
import {Inputs} from '../src/interfaces';
import {getWorkDirName, createDir} from '../src/utils';
import {CmdResult} from '../src/interfaces';
import * as exec from '@actions/exec';
import {cp, rm} from 'shelljs';
import path from 'path';
import fs from 'fs';
const testRoot = path.resolve(__dirname);
async function createTestDir(name: string): Promise<string> {
const date = new Date();
const unixTime = date.getTime();
return await getWorkDirName(`${unixTime}_${name}`);
}
beforeEach(() => {
jest.resetModules();
process.env['GITHUB_ACTOR'] = 'default-octocat';
process.env['GITHUB_REPOSITORY'] = 'owner/repo';
});
afterEach(() => {
delete process.env['GITHUB_ACTOR'];
delete process.env['GITHUB_REPOSITORY'];
});
describe('copyAssets', () => {
let gitTempDir = '';
(async (): Promise<void> => {
const date = new Date();
const unixTime = date.getTime();
gitTempDir = await getWorkDirName(`${unixTime}_git`);
})();
beforeAll(async () => {
await createDir(gitTempDir);
process.chdir(gitTempDir);
await exec.exec('git', ['init']);
});
test('copy assets from publish_dir to root, delete .github', async () => {
const publishDir = await createTestDir('src');
const destDir = await createTestDir('dst');
cp('-Rf', path.resolve(testRoot, 'fixtures/publish_dir_1'), publishDir);
cp('-Rf', gitTempDir, destDir);
await copyAssets(publishDir, destDir, '.github');
expect(fs.existsSync(path.resolve(destDir, '.github'))).toBeFalsy();
expect(fs.existsSync(path.resolve(destDir, 'index.html'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.css'))).toBeTruthy();
rm('-rf', publishDir, destDir);
});
test('copy assets from publish_dir to root, delete .github,main.js', async () => {
const publishDir = await createTestDir('src');
const destDir = await createTestDir('dst');
cp('-Rf', path.resolve(testRoot, 'fixtures/publish_dir_1'), publishDir);
cp('-Rf', gitTempDir, destDir);
await copyAssets(publishDir, destDir, '.github,main.js');
expect(fs.existsSync(path.resolve(destDir, '.github'))).toBeFalsy();
expect(fs.existsSync(path.resolve(destDir, 'index.html'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'main.js'))).toBeFalsy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.css'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.js'))).toBeTruthy();
rm('-rf', publishDir, destDir);
});
test('copy assets from publish_dir to root, delete nothing', async () => {
const publishDir = await createTestDir('src');
const destDir = await createTestDir('dst');
cp('-Rf', path.resolve(testRoot, 'fixtures/publish_dir_root'), publishDir);
cp('-Rf', gitTempDir, destDir);
await copyAssets(publishDir, destDir, '');
expect(fs.existsSync(path.resolve(destDir, '.github'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'index.html'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'main.js'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.css'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.js'))).toBeTruthy();
rm('-rf', publishDir, destDir);
});
test('copy assets from root to root, delete .github', async () => {
const publishDir = await createTestDir('src');
const destDir = await createTestDir('dst');
cp('-Rf', path.resolve(testRoot, 'fixtures/publish_dir_root'), publishDir);
cp('-Rf', gitTempDir, destDir);
cp('-Rf', gitTempDir, publishDir);
await copyAssets(publishDir, destDir, '.github');
expect(fs.existsSync(path.resolve(destDir, '.github'))).toBeFalsy();
expect(fs.existsSync(path.resolve(destDir, 'index.html'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.css'))).toBeTruthy();
rm('-rf', publishDir, destDir);
});
test('copy assets from root to root, delete nothing', async () => {
const publishDir = await createTestDir('src');
const destDir = await createTestDir('dst');
cp('-Rf', path.resolve(testRoot, 'fixtures/publish_dir_root'), publishDir);
cp('-Rf', gitTempDir, destDir);
cp('-Rf', gitTempDir, publishDir);
await copyAssets(publishDir, destDir, '');
expect(fs.existsSync(path.resolve(destDir, '.github'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'index.html'))).toBeTruthy();
expect(fs.existsSync(path.resolve(destDir, 'assets/lib.css'))).toBeTruthy();
rm('-rf', publishDir, destDir);
});
test.todo('copy assets from root to subdir, delete .github');
test.todo('copy assets from root to subdir, delete .github,main.js');
test.todo('copy assets from root to subdir, delete nothing');
});
describe('setRepo()', () => {
test('throw error destination_dir should be a relative path', async () => {
process.env['INPUT_GITHUB_TOKEN'] = 'test_github_token';
process.env['INPUT_PUBLISH_BRANCH'] = 'gh-pages';
process.env['INPUT_PUBLISH_DIR'] = 'public';
process.env['INPUT_DESTINATION_DIR'] = '/subdir';
// process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo';
// process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true';
// process.env['INPUT_KEEP_FILES'] = 'true';
// process.env['INPUT_FORCE_ORPHAN'] = 'true';
// process.env['INPUT_USER_NAME'] = 'username';
// process.env['INPUT_USER_EMAIL'] = 'github@github.com';
// process.env['INPUT_COMMIT_MESSAGE'] = 'feat: Add new feature';
// process.env['INPUT_FULL_COMMIT_MESSAGE'] = 'feat: Add new feature';
// process.env['INPUT_TAG_NAME'] = 'deploy-v1.2.3';
// process.env['INPUT_TAG_MESSAGE'] = 'Deployment v1.2.3';
// process.env['INPUT_DISABLE_NOJEKYLL'] = 'true';
// process.env['INPUT_CNAME'] = 'github.com';
process.env['INPUT_EXCLUDE_ASSETS'] = '.github';
const inps: Inputs = getInputs();
const remoteURL = 'https://x-access-token:pat@github.com/actions/pages.git';
const date = new Date();
const unixTime = date.getTime();
const workDir = await getWorkDirName(`${unixTime}`);
await expect(setRepo(inps, remoteURL, workDir)).rejects.toThrow(
'destination_dir should be a relative path'
);
});
});
describe('getUserName()', () => {
test('get default git user name', () => {
const userName = '';
const test = getUserName(userName);
expect(test).toMatch('default-octocat');
});
test('get custom git user name', () => {
const userName = 'custom-octocat';
const test = getUserName(userName);
expect(test).toMatch(userName);
});
});
describe('getUserEmail()', () => {
test('get default git user email', () => {
const userEmail = '';
const test = getUserEmail(userEmail);
expect(test).toMatch('default-octocat@users.noreply.github.com');
});
test('get custom git user email', () => {
const userEmail = 'custom-octocat@github.com';
const test = getUserEmail(userEmail);
expect(test).toMatch(userEmail);
});
});
describe('setCommitAuthor()', () => {
let workDirName = '';
(async (): Promise<void> => {
const date = new Date();
const unixTime = date.getTime();
workDirName = await getWorkDirName(`${unixTime}`);
})();
beforeEach(async () => {
await createDir(workDirName);
process.chdir(workDirName);
await exec.exec('git', ['init']);
});
test('get default commit author', async () => {
const userName = '';
const userEmail = '';
const result: CmdResult = {
exitcode: 0,
output: ''
};
const options = {
listeners: {
stdout: (data: Buffer): void => {
result.output += data.toString();
}
}
};
await setCommitAuthor(userName, userEmail);
result.exitcode = await exec.exec('git', ['config', 'user.name'], options);
expect(result.output).toMatch('default-octocat');
result.exitcode = await exec.exec('git', ['config', 'user.email'], options);
expect(result.output).toMatch('default-octocat@users.noreply.github.com');
});
test('get custom commit author', async () => {
const userName = 'custom-octocat';
const userEmail = 'custom-octocat@github.com';
const result: CmdResult = {
exitcode: 0,
output: ''
};
const options = {
listeners: {
stdout: (data: Buffer): void => {
result.output += data.toString();
}
}
};
await setCommitAuthor(userName, userEmail);
result.exitcode = await exec.exec('git', ['config', 'user.name'], options);
expect(result.output).toMatch(userName);
result.exitcode = await exec.exec('git', ['config', 'user.email'], options);
expect(result.output).toMatch(userEmail);
});
test('throw error user_email is undefined', async () => {
const userName = 'custom-octocat';
const userEmail = '';
await expect(setCommitAuthor(userName, userEmail)).rejects.toThrow('user_email is undefined');
});
test('throw error user_name is undefined', async () => {
const userName = '';
const userEmail = 'custom-octocat@github.com';
await expect(setCommitAuthor(userName, userEmail)).rejects.toThrow('user_name is undefined');
});
});
describe('getCommitMessage()', () => {
test('get default message', () => {
const test = getCommitMessage('', '', '', 'actions/pages', 'commit_hash');
expect(test).toMatch('deploy: commit_hash');
});
test('get default message for external repository', () => {
const test = getCommitMessage(
'',
'',
'actions/actions.github.io',
'actions/pages',
'commit_hash'
);
expect(test).toMatch('deploy: actions/pages@commit_hash');
});
test('get custom message', () => {
const test = getCommitMessage('Custom msg', '', '', 'actions/pages', 'commit_hash');
expect(test).toMatch('Custom msg commit_hash');
});
test('get custom message for external repository', () => {
const test = getCommitMessage(
'Custom msg',
'',
'actions/actions.github.io',
'actions/pages',
'commit_hash'
);
expect(test).toMatch('Custom msg actions/pages@commit_hash');
});
test('get full custom message', () => {
const test = getCommitMessage('', 'Full custom msg', '', 'actions/pages', 'commit_hash');
expect(test).toMatch('Full custom msg');
});
test('get full custom message for external repository', () => {
const test = getCommitMessage(
'',
'Full custom msg',
'actions/actions.github.io',
'actions/pages',
'commit_hash'
);
expect(test).toMatch('Full custom msg');
});
});

View File

@ -1,37 +0,0 @@
import {setPersonalToken, setGithubToken} from '../src/set-tokens';
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...OLD_ENV};
});
afterAll(() => {
process.env = OLD_ENV; // Restore old environment
});
describe('setGithubToken()', () => {
test('return remote url with GITHUB_TOKEN gh-pages', () => {
process.env.GITHUB_SERVER_URL = 'https://github.enterprise.server';
const expected = 'https://x-access-token:GITHUB_TOKEN@github.enterprise.server/owner/repo.git';
const test = setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages',
'',
'refs/heads/master',
'push'
);
expect(test).toMatch(expected);
});
});
describe('setPersonalToken()', () => {
test('return remote url with personal access token', () => {
process.env.GITHUB_SERVER_URL = 'https://github.enterprise.server';
const expected = 'https://x-access-token:pat@github.enterprise.server/owner/repo.git';
const test = setPersonalToken('pat', 'owner/repo');
expect(test).toMatch(expected);
});
});

View File

@ -1,118 +0,0 @@
import {getPublishRepo, setPersonalToken, setGithubToken} from '../src/set-tokens';
beforeEach(() => {
jest.resetModules();
});
// afterEach(() => {
// });
describe('getPublishRepo()', () => {
test('return repository name', () => {
const test = getPublishRepo('', 'owner', 'repo');
expect(test).toMatch('owner/repo');
});
test('return external repository name', () => {
const test = getPublishRepo('extOwner/extRepo', 'owner', 'repo');
expect(test).toMatch('extOwner/extRepo');
});
});
describe('setGithubToken()', () => {
test('return remote url with GITHUB_TOKEN gh-pages', () => {
const expected = 'https://x-access-token:GITHUB_TOKEN@github.com/owner/repo.git';
const test = setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages',
'',
'refs/heads/master',
'push'
);
expect(test).toMatch(expected);
});
test('return remote url with GITHUB_TOKEN master', () => {
const expected = 'https://x-access-token:GITHUB_TOKEN@github.com/owner/repo.git';
const test = setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'master',
'',
'refs/heads/source',
'push'
);
expect(test).toMatch(expected);
});
test('return remote url with GITHUB_TOKEN gh-pages (RegExp)', () => {
const expected = 'https://x-access-token:GITHUB_TOKEN@github.com/owner/repo.git';
const test = setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages',
'',
'refs/heads/gh-pages-base',
'push'
);
expect(test).toMatch(expected);
});
test('throw error gh-pages-base to gh-pages-base (RegExp)', () => {
expect(() => {
setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages-base',
'',
'refs/heads/gh-pages-base',
'push'
);
}).toThrow('You deploy from gh-pages-base to gh-pages-base');
});
test('throw error master to master', () => {
expect(() => {
setGithubToken('GITHUB_TOKEN', 'owner/repo', 'master', '', 'refs/heads/master', 'push');
}).toThrow('You deploy from master to master');
});
test('throw error external repository with GITHUB_TOKEN', () => {
expect(() => {
setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages',
'extOwner/extRepo',
'refs/heads/master',
'push'
);
}).toThrow(`\
The generated GITHUB_TOKEN (github_token) does not support to push to an external repository.
Use deploy_key or personal_token.
`);
});
test('return remote url with GITHUB_TOKEN pull_request', () => {
const expected = 'https://x-access-token:GITHUB_TOKEN@github.com/owner/repo.git';
const test = setGithubToken(
'GITHUB_TOKEN',
'owner/repo',
'gh-pages',
'',
'refs/pull/29/merge',
'pull_request'
);
expect(test).toMatch(expected);
});
});
describe('setPersonalToken()', () => {
test('return remote url with personal access token', () => {
const expected = 'https://x-access-token:pat@github.com/owner/repo.git';
const test = setPersonalToken('pat', 'owner/repo');
expect(test).toMatch(expected);
});
});

View File

@ -1,183 +0,0 @@
import path from 'path';
import fs from 'fs';
import {
getHomeDir,
getWorkDirName,
createDir,
addNoJekyll,
addCNAME,
skipOnFork
} from '../src/utils';
beforeEach(() => {
jest.resetModules();
});
// afterEach(() => {
// });
async function getTime(): Promise<string> {
const date = new Date();
const unixTime = date.getTime();
return `${unixTime}`;
}
describe('getHomeDir()', () => {
test('get home directory name', async () => {
let test = '';
if (process.platform === 'win32') {
test = 'C:\\Users\\runneradmin';
} else {
test = `${process.env.HOME}`;
}
const expected = await getHomeDir();
expect(test).toMatch(expected);
});
});
describe('getWorkDirName()', () => {
test('get work directory name', async () => {
let home = '';
if (process.platform === 'win32') {
home = 'C:\\Users\\runneradmin';
} else {
home = `${process.env.HOME}`;
}
const unixTime = await getTime();
const expected = path.join(home, `actions_github_pages_${unixTime}`);
const test = await getWorkDirName(`${unixTime}`);
expect(test).toMatch(expected);
});
});
describe('createDir()', () => {
test('create a directory', async () => {
const unixTime = await getTime();
const workDirName = await getWorkDirName(`${unixTime}`);
await createDir(workDirName);
const test = fs.existsSync(workDirName);
expect(test).toBe(true);
});
});
async function getWorkDir(): Promise<string> {
const unixTime = await getTime();
let workDir = '';
workDir = await getWorkDirName(`${unixTime}`);
await createDir(workDir);
return workDir;
}
describe('addNoJekyll()', () => {
test('add .nojekyll', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, '.nojekyll');
await addNoJekyll(workDir, false);
const test = fs.existsSync(filepath);
expect(test).toBe(true);
fs.unlinkSync(filepath);
});
test('.nojekyll already exists', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, '.nojekyll');
fs.closeSync(fs.openSync(filepath, 'w'));
await addNoJekyll(workDir, false);
const test = fs.existsSync(filepath);
expect(test).toBe(true);
fs.unlinkSync(filepath);
});
test('not add .nojekyll disable_nojekyll', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, '.nojekyll');
await addNoJekyll(workDir, true);
const test = fs.existsSync(filepath);
expect(test).toBe(false);
});
});
describe('addCNAME()', () => {
test('add CNAME', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, 'CNAME');
await addCNAME(workDir, 'github.com');
const test = fs.readFileSync(filepath, 'utf8');
expect(test).toMatch('github.com');
fs.unlinkSync(filepath);
});
test('do nothing', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, 'CNAME');
await addCNAME(workDir, '');
const test = fs.existsSync(filepath);
expect(test).toBe(false);
});
test('CNAME already exists', async () => {
let workDir = '';
(async (): Promise<void> => {
workDir = await getWorkDir();
})();
const filepath = path.join(workDir, 'CNAME');
await addCNAME(workDir, 'github.io');
await addCNAME(workDir, 'github.com');
const test = fs.readFileSync(filepath, 'utf8');
expect(test).toMatch('github.io');
fs.unlinkSync(filepath);
});
});
describe('skipOnFork()', () => {
test('return false on upstream', async () => {
const test = await skipOnFork(false, 'token', '', '');
expect(test).toBeFalsy();
});
test('return false on fork with github_token', async () => {
const test = await skipOnFork(true, 'token', '', '');
expect(test).toBeFalsy();
});
test('return false on fork with deploy_key', async () => {
const test = await skipOnFork(true, '', 'deploy_key', '');
expect(test).toBeFalsy();
});
test('return false on fork with personal_token', async () => {
const test = await skipOnFork(true, '', '', 'personal_token');
expect(test).toBeFalsy();
});
test('return true on fork with no tokens', async () => {
const test = await skipOnFork(true, '', '', '');
expect(test).toBeTruthy();
});
});

View File

@ -2,78 +2,40 @@ name: 'GitHub Pages action'
description: 'GitHub Actions for GitHub Pages 🚀 Deploy static files and publish your site easily. Static-Site-Generators-friendly.' description: 'GitHub Actions for GitHub Pages 🚀 Deploy static files and publish your site easily. Static-Site-Generators-friendly.'
author: 'peaceiris' author: 'peaceiris'
runs: runs:
using: 'node20' using: 'docker'
main: 'lib/index.js' image: 'Dockerfile'
branding: branding:
icon: 'upload-cloud' icon: 'upload-cloud'
color: 'blue' color: 'blue'
inputs: inputs:
deploy_key: emptyCommits:
description: 'Set a SSH private key from repository secret value for pushing to the remote branch.'
required: false
github_token:
description: 'Set a generated GITHUB_TOKEN for pushing to the remote branch.'
required: false
personal_token:
description: 'Set a personal access token for pushing to the remote branch.'
required: false
publish_branch:
description: 'Set a target branch for deployment.'
required: false
default: 'gh-pages'
publish_dir:
description: 'Set an input directory for deployment.'
required: false
default: 'public'
destination_dir:
description: 'Set an destination subdirectory for deployment.'
required: false
default: ''
external_repository:
description: 'Set an external repository (owner/repo).'
required: false
allow_empty_commit:
description: 'If empty commits should be made to the publication branch' description: 'If empty commits should be made to the publication branch'
required: false required: false
default: 'false' default: 'true'
keep_files: keepFiles:
description: 'If existing files in the publish branch should be not removed before deploying' description: 'If existing files in the publish branch should be not removed before deploying'
required: false required: false
default: 'false' default: 'false'
force_orphan: forceOrphan:
description: 'Keep only the latest commit on a GitHub Pages branch' description: 'Keep only the latest commit on a GitHub Pages branch'
required: false required: false
default: 'false' default: 'false'
user_name: username:
description: 'Set Git user.name' description: 'Set Git user.name'
required: false required: false
user_email: useremail:
description: 'Set Git user.email' description: 'Set Git user.email'
required: false required: false
commit_message: commitMessage:
description: 'Set a custom commit message with a triggered commit hash' description: 'Set custom commit message'
required: false required: false
full_commit_message: tagName:
description: 'Set a custom full commit message without a triggered commit hash'
required: false
tag_name:
description: 'Set tag name' description: 'Set tag name'
required: false required: false
tag_message: tagMessage:
description: 'Set tag message' description: 'Set tag message'
required: false required: false
enable_jekyll: tagOverwrite:
description: 'Enable the GitHub Pages built-in Jekyll' description: 'Enable overwriting tag'
required: false required: false
default: 'false' default: false
disable_nojekyll:
description: 'An alias for enable_jekyll to disable adding .nojekyll file to a publishing branch'
required: false
default: 'false'
cname:
description: 'Set custom domain'
required: false
exclude_assets:
description: 'Set files or directories to exclude from a publish directory.'
required: false
default: '.github'

163
entrypoint.sh Executable file
View File

@ -0,0 +1,163 @@
#!/bin/bash
set -e
# set -ex
function print_error() {
echo -e "\e[31mERROR: ${1}\e[m"
}
function print_info() {
echo -e "\e[36mINFO: ${1}\e[m"
}
function skip() {
print_info "No changes detected, skipping deployment"
exit 0
}
# check values
if [ -n "${EXTERNAL_REPOSITORY}" ]; then
PUBLISH_REPOSITORY=${EXTERNAL_REPOSITORY}
else
PUBLISH_REPOSITORY=${GITHUB_REPOSITORY}
fi
print_info "Deploy to ${PUBLISH_REPOSITORY}"
if [ -n "${ACTIONS_DEPLOY_KEY}" ]; then
print_info "setup with ACTIONS_DEPLOY_KEY"
if [ -n "${SCRIPT_MODE}" ]; then
print_info "run as SCRIPT_MODE"
SSH_DIR="${HOME}/.ssh"
else
SSH_DIR="/root/.ssh"
fi
mkdir "${SSH_DIR}"
ssh-keyscan -t rsa github.com > "${SSH_DIR}/known_hosts"
echo "${ACTIONS_DEPLOY_KEY}" > "${SSH_DIR}/id_rsa"
chmod 400 "${SSH_DIR}/id_rsa"
remote_repo="git@github.com:${PUBLISH_REPOSITORY}.git"
elif [ -n "${PERSONAL_TOKEN}" ]; then
print_info "setup with PERSONAL_TOKEN"
remote_repo="https://x-access-token:${PERSONAL_TOKEN}@github.com/${PUBLISH_REPOSITORY}.git"
elif [ -n "${GITHUB_TOKEN}" ]; then
print_info "setup with GITHUB_TOKEN"
print_error "GITHUB_TOKEN works only private repo, See #9"
if [ -n "${EXTERNAL_REPOSITORY}" ]; then
print_error "can not use GITHUB_TOKEN to deploy to a external repository"
exit 1
fi
remote_repo="https://x-access-token:${GITHUB_TOKEN}@github.com/${PUBLISH_REPOSITORY}.git"
else
print_error "not found ACTIONS_DEPLOY_KEY, PERSONAL_TOKEN, or GITHUB_TOKEN"
exit 1
fi
if [ -z "${PUBLISH_BRANCH}" ]; then
print_error "not found PUBLISH_BRANCH"
exit 1
fi
if [ -z "${PUBLISH_DIR}" ]; then
print_error "not found PUBLISH_DIR"
exit 1
fi
remote_branch="${PUBLISH_BRANCH}"
local_dir="${HOME}/ghpages_${RANDOM}"
if [[ "${INPUT_FORCEORPHAN}" == "true" ]]; then
print_info "force ophan: ${INPUT_FORCEORPHAN}"
cd "${PUBLISH_DIR}"
git init
git checkout --orphan "${remote_branch}"
elif git clone --depth=1 --single-branch --branch "${remote_branch}" "${remote_repo}" "${local_dir}"; then
cd "${local_dir}"
if [[ ${INPUT_KEEPFILES} == "true" ]]; then
print_info "Keeping existing files: ${INPUT_KEEPFILES}"
else
git rm -r --ignore-unmatch '*'
fi
find "${GITHUB_WORKSPACE}/${PUBLISH_DIR}" -maxdepth 1 -not -name ".git" -not -name ".github" | \
tail -n +2 | \
xargs -I % cp -rf % "${local_dir}/"
else
cd "${PUBLISH_DIR}"
git init
git checkout --orphan "${remote_branch}"
fi
# push to publishing branch
if [[ -n "${INPUT_USERNAME}" ]]; then
git config user.name "${INPUT_USERNAME}"
else
git config user.name "${GITHUB_ACTOR}"
fi
if [[ -n "${INPUT_USEREMAIL}" ]]; then
git config user.email "${INPUT_USEREMAIL}"
else
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
fi
git remote rm origin || true
git remote add origin "${remote_repo}"
git add --all
print_info "Allowing empty commits: ${INPUT_EMPTYCOMMITS}"
if [ -n "${INPUT_COMMITMESSAGE}" ]; then
BASE_COMMIT_MESSAGE="${INPUT_COMMITMESSAGE}"
else
BASE_COMMIT_MESSAGE="Automated deployment: $(date -u)"
fi
if [ -n "${EXTERNAL_REPOSITORY}" ]; then
COMMIT_MESSAGE="${BASE_COMMIT_MESSAGE} ${GITHUB_REPOSITORY}@${GITHUB_SHA}"
else
COMMIT_MESSAGE="${BASE_COMMIT_MESSAGE} ${GITHUB_SHA}"
fi
if [[ ${INPUT_EMPTYCOMMITS} == "false" ]]; then
git commit -m "${COMMIT_MESSAGE}" || skip
else
git commit --allow-empty -m "${COMMIT_MESSAGE}"
fi
if [[ ${INPUT_FORCEORPHAN} == "true" ]]; then
git push origin --force "${remote_branch}"
else
git push origin "${remote_branch}"
fi
if [[ -n "${INPUT_TAGNAME}" ]]; then
print_info "Tag name: ${INPUT_TAGNAME}"
print_info "Tag message: ${INPUT_TAGMESSAGE}"
print_info "Tag overwrite: ${INPUT_TAGOVERWRITE}"
if [[ -n "${INPUT_TAGMESSAGE}" ]]; then
GIT_TAG_MESSAGE="${INPUT_TAGMESSAGE}"
else
GIT_TAG_MESSAGE="Deployment ${INPUT_TAGNAME}"
fi
if [[ "${INPUT_TAGOVERWRITE}" == "true" ]]; then
GIT_TAG_OPTION="--force"
else
GIT_TAG_OPTION=""
fi
git tag "${GIT_TAG_OPTION}" -a "${INPUT_TAGNAME}" -m "${GIT_TAG_MESSAGE}"
git push "${GIT_TAG_OPTION}" origin "${INPUT_TAGNAME}"
fi
print_info "${GITHUB_SHA} was successfully deployed"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
images/default-branch.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 51 KiB

BIN
images/log2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
images/log3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

BIN
images/user_repo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -1,11 +0,0 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
};

13628
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
{
"name": "actions-github-pages",
"version": "4.0.0",
"description": "GitHub Actions for GitHub Pages",
"main": "lib/index.js",
"engines": {
"node": ">=v20.11.0",
"npm": ">=10.2.4"
},
"scripts": {
"postinstall": "npx husky install",
"all": "npm run format && npm run lint && npm test",
"lint": "eslint ./{src,__tests__}/**/*.ts",
"lint:fix": "eslint --fix ./{src,__tests__}/**/*.ts",
"test": "jest --coverage --verbose --detectOpenHandles",
"build": "ncc build ./src/index.ts -o lib --minify",
"tsc": "tsc",
"format": "prettier --write '**/*.ts'",
"format:check": "prettier --check '**/*.ts'",
"release": "standard-version"
},
"lint-staged": {
"{src,__tests__}/**/*.ts": [
"prettier --check",
"eslint"
],
"README.md": [
"npx doctoc@2.1.0 --github"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/peaceiris/actions-gh-pages.git"
},
"keywords": [
"GitHub Actions",
"Actions",
"JavaScript Action",
"TypeScript Action",
"GitHub Pages",
"gh-pages"
],
"author": "peaceiris",
"license": "MIT",
"bugs": {
"url": "https://github.com/peaceiris/actions-gh-pages/issues"
},
"homepage": "https://github.com/peaceiris/actions-gh-pages#readme",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@actions/glob": "^0.5.0",
"@actions/io": "^1.1.2",
"@types/shelljs": "^0.8.11",
"shelljs": "^0.8.5"
},
"devDependencies": {
"@types/jest": "^29.2.6",
"@types/js-yaml": "^4.0.5",
"@types/node": "~16",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"@vercel/ncc": "^0.38.0",
"eslint": "^8.32.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.3",
"jest": "^29.3.1",
"jest-circus": "^29.3.1",
"js-yaml": "^4.1.0",
"lint-staged": "^13.1.0",
"prettier": "2.8.8",
"standard-version": "^9.1.1",
"ts-jest": "^29.0.5",
"typescript": "^4.9.4"
}
}

View File

@ -1,70 +0,0 @@
#!/usr/bin/env bash
# fail on unset variables and command errors
set -eu -o pipefail # -x: is for debugging
DEFAULT_BRANCH="main"
CURRENT_BRANCH="$(git branch --show-current)"
if [ "${CURRENT_BRANCH}" != "${DEFAULT_BRANCH}" ]; then
echo "$0: Current branch ${CURRENT_BRANCH} is not ${DEFAULT_BRANCH}, continue? (y/n)"
read -r res
if [ "${res}" = "n" ]; then
echo "$0: Stop script"
exit 0
fi
fi
PRERELEASE_TYPE_LIST="prerelease prepatch preminor premajor"
if [ "${CURRENT_BRANCH}" != "${DEFAULT_BRANCH}" ]; then
RELEASE_TYPE_LIST="${PRERELEASE_TYPE_LIST}"
else
RELEASE_TYPE_LIST="${PRERELEASE_TYPE_LIST} patch minor major"
fi
if command -v fzf; then
RELEASE_TYPE=$(echo "${RELEASE_TYPE_LIST}" | tr ' ' '\n' | fzf --layout=reverse)
else
select sel in ${RELEASE_TYPE_LIST}; do
RELEASE_TYPE="${sel}"
break
done
fi
echo "$0: Create ${RELEASE_TYPE} release, continue? (y/n)"
read -r res
if [ "${res}" = "n" ]; then
echo "$0: Stop script"
exit 0
fi
git fetch origin
if [ "${CURRENT_BRANCH}" != "${DEFAULT_BRANCH}" ]; then
git pull origin "${CURRENT_BRANCH}"
else
git pull origin ${DEFAULT_BRANCH}
git tag -d v3 || true
git pull origin --tags
fi
npm install
mkdir ./lib
npm run build
git add ./lib/index.js
git commit -m "chore(release): Add build assets"
npm run release -- --release-as "${RELEASE_TYPE}" --preset eslint
git rm ./lib/index.js
rm -rf ./lib
git commit -m "chore(release): Remove build assets [skip ci]"
if [ "${CURRENT_BRANCH}" != "${DEFAULT_BRANCH}" ]; then
git push origin "${CURRENT_BRANCH}"
else
git push origin ${DEFAULT_BRANCH}
fi
TAG_NAME="v$(jq -r '.version' ./package.json)"
git push origin "${TAG_NAME}"

View File

@ -1,13 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>peaceiris/renovate-config"
],
"packageRules": [
{
"automerge": false,
"matchUpdateTypes": ["minor", "patch"],
"automergeStrategy": "squash"
}
]
}

View File

@ -1,74 +0,0 @@
import * as core from '@actions/core';
import {Inputs} from './interfaces';
export function showInputs(inps: Inputs): void {
let authMethod = '';
if (inps.DeployKey) {
authMethod = 'DeployKey';
} else if (inps.GithubToken) {
authMethod = 'GithubToken';
} else if (inps.PersonalToken) {
authMethod = 'PersonalToken';
}
core.info(`\
[INFO] ${authMethod}: true
[INFO] PublishBranch: ${inps.PublishBranch}
[INFO] PublishDir: ${inps.PublishDir}
[INFO] DestinationDir: ${inps.DestinationDir}
[INFO] ExternalRepository: ${inps.ExternalRepository}
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
[INFO] KeepFiles: ${inps.KeepFiles}
[INFO] ForceOrphan: ${inps.ForceOrphan}
[INFO] UserName: ${inps.UserName}
[INFO] UserEmail: ${inps.UserEmail}
[INFO] CommitMessage: ${inps.CommitMessage}
[INFO] FullCommitMessage: ${inps.FullCommitMessage}
[INFO] TagName: ${inps.TagName}
[INFO] TagMessage: ${inps.TagMessage}
[INFO] EnableJekyll (DisableNoJekyll): ${inps.DisableNoJekyll}
[INFO] CNAME: ${inps.CNAME}
[INFO] ExcludeAssets ${inps.ExcludeAssets}
`);
}
export function getInputs(): Inputs {
let useBuiltinJekyll = false;
const isBoolean = (param: string): boolean => (param || 'false').toUpperCase() === 'TRUE';
const enableJekyll: boolean = isBoolean(core.getInput('enable_jekyll'));
const disableNoJekyll: boolean = isBoolean(core.getInput('disable_nojekyll'));
if (enableJekyll && disableNoJekyll) {
throw new Error(`Use either of enable_jekyll or disable_nojekyll`);
} else if (enableJekyll) {
useBuiltinJekyll = true;
} else if (disableNoJekyll) {
useBuiltinJekyll = true;
}
const inps: Inputs = {
DeployKey: core.getInput('deploy_key'),
GithubToken: core.getInput('github_token'),
PersonalToken: core.getInput('personal_token'),
PublishBranch: core.getInput('publish_branch'),
PublishDir: core.getInput('publish_dir'),
DestinationDir: core.getInput('destination_dir'),
ExternalRepository: core.getInput('external_repository'),
AllowEmptyCommit: isBoolean(core.getInput('allow_empty_commit')),
KeepFiles: isBoolean(core.getInput('keep_files')),
ForceOrphan: isBoolean(core.getInput('force_orphan')),
UserName: core.getInput('user_name'),
UserEmail: core.getInput('user_email'),
CommitMessage: core.getInput('commit_message'),
FullCommitMessage: core.getInput('full_commit_message'),
TagName: core.getInput('tag_name'),
TagMessage: core.getInput('tag_message'),
DisableNoJekyll: useBuiltinJekyll,
CNAME: core.getInput('cname'),
ExcludeAssets: core.getInput('exclude_assets')
};
return inps;
}

View File

@ -1,240 +0,0 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as glob from '@actions/glob';
import path from 'path';
import fs from 'fs';
import {URL} from 'url';
import {Inputs, CmdResult} from './interfaces';
import {createDir} from './utils';
import {cp, rm} from 'shelljs';
export async function createBranchForce(branch: string): Promise<void> {
await exec.exec('git', ['init']);
await exec.exec('git', ['checkout', '--orphan', branch]);
return;
}
export function getServerUrl(): URL {
return new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
}
export async function deleteExcludedAssets(destDir: string, excludeAssets: string): Promise<void> {
if (excludeAssets === '') return;
core.info(`[INFO] delete excluded assets`);
const excludedAssetNames: Array<string> = excludeAssets.split(',');
const excludedAssetPaths = ((): Array<string> => {
const paths: Array<string> = [];
for (const pattern of excludedAssetNames) {
paths.push(path.join(destDir, pattern));
}
return paths;
})();
const globber = await glob.create(excludedAssetPaths.join('\n'));
const files = await globber.glob();
for await (const file of globber.globGenerator()) {
core.info(`[INFO] delete ${file}`);
}
rm('-rf', files);
return;
}
export async function copyAssets(
publishDir: string,
destDir: string,
excludeAssets: string
): Promise<void> {
core.info(`[INFO] prepare publishing assets`);
if (!fs.existsSync(destDir)) {
core.info(`[INFO] create ${destDir}`);
await createDir(destDir);
}
const dotGitPath = path.join(publishDir, '.git');
if (fs.existsSync(dotGitPath)) {
core.info(`[INFO] delete ${dotGitPath}`);
rm('-rf', dotGitPath);
}
core.info(`[INFO] copy ${publishDir} to ${destDir}`);
cp('-RfL', [`${publishDir}/*`, `${publishDir}/.*`], destDir);
await deleteExcludedAssets(destDir, excludeAssets);
return;
}
export async function setRepo(inps: Inputs, remoteURL: string, workDir: string): Promise<void> {
const publishDir = path.isAbsolute(inps.PublishDir)
? inps.PublishDir
: path.join(`${process.env.GITHUB_WORKSPACE}`, inps.PublishDir);
if (path.isAbsolute(inps.DestinationDir)) {
throw new Error('destination_dir should be a relative path');
}
const destDir = ((): string => {
if (inps.DestinationDir === '') {
return workDir;
} else {
return path.join(workDir, inps.DestinationDir);
}
})();
core.info(`[INFO] ForceOrphan: ${inps.ForceOrphan}`);
if (inps.ForceOrphan) {
await createDir(destDir);
core.info(`[INFO] chdir ${workDir}`);
process.chdir(workDir);
await createBranchForce(inps.PublishBranch);
await copyAssets(publishDir, destDir, inps.ExcludeAssets);
return;
}
const result: CmdResult = {
exitcode: 0,
output: ''
};
const options = {
listeners: {
stdout: (data: Buffer): void => {
result.output += data.toString();
}
}
};
try {
result.exitcode = await exec.exec(
'git',
['clone', '--depth=1', '--single-branch', '--branch', inps.PublishBranch, remoteURL, workDir],
options
);
if (result.exitcode === 0) {
await createDir(destDir);
if (inps.KeepFiles) {
core.info('[INFO] Keep existing files');
} else {
core.info(`[INFO] clean up ${destDir}`);
core.info(`[INFO] chdir ${destDir}`);
process.chdir(destDir);
await exec.exec('git', ['rm', '-r', '--ignore-unmatch', '*']);
}
core.info(`[INFO] chdir ${workDir}`);
process.chdir(workDir);
await copyAssets(publishDir, destDir, inps.ExcludeAssets);
return;
} else {
throw new Error(`Failed to clone remote branch ${inps.PublishBranch}`);
}
} catch (error) {
if (error instanceof Error) {
core.info(`[INFO] first deployment, create new branch ${inps.PublishBranch}`);
core.info(`[INFO] ${error.message}`);
await createDir(destDir);
core.info(`[INFO] chdir ${workDir}`);
process.chdir(workDir);
await createBranchForce(inps.PublishBranch);
await copyAssets(publishDir, destDir, inps.ExcludeAssets);
return;
} else {
throw new Error('unexpected error');
}
}
}
export function getUserName(userName: string): string {
if (userName) {
return userName;
} else {
return `${process.env.GITHUB_ACTOR}`;
}
}
export function getUserEmail(userEmail: string): string {
if (userEmail) {
return userEmail;
} else {
return `${process.env.GITHUB_ACTOR}@users.noreply.github.com`;
}
}
export async function setCommitAuthor(userName: string, userEmail: string): Promise<void> {
if (userName && !userEmail) {
throw new Error('user_email is undefined');
}
if (!userName && userEmail) {
throw new Error('user_name is undefined');
}
await exec.exec('git', ['config', 'user.name', getUserName(userName)]);
await exec.exec('git', ['config', 'user.email', getUserEmail(userEmail)]);
}
export function getCommitMessage(
msg: string,
fullMsg: string,
extRepo: string,
baseRepo: string,
hash: string
): string {
const msgHash = ((): string => {
if (extRepo) {
return `${baseRepo}@${hash}`;
} else {
return hash;
}
})();
const subject = ((): string => {
if (fullMsg) {
return fullMsg;
} else if (msg) {
return `${msg} ${msgHash}`;
} else {
return `deploy: ${msgHash}`;
}
})();
return subject;
}
export async function commit(allowEmptyCommit: boolean, msg: string): Promise<void> {
try {
if (allowEmptyCommit) {
await exec.exec('git', ['commit', '--allow-empty', '-m', `${msg}`]);
} else {
await exec.exec('git', ['commit', '-m', `${msg}`]);
}
} catch (error) {
if (error instanceof Error) {
core.info('[INFO] skip commit');
core.debug(`[INFO] skip commit ${error.message}`);
} else {
throw new Error('unexpected error');
}
}
}
export async function push(branch: string, forceOrphan: boolean): Promise<void> {
if (forceOrphan) {
await exec.exec('git', ['push', 'origin', '--force', branch]);
} else {
await exec.exec('git', ['push', 'origin', branch]);
}
}
export async function pushTag(tagName: string, tagMessage: string): Promise<void> {
if (tagName === '') {
return;
}
let msg = '';
if (tagMessage) {
msg = tagMessage;
} else {
msg = `Deployment ${tagName}`;
}
await exec.exec('git', ['tag', '-a', `${tagName}`, '-m', `${msg}`]);
await exec.exec('git', ['push', 'origin', `${tagName}`]);
}

View File

@ -1,14 +0,0 @@
import * as core from '@actions/core';
import * as main from './main';
(async (): Promise<void> => {
try {
await main.run();
} catch (error) {
if (error instanceof Error) {
core.setFailed(`Action failed with "${error.message}"`);
} else {
core.setFailed('unexpected error');
}
}
})();

View File

@ -1,26 +0,0 @@
export interface Inputs {
readonly DeployKey: string;
readonly GithubToken: string;
readonly PersonalToken: string;
readonly PublishBranch: string;
readonly PublishDir: string;
readonly DestinationDir: string;
readonly ExternalRepository: string;
readonly AllowEmptyCommit: boolean;
readonly KeepFiles: boolean;
readonly ForceOrphan: boolean;
readonly UserName: string;
readonly UserEmail: string;
readonly CommitMessage: string;
readonly FullCommitMessage: string;
readonly TagName: string;
readonly TagMessage: string;
readonly DisableNoJekyll: boolean;
readonly CNAME: string;
readonly ExcludeAssets: string;
}
export interface CmdResult {
exitcode: number;
output: string;
}

View File

@ -1,100 +0,0 @@
import {context} from '@actions/github';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as github from '@actions/github';
import {Inputs} from './interfaces';
import {showInputs, getInputs} from './get-inputs';
import {setTokens} from './set-tokens';
import {setRepo, setCommitAuthor, getCommitMessage, commit, push, pushTag} from './git-utils';
import {getWorkDirName, addNoJekyll, addCNAME, skipOnFork} from './utils';
export async function run(): Promise<void> {
try {
core.info('[INFO] Usage https://github.com/peaceiris/actions-gh-pages#readme');
const inps: Inputs = getInputs();
core.startGroup('Dump inputs');
showInputs(inps);
core.endGroup();
if (core.isDebug()) {
core.startGroup('Debug: dump context');
console.log(context);
core.endGroup();
}
const eventName = context.eventName;
if (eventName === 'pull_request' || eventName === 'push') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isForkRepository = (context.payload as any).repository.fork;
const isSkipOnFork = await skipOnFork(
isForkRepository,
inps.GithubToken,
inps.DeployKey,
inps.PersonalToken
);
if (isSkipOnFork) {
core.warning('This action runs on a fork and not found auth token, Skip deployment');
core.setOutput('skip', 'true');
return;
}
}
core.startGroup('Setup auth token');
const remoteURL = await setTokens(inps);
core.debug(`remoteURL: ${remoteURL}`);
core.endGroup();
core.startGroup('Prepare publishing assets');
const date = new Date();
const unixTime = date.getTime();
const workDir = await getWorkDirName(`${unixTime}`);
await setRepo(inps, remoteURL, workDir);
await addNoJekyll(workDir, inps.DisableNoJekyll);
await addCNAME(workDir, inps.CNAME);
core.endGroup();
core.startGroup('Setup Git config');
try {
await exec.exec('git', ['remote', 'rm', 'origin']);
} catch (error) {
if (error instanceof Error) {
core.info(`[INFO] ${error.message}`);
} else {
throw new Error('unexpected error');
}
}
await exec.exec('git', ['remote', 'add', 'origin', remoteURL]);
await exec.exec('git', ['add', '--all']);
await setCommitAuthor(inps.UserName, inps.UserEmail);
core.endGroup();
core.startGroup('Create a commit');
const hash = `${process.env.GITHUB_SHA}`;
const baseRepo = `${github.context.repo.owner}/${github.context.repo.repo}`;
const commitMessage = getCommitMessage(
inps.CommitMessage,
inps.FullCommitMessage,
inps.ExternalRepository,
baseRepo,
hash
);
await commit(inps.AllowEmptyCommit, commitMessage);
core.endGroup();
core.startGroup('Push the commit or tag');
await push(inps.PublishBranch, inps.ForceOrphan);
await pushTag(inps.TagName, inps.TagMessage);
core.endGroup();
core.info('[INFO] Action successfully completed');
return;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error('unexpected error');
}
}
}

View File

@ -1,148 +0,0 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as github from '@actions/github';
import * as io from '@actions/io';
import path from 'path';
import fs from 'fs';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const cpSpawnSync = require('child_process').spawnSync;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const cpexec = require('child_process').execFileSync;
import {Inputs} from './interfaces';
import {getHomeDir} from './utils';
import {getServerUrl} from './git-utils';
export async function setSSHKey(inps: Inputs, publishRepo: string): Promise<string> {
core.info('[INFO] setup SSH deploy key');
const homeDir = await getHomeDir();
const sshDir = path.join(homeDir, '.ssh');
await io.mkdirP(sshDir);
await exec.exec('chmod', ['700', sshDir]);
const knownHosts = path.join(sshDir, 'known_hosts');
// ssh-keyscan -t rsa github.com or serverUrl >> ~/.ssh/known_hosts on Ubuntu
const cmdSSHkeyscanOutput = `\
# ${getServerUrl().host}.com:22 SSH-2.0-babeld-1f0633a6
${
getServerUrl().host
} ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
`;
fs.writeFileSync(knownHosts, cmdSSHkeyscanOutput + '\n');
core.info(`[INFO] wrote ${knownHosts}`);
await exec.exec('chmod', ['600', knownHosts]);
const idRSA = path.join(sshDir, 'github');
fs.writeFileSync(idRSA, inps.DeployKey + '\n');
core.info(`[INFO] wrote ${idRSA}`);
await exec.exec('chmod', ['600', idRSA]);
const sshConfigPath = path.join(sshDir, 'config');
const sshConfigContent = `\
Host ${getServerUrl().host}
HostName ${getServerUrl().host}
IdentityFile ~/.ssh/github
User git
`;
fs.writeFileSync(sshConfigPath, sshConfigContent + '\n');
core.info(`[INFO] wrote ${sshConfigPath}`);
await exec.exec('chmod', ['600', sshConfigPath]);
if (process.platform === 'win32') {
core.warning(`\
Currently, the deploy_key option is not supported on the windows-latest.
Watch https://github.com/peaceiris/actions-gh-pages/issues/87
`);
await cpSpawnSync('Start-Process', ['powershell.exe', '-Verb', 'runas']);
await cpSpawnSync('sh', ['-c', '\'eval "$(ssh-agent)"\''], {shell: true});
await exec.exec('sc', ['config', 'ssh-agent', 'start=auto']);
await exec.exec('sc', ['start', 'ssh-agent']);
}
await cpexec('ssh-agent', ['-a', '/tmp/ssh-auth.sock']);
core.exportVariable('SSH_AUTH_SOCK', '/tmp/ssh-auth.sock');
await exec.exec('ssh-add', [idRSA]);
return `git@${getServerUrl().host}:${publishRepo}.git`;
}
export function setGithubToken(
githubToken: string,
publishRepo: string,
publishBranch: string,
externalRepository: string,
ref: string,
eventName: string
): string {
core.info('[INFO] setup GITHUB_TOKEN');
core.debug(`ref: ${ref}`);
core.debug(`eventName: ${eventName}`);
let isProhibitedBranch = false;
if (externalRepository) {
throw new Error(`\
The generated GITHUB_TOKEN (github_token) does not support to push to an external repository.
Use deploy_key or personal_token.
`);
}
if (eventName === 'push') {
isProhibitedBranch = ref.match(new RegExp(`^refs/heads/${publishBranch}$`)) !== null;
if (isProhibitedBranch) {
throw new Error(`\
You deploy from ${publishBranch} to ${publishBranch}
This operation is prohibited to protect your contents
`);
}
}
return `https://x-access-token:${githubToken}@${getServerUrl().host}/${publishRepo}.git`;
}
export function setPersonalToken(personalToken: string, publishRepo: string): string {
core.info('[INFO] setup personal access token');
return `https://x-access-token:${personalToken}@${getServerUrl().host}/${publishRepo}.git`;
}
export function getPublishRepo(externalRepository: string, owner: string, repo: string): string {
if (externalRepository) {
return externalRepository;
}
return `${owner}/${repo}`;
}
export async function setTokens(inps: Inputs): Promise<string> {
try {
const publishRepo = getPublishRepo(
inps.ExternalRepository,
github.context.repo.owner,
github.context.repo.repo
);
if (inps.DeployKey) {
return setSSHKey(inps, publishRepo);
} else if (inps.GithubToken) {
const context = github.context;
const ref = context.ref;
const eventName = context.eventName;
return setGithubToken(
inps.GithubToken,
publishRepo,
inps.PublishBranch,
inps.ExternalRepository,
ref,
eventName
);
} else if (inps.PersonalToken) {
return setPersonalToken(inps.PersonalToken, publishRepo);
} else {
throw new Error('not found deploy key or tokens');
}
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error('unexpected error');
}
}
}

View File

@ -1,70 +0,0 @@
import * as core from '@actions/core';
import * as io from '@actions/io';
import path from 'path';
import fs from 'fs';
export async function getHomeDir(): Promise<string> {
let homedir = '';
if (process.platform === 'win32') {
homedir = process.env['USERPROFILE'] || 'C:\\';
} else {
homedir = `${process.env.HOME}`;
}
core.debug(`homeDir: ${homedir}`);
return homedir;
}
export async function getWorkDirName(unixTime: string): Promise<string> {
const homeDir = await getHomeDir();
const workDirName = path.join(homeDir, `actions_github_pages_${unixTime}`);
return workDirName;
}
export async function createDir(dirPath: string): Promise<void> {
await io.mkdirP(dirPath);
core.debug(`Created directory ${dirPath}`);
return;
}
export async function addNoJekyll(workDir: string, DisableNoJekyll: boolean): Promise<void> {
if (DisableNoJekyll) {
return;
}
const filepath = path.join(workDir, '.nojekyll');
if (fs.existsSync(filepath)) {
return;
}
fs.closeSync(fs.openSync(filepath, 'w'));
core.info(`[INFO] Created ${filepath}`);
}
export async function addCNAME(workDir: string, content: string): Promise<void> {
if (content === '') {
return;
}
const filepath = path.join(workDir, 'CNAME');
if (fs.existsSync(filepath)) {
core.info(`CNAME already exists, skip adding CNAME`);
return;
}
fs.writeFileSync(filepath, content + '\n');
core.info(`[INFO] Created ${filepath}`);
}
export async function skipOnFork(
isForkRepository: boolean,
githubToken: string,
deployKey: string,
personalToken: string
): Promise<boolean> {
if (isForkRepository) {
if (githubToken === '' && deployKey === '' && personalToken === '') {
return true;
}
}
return false;
}

View File

@ -1 +0,0 @@
book

View File

@ -1,6 +0,0 @@
[book]
authors = ["peaceiris"]
language = "en"
multilingual = false
src = "src"
title = "GitHub Actions for GitHub Pages"

View File

@ -1,3 +0,0 @@
# Summary
- [Chapter 1](./chapter_1.md)

View File

@ -1,3 +0,0 @@
# Chapter 1
test 7

View File

@ -1,16 +0,0 @@
{
"compilerOptions": {
"lib": ["ES2019"],
"module": "commonjs",
"target": "ES2019",
"sourceMap": true,
"outDir": "./lib",
"rootDir": "./src",
"removeComments": true,
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"resolveJsonModule": true
},
"exclude": ["node_modules", "**/*.test.ts"]
}