oneclickpush 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -33
- package/cli.js +84 -36
- package/index.d.ts +23 -54
- package/index.js +19 -21
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -16,27 +16,28 @@ none of these, has zero dependencies and only uses built-in Node APIs + `git`.
|
|
|
16
16
|
Deploy your build directory (e.g. `dist`) to the `gh-pages` branch:
|
|
17
17
|
|
|
18
18
|
```text
|
|
19
|
-
$
|
|
20
|
-
$ npx oneclickpush
|
|
19
|
+
$ npx oneclickpush dist
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
## CLI Usage
|
|
24
23
|
|
|
25
24
|
```text
|
|
26
|
-
Usage: oneclickpush [options]
|
|
25
|
+
Usage: oneclickpush <dir> [options]
|
|
27
26
|
|
|
28
27
|
Replace the contents of a remote git branch with that of a local directory.
|
|
29
28
|
|
|
29
|
+
Arguments:
|
|
30
|
+
dir Directory to deploy (required)
|
|
31
|
+
|
|
30
32
|
Options:
|
|
31
|
-
-
|
|
32
|
-
-e, --exclude <glob> Paths to leave out, relative to dist (default: "**/.DS_Store")
|
|
33
|
+
-e, --exclude <glob> Paths to leave out, relative to dir (default: "**/.DS_Store")
|
|
33
34
|
-b, --branch <name> Target branch (default: "gh-pages")
|
|
34
35
|
-m, --message <msg> Commit message (default: "Updates")
|
|
35
|
-
-r, --remote <name|url> Remote name or repo URL to
|
|
36
|
+
-r, --remote <name|url> Remote name or repo URL to deploy to (default: "origin")
|
|
36
37
|
-a, --author <author> Commit author, as "Name <email>"
|
|
37
38
|
-f, --force Force push new commit with no history
|
|
38
39
|
-n, --dry-run Show what would change, without committing or pushing
|
|
39
|
-
-
|
|
40
|
+
-l, --log-level <level> Output: silent, normal or verbose (default: "normal")
|
|
40
41
|
-V, --version Print version
|
|
41
42
|
-h, --help Show this help
|
|
42
43
|
```
|
|
@@ -45,27 +46,46 @@ Options:
|
|
|
45
46
|
> `--exclude` takes glob patterns (`*`, `**`, `?`) and can be repeated. Patterns are matched against
|
|
46
47
|
> the full path, so use `**/name` to match at any depth.
|
|
47
48
|
|
|
49
|
+
### Log levels
|
|
50
|
+
|
|
51
|
+
| Level | Behavior |
|
|
52
|
+
| --------- | -------------------------------------------------------------------- |
|
|
53
|
+
| `silent` | Prints nothing, not even errors. Check the exit code instead. |
|
|
54
|
+
| `normal` | Prints the result and error messages (plus a spinner in a terminal). |
|
|
55
|
+
| `verbose` | Also logs every git command to stderr and prints full errors. |
|
|
56
|
+
|
|
57
|
+
> [!WARNING]
|
|
58
|
+
> If your remote URL contains a token (e.g. `https://user:TOKEN@github.com/o/r.git`), git error
|
|
59
|
+
> messages shown at `normal` and `verbose` may include it. Use `-l silent` in CI, or keep tokens out
|
|
60
|
+
> of the URL with a credential helper.
|
|
61
|
+
|
|
48
62
|
### Examples
|
|
49
63
|
|
|
50
64
|
```bash
|
|
51
65
|
# Preview what would be deployed without pushing
|
|
52
|
-
npx oneclickpush
|
|
66
|
+
npx oneclickpush build --dry-run
|
|
53
67
|
|
|
54
68
|
# Custom branch and commit message
|
|
55
|
-
npx oneclickpush
|
|
69
|
+
npx oneclickpush public -b release -m "deploy: v1.0.0"
|
|
56
70
|
|
|
57
71
|
# Exclude source maps and test files
|
|
58
|
-
npx oneclickpush
|
|
72
|
+
npx oneclickpush dist -e "**/*.map" -e "**/tests/**"
|
|
59
73
|
|
|
60
74
|
# Deploy to a different remote or repository URL
|
|
61
|
-
npx oneclickpush
|
|
62
|
-
npx oneclickpush
|
|
75
|
+
npx oneclickpush dist -r upstream
|
|
76
|
+
npx oneclickpush dist -r git@github.com:user/repo.git
|
|
63
77
|
|
|
64
78
|
# Set commit author (useful in CI environments)
|
|
65
|
-
npx oneclickpush
|
|
79
|
+
npx oneclickpush dist -a "Deploy Bot <bot@example.com>"
|
|
66
80
|
|
|
67
81
|
# Force push fresh history
|
|
68
|
-
npx oneclickpush
|
|
82
|
+
npx oneclickpush dist --force
|
|
83
|
+
|
|
84
|
+
# Silent output (useful in CI, check the exit code)
|
|
85
|
+
npx oneclickpush dist -l silent
|
|
86
|
+
|
|
87
|
+
# Log every git command
|
|
88
|
+
npx oneclickpush dist -l verbose
|
|
69
89
|
```
|
|
70
90
|
|
|
71
91
|
## Programmatic API
|
|
@@ -73,15 +93,15 @@ npx oneclickpush -d dist --force
|
|
|
73
93
|
You can also use `oneclickpush` as an ES module:
|
|
74
94
|
|
|
75
95
|
```bash
|
|
76
|
-
# Install
|
|
96
|
+
# Install
|
|
77
97
|
npm i oneclickpush
|
|
78
98
|
```
|
|
79
99
|
|
|
80
100
|
```javascript
|
|
81
|
-
import {
|
|
101
|
+
import { deploy } from 'oneclickpush'
|
|
82
102
|
|
|
83
|
-
const changes = await
|
|
84
|
-
|
|
103
|
+
const changes = await deploy({
|
|
104
|
+
dir: 'dist',
|
|
85
105
|
exclude: ['**/.DS_Store', '**/*.map'],
|
|
86
106
|
branch: 'gh-pages',
|
|
87
107
|
message: 'Deploy updates',
|
|
@@ -93,25 +113,25 @@ const changes = await publish({
|
|
|
93
113
|
})
|
|
94
114
|
|
|
95
115
|
if (changes) {
|
|
96
|
-
console.log('
|
|
116
|
+
console.log('Deployed changes:\n' + changes)
|
|
97
117
|
} else {
|
|
98
|
-
console.log('Nothing to
|
|
118
|
+
console.log('Nothing to deploy')
|
|
99
119
|
}
|
|
100
120
|
```
|
|
101
121
|
|
|
102
122
|
### Options
|
|
103
123
|
|
|
104
|
-
|
|
|
124
|
+
| Name | Type | Default | Description |
|
|
105
125
|
| --------- | ---------- | ------------------ | --------------------------------------------------- |
|
|
106
|
-
| `
|
|
107
|
-
| `exclude` | `string[]` | `["**/.DS_Store"]` | Paths to exclude relative to `
|
|
126
|
+
| `dir` | `string` | - (required) | Directory to deploy |
|
|
127
|
+
| `exclude` | `string[]` | `["**/.DS_Store"]` | Paths to exclude relative to `dir` |
|
|
108
128
|
| `branch` | `string` | `"gh-pages"` | Target git branch |
|
|
109
129
|
| `message` | `string` | `"Updates"` | Git commit message |
|
|
110
|
-
| `remote` | `string` | `"origin"` | Remote name or repository URL/path to
|
|
111
|
-
| `author` | `string` |
|
|
130
|
+
| `remote` | `string` | `"origin"` | Remote name or repository URL/path to deploy to |
|
|
131
|
+
| `author` | `string` | - | Commit author and committer, as `"Name <email>"` |
|
|
112
132
|
| `force` | `boolean` | `false` | Force push fresh commit with no previous history |
|
|
113
133
|
| `dryRun` | `boolean` | `false` | Return staged changes without committing or pushing |
|
|
114
|
-
| `verbose` | `boolean` | `false` |
|
|
134
|
+
| `verbose` | `boolean` | `false` | Logs git commands to stderr |
|
|
115
135
|
|
|
116
136
|
## How It Works
|
|
117
137
|
|
|
@@ -119,7 +139,7 @@ if (changes) {
|
|
|
119
139
|
URL/path directly.
|
|
120
140
|
2. Creates an isolated temporary directory and fetches the target branch (or initializes it if it
|
|
121
141
|
doesn't exist).
|
|
122
|
-
3. Clears the target branch index and stages the contents of `
|
|
142
|
+
3. Clears the target branch index and stages the contents of `dir` (minus `exclude` patterns)
|
|
123
143
|
directly via Git `work-tree`.
|
|
124
144
|
4. Checks for differences (`git diff --cached --name-status`). If there are changes, commits and
|
|
125
145
|
pushes back to the remote repository.
|
|
@@ -130,12 +150,14 @@ if (changes) {
|
|
|
130
150
|
|
|
131
151
|
### Notes
|
|
132
152
|
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
- The target branch is fully replaced with the contents of `dir` (WYSIWYG), and it's created if it
|
|
154
|
+
doesn't exist yet. If you need files like `.nojekyll` or `CNAME`, put them in `dir`, adding a
|
|
155
|
+
post-build step if your build tool wipes the directory.
|
|
156
|
+
- Dotfiles are included by default, except `.DS_Store`. Use `-e` to exclude more, but note that it
|
|
157
|
+
replaces the default list, so repeat `-e "**/.DS_Store"` if you still want that file excluded.
|
|
158
|
+
- When `--remote` is a repository URL or path, you don't need to run from inside a git repository.
|
|
159
|
+
- In dry-run output, identical content moved to a new path appears as a rename (`R100`).
|
|
160
|
+
- A directory starting with `-` must come after `--`, e.g. `oneclickpush -- -weird-dir`.
|
|
139
161
|
|
|
140
162
|
## License
|
|
141
163
|
|
package/cli.js
CHANGED
|
@@ -1,48 +1,77 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { parseArgs } from 'node:util'
|
|
3
3
|
import { readFileSync } from 'node:fs'
|
|
4
|
-
import {
|
|
4
|
+
import { deploy } from './index.js'
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const DEFAULTS = {
|
|
7
|
+
exclude: ['**/.DS_Store'],
|
|
8
|
+
branch: 'gh-pages',
|
|
9
|
+
message: 'Updates',
|
|
10
|
+
remote: 'origin',
|
|
11
|
+
force: false,
|
|
12
|
+
dryRun: false,
|
|
13
|
+
logLevel: 'normal'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const HELP = `Usage: oneclickpush <dir> [options]
|
|
7
17
|
|
|
8
18
|
Replace the contents of a remote git branch with that of a
|
|
9
19
|
local directory.
|
|
10
20
|
|
|
21
|
+
Arguments:
|
|
22
|
+
dir Directory to deploy (required)
|
|
23
|
+
|
|
11
24
|
Options:
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
(default: "origin")
|
|
25
|
+
-e, --exclude <glob> Paths to leave out, relative to dir
|
|
26
|
+
(default: "${DEFAULTS.exclude.join(', ')}")
|
|
27
|
+
-b, --branch <name> Target branch (default: "${DEFAULTS.branch}")
|
|
28
|
+
-m, --message <msg> Commit message (default: "${DEFAULTS.message}")
|
|
29
|
+
-r, --remote <name|url> Remote name or repo URL to deploy to
|
|
30
|
+
(default: "${DEFAULTS.remote}")
|
|
19
31
|
-a, --author <author> Commit author, as "Name <email>"
|
|
20
32
|
-f, --force Force push new commit with no history
|
|
21
33
|
-n, --dry-run Show what would change, without
|
|
22
34
|
committing or pushing
|
|
23
|
-
-
|
|
35
|
+
-l, --log-level <level> Output: silent, normal or verbose
|
|
36
|
+
(default: "${DEFAULTS.logLevel}")
|
|
24
37
|
-V, --version Print version
|
|
25
38
|
-h, --help Show this help
|
|
26
39
|
|
|
27
40
|
--exclude takes glob patterns (*, **, ?) and can be repeated.
|
|
28
41
|
Patterns are matched against the full path, so use **/name to
|
|
29
|
-
match at any depth
|
|
42
|
+
match at any depth.
|
|
43
|
+
|
|
44
|
+
Log levels: "silent" prints nothing (check the exit code),
|
|
45
|
+
"normal" prints the result and errors, "verbose" also logs git
|
|
46
|
+
commands and full errors.`
|
|
30
47
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
const LEVELS = ['silent', 'normal', 'verbose']
|
|
49
|
+
|
|
50
|
+
const { values: v, positionals } = (() => {
|
|
51
|
+
try {
|
|
52
|
+
return parseArgs({
|
|
53
|
+
allowPositionals: true,
|
|
54
|
+
options: {
|
|
55
|
+
exclude: { type: 'string', short: 'e', multiple: true, default: DEFAULTS.exclude },
|
|
56
|
+
branch: { type: 'string', short: 'b', default: DEFAULTS.branch },
|
|
57
|
+
message: { type: 'string', short: 'm', default: DEFAULTS.message },
|
|
58
|
+
remote: { type: 'string', short: 'r', default: DEFAULTS.remote },
|
|
59
|
+
author: { type: 'string', short: 'a' },
|
|
60
|
+
force: { type: 'boolean', short: 'f', default: DEFAULTS.force },
|
|
61
|
+
'dry-run': { type: 'boolean', short: 'n', default: DEFAULTS.dryRun },
|
|
62
|
+
'log-level': { type: 'string', short: 'l', default: DEFAULTS.logLevel },
|
|
63
|
+
version: { type: 'boolean', short: 'V', default: false },
|
|
64
|
+
help: { type: 'boolean', short: 'h', default: false }
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
} catch (/** @type {any} */ e) {
|
|
68
|
+
if (!e.code?.startsWith('ERR_PARSE_ARGS_')) throw e
|
|
69
|
+
// Keep only the first sentence, Node appends a long "-- " hint to some messages
|
|
70
|
+
const msg = e.message.split('. ')[0].replace(/\.$/, '')
|
|
71
|
+
console.error(`${msg}, run "oneclickpush --help" for usage`)
|
|
72
|
+
process.exit(1)
|
|
44
73
|
}
|
|
45
|
-
})
|
|
74
|
+
})()
|
|
46
75
|
|
|
47
76
|
if (v.help) {
|
|
48
77
|
console.log(HELP)
|
|
@@ -55,27 +84,46 @@ if (v.version) {
|
|
|
55
84
|
process.exit(0)
|
|
56
85
|
}
|
|
57
86
|
|
|
58
|
-
|
|
87
|
+
if (positionals.length !== 1) {
|
|
88
|
+
console.error(
|
|
89
|
+
positionals.length === 0
|
|
90
|
+
? 'Missing required argument <dir>, run "oneclickpush --help" for usage'
|
|
91
|
+
: 'Expected exactly one directory, run "oneclickpush --help" for usage'
|
|
92
|
+
)
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
95
|
+
const dir = positionals[0]
|
|
96
|
+
|
|
97
|
+
const level = v['log-level']
|
|
98
|
+
if (!LEVELS.includes(level)) {
|
|
99
|
+
console.error(`Invalid --log-level "${level}", expected one of: ${LEVELS.join(', ')}`)
|
|
100
|
+
process.exit(1)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Dead simple spinner (normal level, TTY only)
|
|
59
104
|
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
60
105
|
let i = 0
|
|
61
106
|
const spin =
|
|
62
|
-
process.stderr.isTTY &&
|
|
107
|
+
process.stderr.isTTY && level === 'normal'
|
|
63
108
|
? setInterval(() => process.stderr.write(`\r${frames[i++ % frames.length]}`), 100)
|
|
64
109
|
: null
|
|
65
110
|
const stop = () => spin && (clearInterval(spin), process.stderr.write('\r \r'))
|
|
66
111
|
|
|
67
112
|
try {
|
|
68
|
-
const changes = await
|
|
113
|
+
const changes = await deploy({ ...v, dir, verbose: level === 'verbose', dryRun: v['dry-run'] })
|
|
69
114
|
stop()
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
115
|
+
if (level !== 'silent') {
|
|
116
|
+
console.log(
|
|
117
|
+
!changes
|
|
118
|
+
? 'Nothing to deploy'
|
|
119
|
+
: v['dry-run']
|
|
120
|
+
? `Dry run, would deploy:\n${changes}`
|
|
121
|
+
: 'Deployed!'
|
|
122
|
+
)
|
|
123
|
+
}
|
|
77
124
|
} catch (/** @type {any} */ e) {
|
|
78
125
|
stop()
|
|
79
|
-
console.error(
|
|
126
|
+
if (level === 'verbose') console.error(e)
|
|
127
|
+
else if (level === 'normal') console.error(e.message)
|
|
80
128
|
process.exit(1)
|
|
81
129
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,61 +1,20 @@
|
|
|
1
|
-
export type OneclickpushOptions = {
|
|
2
|
-
/**
|
|
3
|
-
* Directory to publish
|
|
4
|
-
*/
|
|
5
|
-
dist?: string
|
|
6
|
-
/**
|
|
7
|
-
* Paths to leave out, relative to dist (default: `**\/.DS_Store`)
|
|
8
|
-
*/
|
|
9
|
-
exclude?: string[]
|
|
10
|
-
/**
|
|
11
|
-
* Target branch
|
|
12
|
-
*/
|
|
13
|
-
branch?: string
|
|
14
|
-
/**
|
|
15
|
-
* Commit message
|
|
16
|
-
*/
|
|
17
|
-
message?: string
|
|
18
|
-
/**
|
|
19
|
-
* Remote name of the current repo, or a repository URL or path
|
|
20
|
-
*/
|
|
21
|
-
remote?: string
|
|
22
|
-
/**
|
|
23
|
-
* Commit author and committer as "Name <email>"
|
|
24
|
-
*/
|
|
25
|
-
author?: string
|
|
26
|
-
/**
|
|
27
|
-
* Force push new commit with no history
|
|
28
|
-
*/
|
|
29
|
-
force?: boolean
|
|
30
|
-
/**
|
|
31
|
-
* Show what would change, without committing or pushing
|
|
32
|
-
*/
|
|
33
|
-
dryRun?: boolean
|
|
34
|
-
/**
|
|
35
|
-
* Log git commands
|
|
36
|
-
*/
|
|
37
|
-
verbose?: boolean
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* @typedef {object} OneclickpushOptions
|
|
41
|
-
* @prop {string} [dist="."] Directory to publish
|
|
42
|
-
* @prop {string[]} [exclude] Paths to leave out, relative to dist (default: `**\/.DS_Store`)
|
|
43
|
-
* @prop {string} [branch="gh-pages"] Target branch
|
|
44
|
-
* @prop {string} [message="Updates"] Commit message
|
|
45
|
-
* @prop {string} [remote="origin"] Remote name of the current repo, or a repository URL or path
|
|
46
|
-
* @prop {string} [author] Commit author and committer as "Name <email>"
|
|
47
|
-
* @prop {boolean} [force=false] Force push new commit with no history
|
|
48
|
-
* @prop {boolean} [dryRun=false] Show what would change, without committing or pushing
|
|
49
|
-
* @prop {boolean} [verbose=false] Log git commands
|
|
50
|
-
*/
|
|
51
1
|
/**
|
|
52
2
|
* Replace the contents of a git branch with the contents of a directory.
|
|
53
3
|
* Returns the staged changes as `git diff --name-status` text or "" if nothing changed.
|
|
54
|
-
* @param {
|
|
4
|
+
* @param {object} o
|
|
5
|
+
* @param {string} o.dir Directory to deploy (required)
|
|
6
|
+
* @param {string[]} [o.exclude] Paths to leave out, relative to dir (default: `**\/.DS_Store`)
|
|
7
|
+
* @param {string} [o.branch="gh-pages"] Target branch
|
|
8
|
+
* @param {string} [o.message="Updates"] Commit message
|
|
9
|
+
* @param {string} [o.remote="origin"] Remote name of the current repo, or a repository URL or path
|
|
10
|
+
* @param {string} [o.author] Commit author and committer as "Name <email>"
|
|
11
|
+
* @param {boolean} [o.force=false] Force push new commit with no history
|
|
12
|
+
* @param {boolean} [o.dryRun=false] Return staged changes without committing or pushing
|
|
13
|
+
* @param {boolean} [o.verbose=false] Log git commands to stderr
|
|
55
14
|
* @returns {Promise<string>}
|
|
56
15
|
*/
|
|
57
|
-
export declare function
|
|
58
|
-
|
|
16
|
+
export declare function deploy({
|
|
17
|
+
dir,
|
|
59
18
|
exclude,
|
|
60
19
|
branch,
|
|
61
20
|
message,
|
|
@@ -64,4 +23,14 @@ export declare function publish({
|
|
|
64
23
|
force,
|
|
65
24
|
dryRun,
|
|
66
25
|
verbose
|
|
67
|
-
}:
|
|
26
|
+
}: {
|
|
27
|
+
dir: string
|
|
28
|
+
exclude?: string[]
|
|
29
|
+
branch?: string
|
|
30
|
+
message?: string
|
|
31
|
+
remote?: string
|
|
32
|
+
author?: string
|
|
33
|
+
force?: boolean
|
|
34
|
+
dryRun?: boolean
|
|
35
|
+
verbose?: boolean
|
|
36
|
+
}): Promise<string>
|
package/index.js
CHANGED
|
@@ -4,27 +4,23 @@ import { mkdtemp, rm } from 'node:fs/promises'
|
|
|
4
4
|
import { tmpdir } from 'node:os'
|
|
5
5
|
import { join, resolve } from 'node:path'
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {object} OneclickpushOptions
|
|
9
|
-
* @prop {string} [dist="."] Directory to publish
|
|
10
|
-
* @prop {string[]} [exclude] Paths to leave out, relative to dist (default: `**\/.DS_Store`)
|
|
11
|
-
* @prop {string} [branch="gh-pages"] Target branch
|
|
12
|
-
* @prop {string} [message="Updates"] Commit message
|
|
13
|
-
* @prop {string} [remote="origin"] Remote name of the current repo, or a repository URL or path
|
|
14
|
-
* @prop {string} [author] Commit author and committer as "Name <email>"
|
|
15
|
-
* @prop {boolean} [force=false] Force push new commit with no history
|
|
16
|
-
* @prop {boolean} [dryRun=false] Show what would change, without committing or pushing
|
|
17
|
-
* @prop {boolean} [verbose=false] Log git commands
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
7
|
/**
|
|
21
8
|
* Replace the contents of a git branch with the contents of a directory.
|
|
22
9
|
* Returns the staged changes as `git diff --name-status` text or "" if nothing changed.
|
|
23
|
-
* @param {
|
|
10
|
+
* @param {object} o
|
|
11
|
+
* @param {string} o.dir Directory to deploy (required)
|
|
12
|
+
* @param {string[]} [o.exclude] Paths to leave out, relative to dir (default: `**\/.DS_Store`)
|
|
13
|
+
* @param {string} [o.branch="gh-pages"] Target branch
|
|
14
|
+
* @param {string} [o.message="Updates"] Commit message
|
|
15
|
+
* @param {string} [o.remote="origin"] Remote name of the current repo, or a repository URL or path
|
|
16
|
+
* @param {string} [o.author] Commit author and committer as "Name <email>"
|
|
17
|
+
* @param {boolean} [o.force=false] Force push new commit with no history
|
|
18
|
+
* @param {boolean} [o.dryRun=false] Return staged changes without committing or pushing
|
|
19
|
+
* @param {boolean} [o.verbose=false] Log git commands to stderr
|
|
24
20
|
* @returns {Promise<string>}
|
|
25
21
|
*/
|
|
26
|
-
export async function
|
|
27
|
-
|
|
22
|
+
export async function deploy({
|
|
23
|
+
dir,
|
|
28
24
|
exclude = ['**/.DS_Store'],
|
|
29
25
|
branch = 'gh-pages',
|
|
30
26
|
message = 'Updates',
|
|
@@ -34,7 +30,8 @@ export async function publish({
|
|
|
34
30
|
dryRun = false,
|
|
35
31
|
verbose = false
|
|
36
32
|
}) {
|
|
37
|
-
|
|
33
|
+
if (!dir) throw new Error('dir is required')
|
|
34
|
+
dir = resolve(dir)
|
|
38
35
|
const run = promisify(execFile)
|
|
39
36
|
|
|
40
37
|
// Env vars beat git config, so this also overrides any identity already set in CI
|
|
@@ -54,7 +51,8 @@ export async function publish({
|
|
|
54
51
|
/** @type {(args: string[], cwd?: string, env?: Record<string, string>) => Promise<string>} */
|
|
55
52
|
const git = async (args, cwd, env) => {
|
|
56
53
|
if (verbose) console.error(`$ git ${args.join(' ')}`)
|
|
57
|
-
|
|
54
|
+
const { stdout } = await run('git', args, { cwd, env: { ...process.env, ...env } })
|
|
55
|
+
return stdout.trim()
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
// A remote name resolves to its url; anything else is used as a url or path as-is
|
|
@@ -82,21 +80,21 @@ export async function publish({
|
|
|
82
80
|
await git(['remote', 'add', 'origin', url], tmp)
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
// Empty the index, then stage everything from
|
|
83
|
+
// Empty the index, then stage everything from dir except excluded paths
|
|
86
84
|
await git(['read-tree', '--empty'], tmp)
|
|
87
85
|
await git(
|
|
88
86
|
[
|
|
89
87
|
'--git-dir',
|
|
90
88
|
join(tmp, '.git'),
|
|
91
89
|
'--work-tree',
|
|
92
|
-
|
|
90
|
+
dir,
|
|
93
91
|
'add',
|
|
94
92
|
'--force',
|
|
95
93
|
'--',
|
|
96
94
|
'.',
|
|
97
95
|
...exclude.map((p) => `:(exclude,glob)${p}`)
|
|
98
96
|
],
|
|
99
|
-
|
|
97
|
+
dir
|
|
100
98
|
)
|
|
101
99
|
|
|
102
100
|
const status = await git(['diff', '--cached', '--name-status'], tmp)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oneclickpush",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "One-click GitHub Pages deployer",
|
|
5
5
|
"author": "Jason Lee <jason@zerodevx.com>",
|
|
6
6
|
"scripts": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"keywords": [
|
|
34
34
|
"one-click",
|
|
35
35
|
"gh-pages",
|
|
36
|
-
"deploy"
|
|
36
|
+
"deploy",
|
|
37
|
+
"cli"
|
|
37
38
|
]
|
|
38
39
|
}
|