Skip to content

Commit f30118c

Browse files
authored
feat: Add destination_dir option (#403)
Related to #324 #390
1 parent 0cb61e9 commit f30118c

9 files changed

Lines changed: 93 additions & 20 deletions

File tree

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ All Actions runners: Linux (Ubuntu), macOS, and Windows are supported.
7474
- [⭐️ `personal_token`](#%EF%B8%8F-personal_token)
7575
- [⭐️ `publish_branch`](#%EF%B8%8F-publish_branch)
7676
- [⭐️ `publish_dir`](#%EF%B8%8F-publish_dir)
77+
- [⭐️ `destination_dir`](#%EF%B8%8F-destination_dir)
7778
- [⭐️ CNAME](#%EF%B8%8F-cname)
7879
- [⭐️ Enable Built-in Jekyll](#%EF%B8%8F-enable-built-in-jekyll)
7980
- [⭐️ 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`.
255256

256257
### ⭐️ `publish_dir`
257258

258-
A target directory to deploy to GitHub Pages. The default is `public`.
259+
A source directory to deploy to GitHub Pages. The default is `public`.
259260

260261
```yaml
261262
- name: Deploy
@@ -265,6 +266,18 @@ A target directory to deploy to GitHub Pages. The default is `public`.
265266
publish_dir: ./out # default: public
266267
```
267268

269+
### ⭐️ `destination_dir`
270+
271+
A destination subdirectory on a publishing branch. The default is empty.
272+
273+
```yaml
274+
- name: Deploy
275+
uses: peaceiris/actions-gh-pages@v3.7.0-0
276+
with:
277+
github_token: ${{ secrets.GITHUB_TOKEN }}
278+
destination_dir: subdir
279+
```
280+
268281
### ⭐️ CNAME
269282

270283
To add `CNAME` file, we can set the `cname` option.

__tests__/get-inputs.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function getInputsLog(authMethod: string, inps: Inputs): string {
4040
[INFO] ${authMethod}: true
4141
[INFO] PublishBranch: ${inps.PublishBranch}
4242
[INFO] PublishDir: ${inps.PublishDir}
43+
[INFO] DestinationDir: ${inps.DestinationDir}
4344
[INFO] ExternalRepository: ${inps.ExternalRepository}
4445
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
4546
[INFO] KeepFiles: ${inps.KeepFiles}
@@ -107,6 +108,7 @@ describe('getInputs()', () => {
107108
expect(inps.PersonalToken).toMatch('');
108109
expect(inps.PublishBranch).toMatch('gh-pages');
109110
expect(inps.PublishDir).toMatch('public');
111+
expect(inps.DestinationDir).toMatch('');
110112
expect(inps.ExternalRepository).toMatch('');
111113
expect(inps.AllowEmptyCommit).toBe(false);
112114
expect(inps.KeepFiles).toBe(false);
@@ -127,6 +129,7 @@ describe('getInputs()', () => {
127129
process.env['INPUT_PERSONAL_TOKEN'] = 'test_personal_token';
128130
process.env['INPUT_PUBLISH_BRANCH'] = 'master';
129131
process.env['INPUT_PUBLISH_DIR'] = 'out';
132+
process.env['INPUT_DESTINATION_DIR'] = 'subdir';
130133
process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo';
131134
process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true';
132135
process.env['INPUT_KEEP_FILES'] = 'true';
@@ -147,6 +150,7 @@ describe('getInputs()', () => {
147150
expect(inps.PersonalToken).toMatch('test_personal_token');
148151
expect(inps.PublishBranch).toMatch('master');
149152
expect(inps.PublishDir).toMatch('out');
153+
expect(inps.DestinationDir).toMatch('subdir');
150154
expect(inps.ExternalRepository).toMatch('user/repo');
151155
expect(inps.AllowEmptyCommit).toBe(true);
152156
expect(inps.KeepFiles).toBe(true);

__tests__/git-utils.test.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
import {getUserName, getUserEmail, setCommitAuthor, getCommitMessage} from '../src/git-utils';
2-
import {getWorkDirName, createWorkDir} from '../src/utils';
1+
import {
2+
setRepo,
3+
getUserName,
4+
getUserEmail,
5+
setCommitAuthor,
6+
getCommitMessage
7+
} from '../src/git-utils';
8+
import {getInputs} from '../src/get-inputs';
9+
import {Inputs} from '../src/interfaces';
10+
import {getWorkDirName, createDir} from '../src/utils';
311
import {CmdResult} from '../src/interfaces';
412
import * as exec from '@actions/exec';
513

@@ -14,6 +22,35 @@ afterEach(() => {
1422
delete process.env['GITHUB_REPOSITORY'];
1523
});
1624

25+
describe('setRepo()', () => {
26+
test('throw error destination_dir should be a relative path', async () => {
27+
process.env['INPUT_GITHUB_TOKEN'] = 'test_github_token';
28+
process.env['INPUT_PUBLISH_BRANCH'] = 'gh-pages';
29+
process.env['INPUT_PUBLISH_DIR'] = 'public';
30+
process.env['INPUT_DESTINATION_DIR'] = '/subdir';
31+
// process.env['INPUT_EXTERNAL_REPOSITORY'] = 'user/repo';
32+
// process.env['INPUT_ALLOW_EMPTY_COMMIT'] = 'true';
33+
// process.env['INPUT_KEEP_FILES'] = 'true';
34+
// process.env['INPUT_FORCE_ORPHAN'] = 'true';
35+
// process.env['INPUT_USER_NAME'] = 'username';
36+
// process.env['INPUT_USER_EMAIL'] = 'github@github.com';
37+
// process.env['INPUT_COMMIT_MESSAGE'] = 'feat: Add new feature';
38+
// process.env['INPUT_FULL_COMMIT_MESSAGE'] = 'feat: Add new feature';
39+
// process.env['INPUT_TAG_NAME'] = 'deploy-v1.2.3';
40+
// process.env['INPUT_TAG_MESSAGE'] = 'Deployment v1.2.3';
41+
// process.env['INPUT_DISABLE_NOJEKYLL'] = 'true';
42+
// process.env['INPUT_CNAME'] = 'github.com';
43+
const inps: Inputs = getInputs();
44+
const remoteURL = 'https://x-access-token:pat@github.com/actions/pages.git';
45+
const date = new Date();
46+
const unixTime = date.getTime();
47+
const workDir = await getWorkDirName(`${unixTime}`);
48+
await expect(setRepo(inps, remoteURL, workDir)).rejects.toThrowError(
49+
'destination_dir should be a relative path'
50+
);
51+
});
52+
});
53+
1754
describe('getUserName()', () => {
1855
test('get default git user name', () => {
1956
const userName = '';
@@ -51,7 +88,7 @@ describe('setCommitAuthor()', () => {
5188
})();
5289

5390
beforeEach(async () => {
54-
await createWorkDir(workDirName);
91+
await createDir(workDirName);
5592
process.chdir(workDirName);
5693
await exec.exec('git', ['init']);
5794
});

__tests__/utils.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import fs from 'fs';
33
import {
44
getHomeDir,
55
getWorkDirName,
6-
createWorkDir,
6+
createDir,
77
addNoJekyll,
88
addCNAME,
99
skipOnFork
@@ -51,11 +51,11 @@ describe('getWorkDirName()', () => {
5151
});
5252
});
5353

54-
describe('createWorkDir()', () => {
55-
test('create work directory', async () => {
54+
describe('createDir()', () => {
55+
test('create a directory', async () => {
5656
const unixTime = await getTime();
5757
const workDirName = await getWorkDirName(`${unixTime}`);
58-
await createWorkDir(workDirName);
58+
await createDir(workDirName);
5959
const test = fs.existsSync(workDirName);
6060
expect(test).toBe(true);
6161
});
@@ -65,7 +65,7 @@ async function getWorkDir(): Promise<string> {
6565
const unixTime = await getTime();
6666
let workDir = '';
6767
workDir = await getWorkDirName(`${unixTime}`);
68-
await createWorkDir(workDir);
68+
await createDir(workDir);
6969
return workDir;
7070
}
7171

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ inputs:
2525
description: 'Set an input directory for deployment.'
2626
required: false
2727
default: 'public'
28+
destination_dir:
29+
description: 'Set an destination subdirectory for deployment.'
30+
required: false
31+
default: ''
2832
external_repository:
2933
description: 'Set an external repository (owner/repo).'
3034
required: false

src/get-inputs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export function showInputs(inps: Inputs): void {
1515
[INFO] ${authMethod}: true
1616
[INFO] PublishBranch: ${inps.PublishBranch}
1717
[INFO] PublishDir: ${inps.PublishDir}
18+
[INFO] DestinationDir: ${inps.DestinationDir}
1819
[INFO] ExternalRepository: ${inps.ExternalRepository}
1920
[INFO] AllowEmptyCommit: ${inps.AllowEmptyCommit}
2021
[INFO] KeepFiles: ${inps.KeepFiles}
@@ -52,6 +53,7 @@ export function getInputs(): Inputs {
5253
PersonalToken: core.getInput('personal_token'),
5354
PublishBranch: core.getInput('publish_branch'),
5455
PublishDir: core.getInput('publish_dir'),
56+
DestinationDir: core.getInput('destination_dir'),
5557
ExternalRepository: core.getInput('external_repository'),
5658
AllowEmptyCommit: (core.getInput('allow_empty_commit') || 'false').toUpperCase() === 'TRUE',
5759
KeepFiles: (core.getInput('keep_files') || 'false').toUpperCase() === 'TRUE',

src/git-utils.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import * as io from '@actions/io';
44
import path from 'path';
55
import fs from 'fs';
66
import {Inputs, CmdResult} from './interfaces';
7-
import {createWorkDir} from './utils';
7+
import {createDir} from './utils';
88

99
export async function createBranchForce(branch: string): Promise<void> {
1010
await exec.exec('git', ['init']);
1111
await exec.exec('git', ['checkout', '--orphan', branch]);
1212
return;
1313
}
1414

15-
export async function copyAssets(publishDir: string, workDir: string): Promise<void> {
15+
export async function copyAssets(publishDir: string, destDir: string): Promise<void> {
1616
const copyOpts = {recursive: true, force: true};
1717
const files = fs.readdirSync(publishDir);
1818
core.debug(`${files}`);
@@ -21,7 +21,7 @@ export async function copyAssets(publishDir: string, workDir: string): Promise<v
2121
continue;
2222
}
2323
const filePath = path.join(publishDir, file);
24-
await io.cp(filePath, `${workDir}/`, copyOpts);
24+
await io.cp(filePath, `${destDir}/`, copyOpts);
2525
core.info(`[INFO] copy ${file}`);
2626
}
2727

@@ -33,12 +33,24 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string):
3333
? inps.PublishDir
3434
: path.join(`${process.env.GITHUB_WORKSPACE}`, inps.PublishDir);
3535

36+
if (path.isAbsolute(inps.DestinationDir)) {
37+
throw new Error('destination_dir should be a relative path');
38+
}
39+
const destDir = ((): string => {
40+
if (inps.DestinationDir === '') {
41+
return workDir;
42+
} else {
43+
return path.join(workDir, inps.DestinationDir);
44+
}
45+
})();
46+
3647
core.info(`[INFO] ForceOrphan: ${inps.ForceOrphan}`);
3748
if (inps.ForceOrphan) {
38-
await createWorkDir(workDir);
49+
await createDir(destDir);
3950
process.chdir(workDir);
4051
await createBranchForce(inps.PublishBranch);
41-
await copyAssets(publishDir, workDir);
52+
process.chdir(destDir);
53+
await copyAssets(publishDir, destDir);
4254
return;
4355
}
4456

@@ -68,18 +80,18 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string):
6880
await exec.exec('git', ['rm', '-r', '--ignore-unmatch', '*']);
6981
}
7082

71-
await copyAssets(publishDir, workDir);
83+
await copyAssets(publishDir, destDir);
7284
return;
7385
} else {
7486
throw new Error(`Failed to clone remote branch ${inps.PublishBranch}`);
7587
}
7688
} catch (e) {
7789
core.info(`[INFO] first deployment, create new branch ${inps.PublishBranch}`);
7890
core.info(e.message);
79-
await createWorkDir(workDir);
91+
await createDir(destDir);
8092
process.chdir(workDir);
8193
await createBranchForce(inps.PublishBranch);
82-
await copyAssets(publishDir, workDir);
94+
await copyAssets(publishDir, destDir);
8395
return;
8496
}
8597
}

src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export interface Inputs {
44
readonly PersonalToken: string;
55
readonly PublishBranch: string;
66
readonly PublishDir: string;
7+
readonly DestinationDir: string;
78
readonly ExternalRepository: string;
89
readonly AllowEmptyCommit: boolean;
910
readonly KeepFiles: boolean;

src/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ export async function getWorkDirName(unixTime: string): Promise<string> {
2323
return workDirName;
2424
}
2525

26-
export async function createWorkDir(workDirName: string): Promise<void> {
27-
await io.mkdirP(workDirName);
28-
core.debug(`Created: ${workDirName}`);
26+
export async function createDir(dirPath: string): Promise<void> {
27+
await io.mkdirP(dirPath);
28+
core.debug(`Created directory ${dirPath}`);
2929
return;
3030
}
3131

0 commit comments

Comments
 (0)