1 |
|
2 | # gh-pages
|
3 |
|
4 | Publish files to a `gh-pages` branch on GitHub (or any other branch anywhere else).
|
5 |
|
6 | ## Getting Started
|
7 |
|
8 | ```shell
|
9 | npm install gh-pages --save-dev
|
10 | ```
|
11 |
|
12 | This module requires Git >= 1.9 and Node > 14.
|
13 |
|
14 | ## Basic Usage
|
15 |
|
16 | ```js
|
17 | var ghpages = require('gh-pages');
|
18 |
|
19 | ghpages.publish('dist', function(err) {});
|
20 | ```
|
21 |
|
22 |
|
23 | ## `publish`
|
24 |
|
25 | ```js
|
26 | ghpages.publish(dir, callback);
|
27 | // or...
|
28 | ghpages.publish(dir, options, callback);
|
29 | ```
|
30 |
|
31 | Calling 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 |
|
33 | If 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 |
|
41 | The base directory for all source files (those listed in the `src` config property).
|
42 |
|
43 | Example 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 | */
|
61 | ghpages.publish('dist', callback);
|
62 | ```
|
63 |
|
64 |
|
65 | ### Options
|
66 |
|
67 | The 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 |
|
74 | The [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 |
|
82 | The 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 |
|
84 | Example use of the `branch` option:
|
85 |
|
86 | ```js
|
87 | /**
|
88 | * This task pushes to the `master` branch of the configured `repo`.
|
89 | */
|
90 | ghpages.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 |
|
101 | The destination folder within the destination branch. By default, all files are published to the root of the repository.
|
102 |
|
103 | Example use of the `dest` option:
|
104 |
|
105 | ```js
|
106 | /**
|
107 | * Place content in the static/project subdirectory of the target
|
108 | * branch.
|
109 | */
|
110 | ghpages.publish('dist', {
|
111 | dest: 'static/project'
|
112 | }, callback);
|
113 | ```
|
114 |
|
115 | #### <a id="optionsdotfiles">options.dotfiles</a>
|
116 | * type: `boolean`
|
117 | * default: `false`
|
118 |
|
119 | Include 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 |
|
121 | Example 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 | */
|
128 | ghpages.publish('dist', {dotfiles: true}, callback);
|
129 | ```
|
130 |
|
131 | #### <a id="optionsnojekyll">options.nojekyll</a>
|
132 | * type: `boolean`
|
133 | * default: `false`
|
134 |
|
135 | Write out a `.nojekyll` file to [bypass Jekyll on GitHub Pages](https://github.blog/2009-12-29-bypassing-jekyll-on-github-pages/).
|
136 |
|
137 | Example use of the `nojekyll` option:
|
138 |
|
139 | ```js
|
140 | /**
|
141 | * The usage below will add a `.nojekyll` file to the output.
|
142 | */
|
143 | ghpages.publish('dist', {nojekyll: true}, callback);
|
144 | ```
|
145 |
|
146 | #### <a id="optionscname">options.cname</a>
|
147 | * type: `string`
|
148 |
|
149 | Write out a `CNAME` file with a custom domain name.
|
150 |
|
151 | Example use of the `cname` option:
|
152 |
|
153 | ```js
|
154 | /**
|
155 | * The usage below will add a `CNAME` file to the output.
|
156 | */
|
157 | ghpages.publish('dist', {cname: 'custom-domain.com'}, callback);
|
158 | ```
|
159 |
|
160 |
|
161 | #### <a id="optionsadd">options.add</a>
|
162 | * type: `boolean`
|
163 | * default: `false`
|
164 |
|
165 | Only 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 |
|
167 | Example 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 | */
|
174 | ghpages.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 |
|
183 | By 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 |
|
185 | If 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 |
|
187 | Example 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 | */
|
195 | ghpages.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 |
|
205 | The 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 |
|
207 | Example use of the `remote` option:
|
208 |
|
209 | ```js
|
210 | /**
|
211 | * This task pushes to the `gh-pages` branch of of your `upstream` remote.
|
212 | */
|
213 | ghpages.publish('dist', {
|
214 | remote: 'upstream'
|
215 | }, callback);
|
216 | ```
|
217 |
|
218 |
|
219 | #### <a id="optionstag">options.tag</a>
|
220 | * type: `string`
|
221 | * default: `''`
|
222 |
|
223 | Create 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 |
|
230 | The commit message for all commits.
|
231 |
|
232 | Example use of the `message` option:
|
233 |
|
234 | ```js
|
235 | /**
|
236 | * This adds commits with a custom message.
|
237 | */
|
238 | ghpages.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 |
|
248 | If 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 |
|
250 | Example use of the `user` option:
|
251 |
|
252 | ```js
|
253 | ghpages.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 |
|
265 | Removes files that match the given pattern (Ignored if used together with
|
266 | `--add`). By default, `gh-pages` removes everything inside the target branch
|
267 | auto-generated directory before copying the new files from `dir`.
|
268 |
|
269 | Example use of the `remove` option:
|
270 |
|
271 | ```js
|
272 | ghpages.publish('dist', {
|
273 | remove: "*.json"
|
274 | }, callback);
|
275 | ```
|
276 |
|
277 |
|
278 | #### <a id="optionspush">options.push</a>
|
279 | * type: `boolean`
|
280 | * default: `true`
|
281 |
|
282 | Push branch to remote. To commit only (with no push) set to `false`.
|
283 |
|
284 | Example use of the `push` option:
|
285 |
|
286 | ```js
|
287 | ghpages.publish('dist', {push: false}, callback);
|
288 | ```
|
289 |
|
290 |
|
291 | #### <a id="optionshistory">options.history</a>
|
292 | * type: `boolean`
|
293 | * default: `true`
|
294 |
|
295 | Push force new commit without parent history.
|
296 |
|
297 | Example use of the `history` option:
|
298 |
|
299 | ```js
|
300 | ghpages.publish('dist', {history: false}, callback);
|
301 | ```
|
302 |
|
303 |
|
304 | #### <a id="optionssilent">options.silent</a>
|
305 | * type: `boolean`
|
306 | * default: `false`
|
307 |
|
308 | Avoid showing repository URLs or other information in errors.
|
309 |
|
310 | Example use of the `silent` option:
|
311 |
|
312 | ```js
|
313 | /**
|
314 | * This configuration will avoid logging the GH_TOKEN if there is an error.
|
315 | */
|
316 | ghpages.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 |
|
327 | Custom callback that is executed right before `git add`.
|
328 |
|
329 | The CLI expects a file exporting the beforeAdd function
|
330 |
|
331 | ```bash
|
332 | gh-pages --before-add ./cleanup.js
|
333 | ```
|
334 |
|
335 | Example 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 | */
|
343 | ghpages.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 |
|
356 | Your `git` executable.
|
357 |
|
358 | Example use of the `git` option:
|
359 |
|
360 | ```js
|
361 | /**
|
362 | * If `git` is not on your path, provide the path as shown below.
|
363 | */
|
364 | ghpages.publish('dist', {
|
365 | git: '/path/to/git'
|
366 | }, callback);
|
367 | ```
|
368 |
|
369 | ## Command Line Utility
|
370 |
|
371 | Installing the package creates a `gh-pages` command line utility. Run `gh-pages --help` to see a list of supported options.
|
372 |
|
373 | With 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 |
|
381 | And then to publish everything from your `dist` folder to your `gh-pages` branch, you'd run this:
|
382 |
|
383 | ```shell
|
384 | npm run deploy
|
385 | ```
|
386 |
|
387 | ## GitHub Pages Project Sites
|
388 |
|
389 | There 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 |
|
391 | Examples:
|
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 |
|
397 | When 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 |
|
401 | To get additional output from the `gh-pages` script, set `NODE_DEBUG=gh-pages`. For example:
|
402 |
|
403 | ```shell
|
404 | NODE_DEBUG=gh-pages npm run deploy
|
405 | ```
|
406 |
|
407 | ## Dependencies
|
408 |
|
409 | Note 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 |
|
428 | The `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 |
|
430 | If `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 |
|
434 | Use 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 | ```
|
437 | gh-pages -d build --cname custom-domain.com"
|
438 | ```
|
439 |
|
440 | ### Deploying with GitHub Actions
|
441 |
|
442 | In 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 |
|
453 | The `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 |
|
455 | See [Issue #345](https://github.com/tschaub/gh-pages/issues/345) for more information
|
456 |
|
457 | #### Deploying with GitHub Actions and a named script
|
458 |
|
459 | If 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 |
|
467 | You 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 |
|
478 | See [Pull Request #368](https://github.com/tschaub/gh-pages/pull/368) for more information.
|