UNPKG

14.5 kBMarkdownView Raw
1
2# gh-pages
3
4Publish files to a `gh-pages` branch on GitHub (or any other branch anywhere else).
5
6## Getting Started
7
8```shell
9npm install gh-pages --save-dev
10```
11
12This module requires Git >= 1.9 and Node > 14.
13
14## Basic Usage
15
16```js
17var ghpages = require('gh-pages');
18
19ghpages.publish('dist', function(err) {});
20```
21
22
23## `publish`
24
25```js
26ghpages.publish(dir, callback);
27// or...
28ghpages.publish(dir, options, callback);
29```
30
31Calling this function will create a temporary clone of the current repository, create a `gh-pages` branch if one doesn't already exist, copy over all files from the base path, or only those that match patterns from the optional `src` configuration, commit all changes, and push to the `origin` remote.
32
33If a `gh-pages` branch already exists, it will be updated with all commits from the remote before adding any commits from the provided `src` files.
34
35**Note** that any files in the `gh-pages` branch that are *not* in the `src` files **will be removed**. See the [`add` option](#optionsadd) if you don't want any of the existing files removed.
36
37
38### <a id="dir">`dir`</a>
39* type: `string`
40
41The base directory for all source files (those listed in the `src` config property).
42
43Example use:
44
45```js
46/**
47 * Given the following directory structure:
48 *
49 * dist/
50 * index.html
51 * js/
52 * site.js
53 *
54 * The usage below will create a `gh-pages` branch that looks like this:
55 *
56 * index.html
57 * js/
58 * site.js
59 *
60 */
61ghpages.publish('dist', callback);
62```
63
64
65### Options
66
67The default options work for simple cases. The options described below let you push to alternate branches, customize your commit messages and more.
68
69
70#### <a id="optionssrc">options.src</a>
71 * type: `string|Array<string>`
72 * default: `'**/*'`
73
74The [minimatch](https://github.com/isaacs/minimatch) pattern or array of patterns is used to select which files should be published.
75
76
77#### <a id="optionsbranch">options.branch</a>
78 * type: `string`
79 * default: `'gh-pages'`
80 * `-b | --branch <branch name>`
81
82The name of the branch you'll be pushing to. The default uses GitHub's `gh-pages` branch, but this can be configured to push to any branch on any remote.
83
84Example use of the `branch` option:
85
86```js
87/**
88 * This task pushes to the `master` branch of the configured `repo`.
89 */
90ghpages.publish('dist', {
91 branch: 'master',
92 repo: 'https://example.com/other/repo.git'
93}, callback);
94```
95
96
97#### <a id="optionsdest">options.dest</a>
98 * type: `string`
99 * default: `'.'`
100
101The destination folder within the destination branch. By default, all files are published to the root of the repository.
102
103Example use of the `dest` option:
104
105```js
106/**
107 * Place content in the static/project subdirectory of the target
108 * branch.
109 */
110ghpages.publish('dist', {
111 dest: 'static/project'
112}, callback);
113```
114
115#### <a id="optionsdotfiles">options.dotfiles</a>
116 * type: `boolean`
117 * default: `false`
118
119Include dotfiles. By default, files starting with `.` are ignored unless they are explicitly provided in the `src` array. If you want to also include dotfiles that otherwise match your `src` patterns, set `dotfiles: true` in your options.
120
121Example use of the `dotfiles` option:
122
123```js
124/**
125 * The usage below will push dotfiles (directories and files)
126 * that otherwise match the `src` pattern.
127 */
128ghpages.publish('dist', {dotfiles: true}, callback);
129```
130
131#### <a id="optionsnojekyll">options.nojekyll</a>
132 * type: `boolean`
133 * default: `false`
134
135Write out a `.nojekyll` file to [bypass Jekyll on GitHub Pages](https://github.blog/2009-12-29-bypassing-jekyll-on-github-pages/).
136
137Example use of the `nojekyll` option:
138
139```js
140/**
141 * The usage below will add a `.nojekyll` file to the output.
142 */
143ghpages.publish('dist', {nojekyll: true}, callback);
144```
145
146#### <a id="optionscname">options.cname</a>
147 * type: `string`
148
149Write out a `CNAME` file with a custom domain name.
150
151Example use of the `cname` option:
152
153```js
154/**
155 * The usage below will add a `CNAME` file to the output.
156 */
157ghpages.publish('dist', {cname: 'custom-domain.com'}, callback);
158```
159
160
161#### <a id="optionsadd">options.add</a>
162 * type: `boolean`
163 * default: `false`
164
165Only add, and never remove existing files. By default, existing files in the target branch are removed before adding the ones from your `src` config. If you want the task to add new `src` files but leave existing ones untouched, set `add: true` in your options.
166
167Example use of the `add` option:
168
169```js
170/**
171 * The usage below will only add files to the `gh-pages` branch, never removing
172 * any existing files (even if they don't exist in the `src` config).
173 */
174ghpages.publish('dist', {add: true}, callback);
175```
176
177
178#### <a id="optionsrepo">options.repo</a>
179 * type: `string`
180 * default: url for the origin remote of the current dir (assumes a git repository)
181 * `-r | --repo <repo url>`
182
183By default, `gh-pages` assumes that the current working directory is a git repository, and that you want to push changes to the `origin` remote.
184
185If instead your script is not in a git repository, or if you want to push to another repository, you can provide the repository URL in the `repo` option.
186
187Example use of the `repo` option:
188
189```js
190/**
191 * If the current directory is not a clone of the repository you want to work
192 * with, set the URL for the repository in the `repo` option. This usage will
193 * push all files in the `src` config to the `gh-pages` branch of the `repo`.
194 */
195ghpages.publish('dist', {
196 repo: 'https://example.com/other/repo.git'
197}, callback);
198```
199
200
201#### <a id="optionsremote">options.remote</a>
202 * type: `string`
203 * default: `'origin'`
204
205The name of the remote you'll be pushing to. The default is your `'origin'` remote, but this can be configured to push to any remote.
206
207Example use of the `remote` option:
208
209```js
210/**
211 * This task pushes to the `gh-pages` branch of of your `upstream` remote.
212 */
213ghpages.publish('dist', {
214 remote: 'upstream'
215}, callback);
216```
217
218
219#### <a id="optionstag">options.tag</a>
220 * type: `string`
221 * default: `''`
222
223Create a tag after committing changes on the target branch. By default, no tag is created. To create a tag, provide the tag name as the option value.
224
225
226#### <a id="optionsmessage">options.message</a>
227 * type: `string`
228 * default: `'Updates'`
229
230The commit message for all commits.
231
232Example use of the `message` option:
233
234```js
235/**
236 * This adds commits with a custom message.
237 */
238ghpages.publish('dist', {
239 message: 'Auto-generated commit'
240}, callback);
241```
242
243
244#### <a id="optionsuser">options.user</a>
245 * type: `Object`
246 * default: `null`
247
248If you are running the `gh-pages` task in a repository without a `user.name` or `user.email` git config properties (or on a machine without these global config properties), you must provide user info before git allows you to commit. The `options.user` object accepts `name` and `email` string values to identify the committer.
249
250Example use of the `user` option:
251
252```js
253ghpages.publish('dist', {
254 user: {
255 name: 'Joe Code',
256 email: 'coder@example.com'
257 }
258}, callback);
259```
260
261#### <a id="optionsuser">options.remove</a>
262 * type: `string`
263 * default: `'.'`
264
265Removes files that match the given pattern (Ignored if used together with
266`--add`). By default, `gh-pages` removes everything inside the target branch
267auto-generated directory before copying the new files from `dir`.
268
269Example use of the `remove` option:
270
271```js
272ghpages.publish('dist', {
273 remove: "*.json"
274}, callback);
275```
276
277
278#### <a id="optionspush">options.push</a>
279 * type: `boolean`
280 * default: `true`
281
282Push branch to remote. To commit only (with no push) set to `false`.
283
284Example use of the `push` option:
285
286```js
287ghpages.publish('dist', {push: false}, callback);
288```
289
290
291#### <a id="optionshistory">options.history</a>
292 * type: `boolean`
293 * default: `true`
294
295Push force new commit without parent history.
296
297Example use of the `history` option:
298
299```js
300ghpages.publish('dist', {history: false}, callback);
301```
302
303
304#### <a id="optionssilent">options.silent</a>
305 * type: `boolean`
306 * default: `false`
307
308Avoid showing repository URLs or other information in errors.
309
310Example use of the `silent` option:
311
312```js
313/**
314 * This configuration will avoid logging the GH_TOKEN if there is an error.
315 */
316ghpages.publish('dist', {
317 repo: 'https://' + process.env.GH_TOKEN + '@github.com/user/private-repo.git',
318 silent: true
319}, callback);
320```
321
322
323#### <a id="optionsbeforeadd">options.beforeAdd</a>
324 * type: `function`
325 * default: `null`
326
327Custom callback that is executed right before `git add`.
328
329The CLI expects a file exporting the beforeAdd function
330
331```bash
332gh-pages --before-add ./cleanup.js
333```
334
335Example use of the `beforeAdd` option:
336
337```js
338/**
339 * beforeAdd makes most sense when `add` option is active
340 * Assuming we want to keep everything on the gh-pages branch
341 * but remove just `some-outdated-file.txt`
342 */
343ghpages.publish('dist', {
344 add: true,
345 async beforeAdd(git) {
346 return git.rm('./some-outdated-file.txt');
347 }
348}, callback);
349```
350
351
352#### <a id="optionsgit">options.git</a>
353 * type: `string`
354 * default: `'git'`
355
356Your `git` executable.
357
358Example use of the `git` option:
359
360```js
361/**
362 * If `git` is not on your path, provide the path as shown below.
363 */
364ghpages.publish('dist', {
365 git: '/path/to/git'
366}, callback);
367```
368
369## Command Line Utility
370
371Installing the package creates a `gh-pages` command line utility. Run `gh-pages --help` to see a list of supported options.
372
373With a local install of `gh-pages`, you can set up a package script with something like the following:
374
375```shell
376"scripts": {
377 "deploy": "gh-pages -d dist"
378}
379```
380
381And then to publish everything from your `dist` folder to your `gh-pages` branch, you'd run this:
382
383```shell
384npm run deploy
385```
386
387## GitHub Pages Project Sites
388
389There are three types of GitHub Pages sites: [project, user, and organization](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#types-of-github-pages-sites). Since project sites are not hosted on the root `<user|org>.github.io` domain and instead under a URL path based on the repository name, they often require configuration tweaks for various build tools and frameworks. If not configured properly, a browser will usually log `net::ERR_ABORTED 404` errors when looking for compiled assets.
390
391Examples:
392- Create React App (which uses webpack under the hood) [requires the user to set a `"homepage"` property in their `package.json` so that built assets are referenced correctly in the final compiled HTML](https://create-react-app.dev/docs/deployment/#building-for-relative-paths).
393 - This [has been often been thought of as an issue with `gh-pages`](https://github.com/tschaub/gh-pages/issues/285#issuecomment-805321474), though this package isn't able to control a project's build configuration.
394- Vite [requires a `"base"` property in its `vite.config.js`](https://vitejs.dev/guide/static-deploy.html#github-pages)
395- Next.js [requires a `"basePath"` property in its `next.config.js`](https://nextjs.org/docs/pages/api-reference/next-config-js/basePath)
396
397When using a project site, be sure to read the documentation for your particular build tool or framework to learn how to configure correct asset paths.
398
399## Debugging
400
401To get additional output from the `gh-pages` script, set `NODE_DEBUG=gh-pages`. For example:
402
403```shell
404NODE_DEBUG=gh-pages npm run deploy
405```
406
407## Dependencies
408
409Note that this plugin requires Git 1.9 or higher (because it uses the `--exit-code` option for `git ls-remote`). If you'd like to see this working with earlier versions of Git, please [open an issue](https://github.com/tschaub/gh-pages/issues).
410
411![Test Status](https://github.com/tschaub/gh-pages/workflows/Test/badge.svg)
412
413## Tips
414
415### when get error `branch already exists`
416```
417{ ProcessError: fatal: A branch named 'gh-pages' already exists.
418
419 at ChildProcess.<anonymous> (~/node_modules/gh-pages/lib/git.js:42:16)
420 at ChildProcess.emit (events.js:180:13)
421 at maybeClose (internal/child_process.js:936:16)
422 at Process.ChildProcess._handle.onexit (internal/child_process.js:220:5)
423 code: 128,
424 message: 'fatal: A branch named \'gh-pages\' already exists.\n',
425 name: 'ProcessError' }
426 ```
427
428The `gh-pages` module writes temporary files to a `node_modules/.cache/gh-pages` directory. The location of this directory can be customized by setting the `CACHE_DIR` environment variable.
429
430If `gh-pages` fails, you may find that you need to manually clean up the cache directory. To remove the cache directory, run `node_modules/gh-pages/bin/gh-pages-clean` or remove `node_modules/.cache/gh-pages`.
431
432### Deploying to github pages with custom domain
433
434Use the `--cname` option to create a `CNAME` file with the name of your custom domain. See [the GitHub docs](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site) for more detail.
435
436```
437gh-pages -d build --cname custom-domain.com"
438```
439
440### Deploying with GitHub Actions
441
442In order to deploy with GitHub Actions, you will need to define a user and set the git repository for the process. See the example step below
443
444```yaml
445- name: Deploy with gh-pages
446 run: |
447 git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
448 npx gh-pages -d build -u "github-actions-bot <support+actions@github.com>"
449 env:
450 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
451```
452
453The `secrets.GITHUB_TOKEN` is provided automatically as part of the GitHub Action and does not require any further configuration, but simply needs to be passed in as an environmental variable to the step. `GITHUB_REPOSITORY` is the owner and repository name and is also passed in automatically, but does not need to be added to the `env` list.
454
455See [Issue #345](https://github.com/tschaub/gh-pages/issues/345) for more information
456
457#### Deploying with GitHub Actions and a named script
458
459If you are using a named script in the `package.json` file to deploy, you will need to ensure you pass the variables properly to the wrapped `gh-pages` script. Given the `package.json` script below:
460
461```json
462"scripts": {
463 "deploy": "gh-pages -d build"
464}
465```
466
467You will need to utilize the `--` option to pass any additional arguments:
468
469```yaml
470- name: Deploy with gh-pages
471 run: |
472 git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
473 npm run deploy -- -u "github-actions-bot <support+actions@github.com>"
474 env:
475 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
476```
477
478See [Pull Request #368](https://github.com/tschaub/gh-pages/pull/368) for more information.