feat: Add destination_dir option (#403)

Related to #324 #390
This commit is contained in:
Shohei Ueda 2020-07-21 11:15:53 +09:00 committed by GitHub
parent 0cb61e91a5
commit f30118c78e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 93 additions and 20 deletions

View File

@ -74,6 +74,7 @@ All Actions runners: Linux (Ubuntu), macOS, and Windows are supported.
- [⭐️ `personal_token`](#%EF%B8%8F-personal_token) - [⭐️ `personal_token`](#%EF%B8%8F-personal_token)
- [⭐️ `publish_branch`](#%EF%B8%8F-publish_branch) - [⭐️ `publish_branch`](#%EF%B8%8F-publish_branch)
- [⭐️ `publish_dir`](#%EF%B8%8F-publish_dir) - [⭐️ `publish_dir`](#%EF%B8%8F-publish_dir)
- [⭐️ `destination_dir`](#%EF%B8%8F-destination_dir)
- [⭐️ CNAME](#%EF%B8%8F-cname) - [⭐️ CNAME](#%EF%B8%8F-cname)
- [⭐️ Enable Built-in Jekyll](#%EF%B8%8F-enable-built-in-jekyll) - [⭐️ Enable Built-in Jekyll](#%EF%B8%8F-enable-built-in-jekyll)
- [⭐️ Allow empty commits](#%EF%B8%8F-allow-empty-commits) - [⭐️ Allow empty commits](#%EF%B8%8F-allow-empty-commits)
@ -255,7 +256,7 @@ A target branch to deploy to GitHub Pages. The default is `gh-pages`.
### ⭐️ `publish_dir` ### ⭐️ `publish_dir`
A target directory to deploy to GitHub Pages. The default is `public`. A source directory to deploy to GitHub Pages. The default is `public`.
```yaml ```yaml
- name: Deploy - name: Deploy
@ -265,6 +266,18 @@ A target directory to deploy to GitHub Pages. The default is `public`.
publish_dir: ./out # default: public publish_dir: ./out # default: public
``` ```
### ⭐️ `destination_dir`
A destination subdirectory on a publishing branch. The default is empty.
```yaml
- name: Deploy
uses: peaceiris/actions-gh-pages@v3.7.0-0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
destination_dir: subdir
```
### ⭐️ CNAME ### ⭐️ CNAME
To add `CNAME` file, we can set the `cname` option. To add `CNAME` file, we can set the `cname` option.

View File

@ -40,6 +40,7 @@ function getInputsLog(authMethod: string, inps: Inputs): string {
[INFO] ${authMethod}: true [INFO] ${authMethod}: true
[INFO] PublishBranch: ${inps.PublishBranch} [INFO] PublishBranch: ${inps.PublishBranch}
[INFO] PublishDir: ${inps.PublishDir} [INFO] PublishDir: ${inps.PublishDir}
[INFO] DestinationDir: ${inps.DestinationDir}
[INFO] ExternalRepository: ${inps.ExternalRepository} [INFO] ExternalRepository: ${inps.ExternalRepository}
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit} [INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
[INFO] KeepFiles: ${inps.KeepFiles} [INFO] KeepFiles: ${inps.KeepFiles}
@ -107,6 +108,7 @@ describe('getInputs()', () => {
expect(inps.PersonalToken).toMatch(''); expect(inps.PersonalToken).toMatch('');
expect(inps.PublishBranch).toMatch('gh-pages'); expect(inps.PublishBranch).toMatch('gh-pages');
expect(inps.PublishDir).toMatch('public'); expect(inps.PublishDir).toMatch('public');
expect(inps.DestinationDir).toMatch('');
expect(inps.ExternalRepository).toMatch(''); expect(inps.ExternalRepository).toMatch('');
expect(inps.AllowEmptyCommit).toBe(false); expect(inps.AllowEmptyCommit).toBe(false);
expect(inps.KeepFiles).toBe(false); expect(inps.KeepFiles).toBe(false);
@ -127,6 +129,7 @@ describe('getInputs()', () => {
process.env['INPUT_PERSONAL_TOKEN'] = 'test_personal_token'; process.env['INPUT_PERSONAL_TOKEN'] = 'test_personal_token';
process.env['INPUT_PUBLISH_BRANCH'] = 'master'; process.env['INPUT_PUBLISH_BRANCH'] = 'master';
process.env['INPUT_PUBLISH_DIR'] = 'out'; process.env['INPUT_PUBLISH_DIR'] = 'out';
process.env['INPUT_DESTINATION_DIR'] = 'subdir';
process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo'; process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo';
process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true'; process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true';
process.env['INPUT_KEEP_FILES'] = 'true'; process.env['INPUT_KEEP_FILES'] = 'true';
@ -147,6 +150,7 @@ describe('getInputs()', () => {
expect(inps.PersonalToken).toMatch('test_personal_token'); expect(inps.PersonalToken).toMatch('test_personal_token');
expect(inps.PublishBranch).toMatch('master'); expect(inps.PublishBranch).toMatch('master');
expect(inps.PublishDir).toMatch('out'); expect(inps.PublishDir).toMatch('out');
expect(inps.DestinationDir).toMatch('subdir');
expect(inps.ExternalRepository).toMatch('user/repo'); expect(inps.ExternalRepository).toMatch('user/repo');
expect(inps.AllowEmptyCommit).toBe(true); expect(inps.AllowEmptyCommit).toBe(true);
expect(inps.KeepFiles).toBe(true); expect(inps.KeepFiles).toBe(true);

View File

@ -1,5 +1,13 @@
import {getUserName, getUserEmail, setCommitAuthor, getCommitMessage} from '../src/git-utils'; import {
import {getWorkDirName, createWorkDir} from '../src/utils'; 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 {CmdResult} from '../src/interfaces';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
@ -14,6 +22,35 @@ afterEach(() => {
delete process.env['GITHUB_REPOSITORY']; delete process.env['GITHUB_REPOSITORY'];
}); });
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';
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.toThrowError(
'destination_dir should be a relative path'
);
});
});
describe('getUserName()', () => { describe('getUserName()', () => {
test('get default git user name', () => { test('get default git user name', () => {
const userName = ''; const userName = '';
@ -51,7 +88,7 @@ describe('setCommitAuthor()', () => {
})(); })();
beforeEach(async () => { beforeEach(async () => {
await createWorkDir(workDirName); await createDir(workDirName);
process.chdir(workDirName); process.chdir(workDirName);
await exec.exec('git', ['init']); await exec.exec('git', ['init']);
}); });

View File

@ -3,7 +3,7 @@ import fs from 'fs';
import { import {
getHomeDir, getHomeDir,
getWorkDirName, getWorkDirName,
createWorkDir, createDir,
addNoJekyll, addNoJekyll,
addCNAME, addCNAME,
skipOnFork skipOnFork
@ -51,11 +51,11 @@ describe('getWorkDirName()', () => {
}); });
}); });
describe('createWorkDir()', () => { describe('createDir()', () => {
test('create work directory', async () => { test('create a directory', async () => {
const unixTime = await getTime(); const unixTime = await getTime();
const workDirName = await getWorkDirName(`${unixTime}`); const workDirName = await getWorkDirName(`${unixTime}`);
await createWorkDir(workDirName); await createDir(workDirName);
const test = fs.existsSync(workDirName); const test = fs.existsSync(workDirName);
expect(test).toBe(true); expect(test).toBe(true);
}); });
@ -65,7 +65,7 @@ async function getWorkDir(): Promise<string> {
const unixTime = await getTime(); const unixTime = await getTime();
let workDir = ''; let workDir = '';
workDir = await getWorkDirName(`${unixTime}`); workDir = await getWorkDirName(`${unixTime}`);
await createWorkDir(workDir); await createDir(workDir);
return workDir; return workDir;
} }

View File

@ -25,6 +25,10 @@ inputs:
description: 'Set an input directory for deployment.' description: 'Set an input directory for deployment.'
required: false required: false
default: 'public' default: 'public'
destination_dir:
description: 'Set an destination subdirectory for deployment.'
required: false
default: ''
external_repository: external_repository:
description: 'Set an external repository (owner/repo).' description: 'Set an external repository (owner/repo).'
required: false required: false

View File

@ -15,6 +15,7 @@ export function showInputs(inps: Inputs): void {
[INFO] ${authMethod}: true [INFO] ${authMethod}: true
[INFO] PublishBranch: ${inps.PublishBranch} [INFO] PublishBranch: ${inps.PublishBranch}
[INFO] PublishDir: ${inps.PublishDir} [INFO] PublishDir: ${inps.PublishDir}
[INFO] DestinationDir: ${inps.DestinationDir}
[INFO] ExternalRepository: ${inps.ExternalRepository} [INFO] ExternalRepository: ${inps.ExternalRepository}
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit} [INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
[INFO] KeepFiles: ${inps.KeepFiles} [INFO] KeepFiles: ${inps.KeepFiles}
@ -52,6 +53,7 @@ export function getInputs(): Inputs {
PersonalToken: core.getInput('personal_token'), PersonalToken: core.getInput('personal_token'),
PublishBranch: core.getInput('publish_branch'), PublishBranch: core.getInput('publish_branch'),
PublishDir: core.getInput('publish_dir'), PublishDir: core.getInput('publish_dir'),
DestinationDir: core.getInput('destination_dir'),
ExternalRepository: core.getInput('external_repository'), ExternalRepository: core.getInput('external_repository'),
AllowEmptyCommit: (core.getInput('allow_empty_commit') || 'false').toUpperCase() === 'TRUE', AllowEmptyCommit: (core.getInput('allow_empty_commit') || 'false').toUpperCase() === 'TRUE',
KeepFiles: (core.getInput('keep_files') || 'false').toUpperCase() === 'TRUE', KeepFiles: (core.getInput('keep_files') || 'false').toUpperCase() === 'TRUE',

View File

@ -4,7 +4,7 @@ import * as io from '@actions/io';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import {Inputs, CmdResult} from './interfaces'; import {Inputs, CmdResult} from './interfaces';
import {createWorkDir} from './utils'; import {createDir} from './utils';
export async function createBranchForce(branch: string): Promise<void> { export async function createBranchForce(branch: string): Promise<void> {
await exec.exec('git', ['init']); await exec.exec('git', ['init']);
@ -12,7 +12,7 @@ export async function createBranchForce(branch: string): Promise<void> {
return; return;
} }
export async function copyAssets(publishDir: string, workDir: string): Promise<void> { export async function copyAssets(publishDir: string, destDir: string): Promise<void> {
const copyOpts = {recursive: true, force: true}; const copyOpts = {recursive: true, force: true};
const files = fs.readdirSync(publishDir); const files = fs.readdirSync(publishDir);
core.debug(`${files}`); core.debug(`${files}`);
@ -21,7 +21,7 @@ export async function copyAssets(publishDir: string, workDir: string): Promise<v
continue; continue;
} }
const filePath = path.join(publishDir, file); const filePath = path.join(publishDir, file);
await io.cp(filePath, `${workDir}/`, copyOpts); await io.cp(filePath, `${destDir}/`, copyOpts);
core.info(`[INFO] copy ${file}`); core.info(`[INFO] copy ${file}`);
} }
@ -33,12 +33,24 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string):
? inps.PublishDir ? inps.PublishDir
: path.join(`${process.env.GITHUB_WORKSPACE}`, 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}`); core.info(`[INFO] ForceOrphan: ${inps.ForceOrphan}`);
if (inps.ForceOrphan) { if (inps.ForceOrphan) {
await createWorkDir(workDir); await createDir(destDir);
process.chdir(workDir); process.chdir(workDir);
await createBranchForce(inps.PublishBranch); await createBranchForce(inps.PublishBranch);
await copyAssets(publishDir, workDir); process.chdir(destDir);
await copyAssets(publishDir, destDir);
return; return;
} }
@ -68,7 +80,7 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string):
await exec.exec('git', ['rm', '-r', '--ignore-unmatch', '*']); await exec.exec('git', ['rm', '-r', '--ignore-unmatch', '*']);
} }
await copyAssets(publishDir, workDir); await copyAssets(publishDir, destDir);
return; return;
} else { } else {
throw new Error(`Failed to clone remote branch ${inps.PublishBranch}`); throw new Error(`Failed to clone remote branch ${inps.PublishBranch}`);
@ -76,10 +88,10 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string):
} catch (e) { } catch (e) {
core.info(`[INFO] first deployment, create new branch ${inps.PublishBranch}`); core.info(`[INFO] first deployment, create new branch ${inps.PublishBranch}`);
core.info(e.message); core.info(e.message);
await createWorkDir(workDir); await createDir(destDir);
process.chdir(workDir); process.chdir(workDir);
await createBranchForce(inps.PublishBranch); await createBranchForce(inps.PublishBranch);
await copyAssets(publishDir, workDir); await copyAssets(publishDir, destDir);
return; return;
} }
} }

View File

@ -4,6 +4,7 @@ export interface Inputs {
readonly PersonalToken: string; readonly PersonalToken: string;
readonly PublishBranch: string; readonly PublishBranch: string;
readonly PublishDir: string; readonly PublishDir: string;
readonly DestinationDir: string;
readonly ExternalRepository: string; readonly ExternalRepository: string;
readonly AllowEmptyCommit: boolean; readonly AllowEmptyCommit: boolean;
readonly KeepFiles: boolean; readonly KeepFiles: boolean;

View File

@ -23,9 +23,9 @@ export async function getWorkDirName(unixTime: string): Promise<string> {
return workDirName; return workDirName;
} }
export async function createWorkDir(workDirName: string): Promise<void> { export async function createDir(dirPath: string): Promise<void> {
await io.mkdirP(workDirName); await io.mkdirP(dirPath);
core.debug(`Created: ${workDirName}`); core.debug(`Created directory ${dirPath}`);
return; return;
} }