From f30118c78eebbbe6cf66009b80a7414a4047de43 Mon Sep 17 00:00:00 2001 From: Shohei Ueda <30958501+peaceiris@users.noreply.github.com> Date: Tue, 21 Jul 2020 11:15:53 +0900 Subject: [PATCH] feat: Add destination_dir option (#403) Related to #324 #390 --- README.md | 15 ++++++++++++- __tests__/get-inputs.test.ts | 4 ++++ __tests__/git-utils.test.ts | 43 +++++++++++++++++++++++++++++++++--- __tests__/utils.test.ts | 10 ++++----- action.yml | 4 ++++ src/get-inputs.ts | 2 ++ src/git-utils.ts | 28 ++++++++++++++++------- src/interfaces.ts | 1 + src/utils.ts | 6 ++--- 9 files changed, 93 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c98fee130..d18de36b5 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ All Actions runners: Linux (Ubuntu), macOS, and Windows are supported. - [⭐️ `personal_token`](#%EF%B8%8F-personal_token) - [⭐️ `publish_branch`](#%EF%B8%8F-publish_branch) - [⭐️ `publish_dir`](#%EF%B8%8F-publish_dir) + - [⭐️ `destination_dir`](#%EF%B8%8F-destination_dir) - [⭐️ CNAME](#%EF%B8%8F-cname) - [⭐️ Enable Built-in Jekyll](#%EF%B8%8F-enable-built-in-jekyll) - [⭐️ 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` -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 - name: Deploy @@ -265,6 +266,18 @@ A target directory to deploy to GitHub Pages. The default is `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 To add `CNAME` file, we can set the `cname` option. diff --git a/__tests__/get-inputs.test.ts b/__tests__/get-inputs.test.ts index 43d8e9b34..a0537074c 100644 --- a/__tests__/get-inputs.test.ts +++ b/__tests__/get-inputs.test.ts @@ -40,6 +40,7 @@ function getInputsLog(authMethod: string, inps: Inputs): string { [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} @@ -107,6 +108,7 @@ describe('getInputs()', () => { 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); @@ -127,6 +129,7 @@ describe('getInputs()', () => { 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'; @@ -147,6 +150,7 @@ describe('getInputs()', () => { 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); diff --git a/__tests__/git-utils.test.ts b/__tests__/git-utils.test.ts index 1cda5e4b8..6b64fb741 100644 --- a/__tests__/git-utils.test.ts +++ b/__tests__/git-utils.test.ts @@ -1,5 +1,13 @@ -import {getUserName, getUserEmail, setCommitAuthor, getCommitMessage} from '../src/git-utils'; -import {getWorkDirName, createWorkDir} from '../src/utils'; +import { + 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'; @@ -14,6 +22,35 @@ afterEach(() => { 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()', () => { test('get default git user name', () => { const userName = ''; @@ -51,7 +88,7 @@ describe('setCommitAuthor()', () => { })(); beforeEach(async () => { - await createWorkDir(workDirName); + await createDir(workDirName); process.chdir(workDirName); await exec.exec('git', ['init']); }); diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 943aa71e1..d893b122b 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import { getHomeDir, getWorkDirName, - createWorkDir, + createDir, addNoJekyll, addCNAME, skipOnFork @@ -51,11 +51,11 @@ describe('getWorkDirName()', () => { }); }); -describe('createWorkDir()', () => { - test('create work directory', async () => { +describe('createDir()', () => { + test('create a directory', async () => { const unixTime = await getTime(); const workDirName = await getWorkDirName(`${unixTime}`); - await createWorkDir(workDirName); + await createDir(workDirName); const test = fs.existsSync(workDirName); expect(test).toBe(true); }); @@ -65,7 +65,7 @@ async function getWorkDir(): Promise { const unixTime = await getTime(); let workDir = ''; workDir = await getWorkDirName(`${unixTime}`); - await createWorkDir(workDir); + await createDir(workDir); return workDir; } diff --git a/action.yml b/action.yml index 74c5afda0..651d5f8b0 100644 --- a/action.yml +++ b/action.yml @@ -25,6 +25,10 @@ inputs: 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 diff --git a/src/get-inputs.ts b/src/get-inputs.ts index 1c4b5acbc..d19692485 100644 --- a/src/get-inputs.ts +++ b/src/get-inputs.ts @@ -15,6 +15,7 @@ export function showInputs(inps: Inputs): void { [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} @@ -52,6 +53,7 @@ export function getInputs(): Inputs { 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: (core.getInput('allow_empty_commit') || 'false').toUpperCase() === 'TRUE', KeepFiles: (core.getInput('keep_files') || 'false').toUpperCase() === 'TRUE', diff --git a/src/git-utils.ts b/src/git-utils.ts index c685b4728..97be11ee9 100644 --- a/src/git-utils.ts +++ b/src/git-utils.ts @@ -4,7 +4,7 @@ import * as io from '@actions/io'; import path from 'path'; import fs from 'fs'; import {Inputs, CmdResult} from './interfaces'; -import {createWorkDir} from './utils'; +import {createDir} from './utils'; export async function createBranchForce(branch: string): Promise { await exec.exec('git', ['init']); @@ -12,7 +12,7 @@ export async function createBranchForce(branch: string): Promise { return; } -export async function copyAssets(publishDir: string, workDir: string): Promise { +export async function copyAssets(publishDir: string, destDir: string): Promise { const copyOpts = {recursive: true, force: true}; const files = fs.readdirSync(publishDir); core.debug(`${files}`); @@ -21,7 +21,7 @@ export async function copyAssets(publishDir: string, workDir: string): Promise { + if (inps.DestinationDir === '') { + return workDir; + } else { + return path.join(workDir, inps.DestinationDir); + } + })(); + core.info(`[INFO] ForceOrphan: ${inps.ForceOrphan}`); if (inps.ForceOrphan) { - await createWorkDir(workDir); + await createDir(destDir); process.chdir(workDir); await createBranchForce(inps.PublishBranch); - await copyAssets(publishDir, workDir); + process.chdir(destDir); + await copyAssets(publishDir, destDir); return; } @@ -68,7 +80,7 @@ export async function setRepo(inps: Inputs, remoteURL: string, workDir: string): await exec.exec('git', ['rm', '-r', '--ignore-unmatch', '*']); } - await copyAssets(publishDir, workDir); + await copyAssets(publishDir, destDir); return; } else { 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) { core.info(`[INFO] first deployment, create new branch ${inps.PublishBranch}`); core.info(e.message); - await createWorkDir(workDir); + await createDir(destDir); process.chdir(workDir); await createBranchForce(inps.PublishBranch); - await copyAssets(publishDir, workDir); + await copyAssets(publishDir, destDir); return; } } diff --git a/src/interfaces.ts b/src/interfaces.ts index 2cbd538ff..ad1babfed 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -4,6 +4,7 @@ export interface Inputs { readonly PersonalToken: string; readonly PublishBranch: string; readonly PublishDir: string; + readonly DestinationDir: string; readonly ExternalRepository: string; readonly AllowEmptyCommit: boolean; readonly KeepFiles: boolean; diff --git a/src/utils.ts b/src/utils.ts index 7a1d8d1ed..77e8b3ccb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -23,9 +23,9 @@ export async function getWorkDirName(unixTime: string): Promise { return workDirName; } -export async function createWorkDir(workDirName: string): Promise { - await io.mkdirP(workDirName); - core.debug(`Created: ${workDirName}`); +export async function createDir(dirPath: string): Promise { + await io.mkdirP(dirPath); + core.debug(`Created directory ${dirPath}`); return; }