@yukiakai/actions-git 1.0.7 → 2.0.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 +123 -109
- package/dist/public.d.ts +32 -22
- package/dist/public.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,36 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
> Lightweight Git client for GitHub Actions and CI workflows.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@yukiakai/actions-git` prepares a Git repository for automated workflows.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Artifact publishing
|
|
9
|
-
- Docs deployment
|
|
10
|
-
- CI synchronization
|
|
11
|
-
- Temporary repository workflows
|
|
12
|
-
|
|
13
|
-
Designed to be:
|
|
14
|
-
- Minimal
|
|
15
|
-
- Predictable
|
|
16
|
-
- CI-friendly
|
|
17
|
-
- Easy to test
|
|
7
|
+
The library handles repository setup for you—including cloning, branch initialization, and Git identity configuration—then returns a repository that is ready to commit and push.
|
|
18
8
|
|
|
19
9
|
---
|
|
20
10
|
|
|
21
|
-
|
|
11
|
+
# Features
|
|
22
12
|
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
13
|
+
* Ready-to-use Git repository
|
|
14
|
+
* Automatic remote branch detection
|
|
15
|
+
* Shallow clone with automatic fallback
|
|
16
|
+
* Automatic orphan branch initialization
|
|
17
|
+
* Configurable Git identity
|
|
18
|
+
* Simple staging, commit and push workflow
|
|
19
|
+
* Promise-based API
|
|
20
|
+
* Fully typed
|
|
21
|
+
* Designed for GitHub Actions and CI
|
|
31
22
|
|
|
32
23
|
---
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
# Installation
|
|
35
26
|
|
|
36
27
|
```bash
|
|
37
28
|
npm install @yukiakai/actions-git
|
|
@@ -39,135 +30,147 @@ npm install @yukiakai/actions-git
|
|
|
39
30
|
|
|
40
31
|
---
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
# Quick Start
|
|
43
34
|
|
|
44
35
|
```ts
|
|
45
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
prepareGitRepository,
|
|
38
|
+
GITHUB_ACTIONS_IDENTITY,
|
|
39
|
+
} from '@yukiakai/actions-git';
|
|
46
40
|
|
|
47
|
-
const
|
|
48
|
-
|
|
41
|
+
const repository = await prepareGitRepository({
|
|
42
|
+
repository: 'owner/repository',
|
|
49
43
|
token: process.env.GITHUB_TOKEN!,
|
|
50
44
|
branch: 'gh-pages',
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
await git.clone();
|
|
55
|
-
|
|
56
|
-
await git.setup();
|
|
45
|
+
workingDirectory: '.deploy',
|
|
57
46
|
|
|
58
|
-
|
|
47
|
+
identity: GITHUB_ACTIONS_IDENTITY,
|
|
48
|
+
});
|
|
59
49
|
|
|
60
|
-
await
|
|
50
|
+
await repository.wipe(['.']);
|
|
61
51
|
|
|
62
|
-
await
|
|
52
|
+
await repository.add(['dist']);
|
|
63
53
|
|
|
64
|
-
|
|
65
|
-
await git.commit('deploy: update docs');
|
|
54
|
+
await repository.commit('deploy: update documentation');
|
|
66
55
|
|
|
67
|
-
|
|
56
|
+
if (await repository.hasStagedChanges()) {
|
|
57
|
+
|
|
58
|
+
await repository.push();
|
|
68
59
|
}
|
|
69
60
|
```
|
|
70
61
|
|
|
71
62
|
---
|
|
72
63
|
|
|
73
|
-
|
|
64
|
+
# API
|
|
74
65
|
|
|
75
|
-
|
|
66
|
+
## `prepareGitRepository(options)`
|
|
76
67
|
|
|
77
|
-
|
|
68
|
+
Prepare a repository for automated Git workflows.
|
|
78
69
|
|
|
79
70
|
```ts
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
interface PrepareGitRepositoryOptions {
|
|
72
|
+
repository: string;
|
|
82
73
|
token: string;
|
|
83
74
|
branch: string;
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
# Methods
|
|
75
|
+
workingDirectory: string;
|
|
91
76
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
identity: GitIdentity;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
95
80
|
|
|
96
|
-
|
|
81
|
+
Returns:
|
|
97
82
|
|
|
98
|
-
```
|
|
99
|
-
|
|
83
|
+
```ts
|
|
84
|
+
Promise<PreparedGitRepository>
|
|
100
85
|
```
|
|
101
86
|
|
|
102
|
-
|
|
87
|
+
The returned repository only exposes workflow operations. Repository initialization APIs are intentionally kept internal.
|
|
103
88
|
|
|
104
89
|
---
|
|
105
90
|
|
|
106
|
-
|
|
91
|
+
# Built-in Identities
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
The library provides reusable identities for common CI environments.
|
|
109
94
|
|
|
110
|
-
|
|
95
|
+
## `GITHUB_ACTIONS_IDENTITY`
|
|
111
96
|
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
|
|
97
|
+
```ts
|
|
98
|
+
import {
|
|
99
|
+
GITHUB_ACTIONS_IDENTITY,
|
|
100
|
+
} from '@yukiakai/actions-git';
|
|
115
101
|
```
|
|
116
102
|
|
|
117
|
-
|
|
103
|
+
Equivalent to:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
{
|
|
107
|
+
name: 'github-actions[bot]',
|
|
108
|
+
email: 'github-actions[bot]@users.noreply.github.com',
|
|
109
|
+
}
|
|
110
|
+
```
|
|
118
111
|
|
|
119
|
-
|
|
112
|
+
You can also provide your own identity.
|
|
120
113
|
|
|
121
|
-
|
|
114
|
+
```ts
|
|
115
|
+
identity: {
|
|
116
|
+
name: 'Yuki Akai',
|
|
117
|
+
email: 'yuki@example.com',
|
|
118
|
+
}
|
|
119
|
+
```
|
|
122
120
|
|
|
123
|
-
|
|
121
|
+
---
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
- `git checkout <branch>`
|
|
123
|
+
# PreparedGitRepository
|
|
127
124
|
|
|
128
|
-
|
|
129
|
-
- creates orphan branch
|
|
130
|
-
- wipes working tree
|
|
125
|
+
Represents a repository that has already been prepared for write operations.
|
|
131
126
|
|
|
132
127
|
---
|
|
133
128
|
|
|
134
129
|
## `wipe(patterns)`
|
|
135
130
|
|
|
136
|
-
Remove tracked and untracked files
|
|
131
|
+
Remove tracked and untracked files.
|
|
137
132
|
|
|
138
133
|
```ts
|
|
139
|
-
await
|
|
134
|
+
await repository.wipe(['.']);
|
|
140
135
|
```
|
|
141
136
|
|
|
142
|
-
Internally
|
|
137
|
+
Internally executes:
|
|
143
138
|
|
|
144
139
|
```bash
|
|
145
140
|
git rm -r -f --ignore-unmatch
|
|
146
141
|
git clean -fdx
|
|
147
142
|
```
|
|
148
143
|
|
|
149
|
-
Useful for deployment workflows where the workspace must be fully reset.
|
|
150
|
-
|
|
151
144
|
---
|
|
152
145
|
|
|
153
|
-
## `
|
|
146
|
+
## `add(patterns)`
|
|
154
147
|
|
|
155
|
-
|
|
148
|
+
Stage files.
|
|
156
149
|
|
|
157
|
-
```
|
|
158
|
-
|
|
150
|
+
```ts
|
|
151
|
+
await repository.add([
|
|
152
|
+
'dist',
|
|
153
|
+
'package.json',
|
|
154
|
+
]);
|
|
159
155
|
```
|
|
160
156
|
|
|
161
157
|
---
|
|
162
158
|
|
|
163
|
-
## `
|
|
159
|
+
## `hasStagedChanges()`
|
|
164
160
|
|
|
165
|
-
|
|
161
|
+
Check whether staged changes exist.
|
|
166
162
|
|
|
167
|
-
|
|
168
|
-
|
|
163
|
+
Internally executes:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
git diff --cached --quiet
|
|
169
167
|
```
|
|
170
168
|
|
|
169
|
+
Returns:
|
|
170
|
+
|
|
171
|
+
* `true` if staged changes exist.
|
|
172
|
+
* `false` otherwise.
|
|
173
|
+
|
|
171
174
|
---
|
|
172
175
|
|
|
173
176
|
## `commit(message)`
|
|
@@ -175,52 +178,63 @@ await git.add(['dist', 'package.json']);
|
|
|
175
178
|
Create a commit.
|
|
176
179
|
|
|
177
180
|
```ts
|
|
178
|
-
await
|
|
181
|
+
await repository.commit(
|
|
182
|
+
'deploy: update documentation',
|
|
183
|
+
);
|
|
179
184
|
```
|
|
180
185
|
|
|
181
186
|
---
|
|
182
187
|
|
|
183
188
|
## `push()`
|
|
184
189
|
|
|
185
|
-
Push the current branch
|
|
190
|
+
Push the current checked-out branch.
|
|
186
191
|
|
|
187
192
|
```ts
|
|
188
|
-
await
|
|
193
|
+
await repository.push();
|
|
189
194
|
```
|
|
190
195
|
|
|
191
|
-
|
|
196
|
+
The current `HEAD` is pushed to `origin`.
|
|
192
197
|
|
|
193
|
-
|
|
198
|
+
---
|
|
194
199
|
|
|
195
|
-
|
|
200
|
+
# Typical Workflow
|
|
196
201
|
|
|
197
202
|
```ts
|
|
198
|
-
const
|
|
199
|
-
|
|
203
|
+
const repository = await prepareGitRepository({
|
|
204
|
+
repository: 'owner/repository',
|
|
205
|
+
token: process.env.GITHUB_TOKEN!,
|
|
206
|
+
branch: 'gh-pages',
|
|
207
|
+
workingDirectory: '.deploy',
|
|
200
208
|
|
|
201
|
-
|
|
209
|
+
identity: GITHUB_ACTIONS_IDENTITY,
|
|
210
|
+
});
|
|
202
211
|
|
|
203
|
-
|
|
204
|
-
git diff --cached --quiet
|
|
205
|
-
```
|
|
212
|
+
await repository.wipe(['.']);
|
|
206
213
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
214
|
+
await repository.add(['dist']);
|
|
215
|
+
|
|
216
|
+
await repository.commit('deploy');
|
|
217
|
+
if (!await repository.hasStagedChanges()) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
await repository.push();
|
|
222
|
+
```
|
|
210
223
|
|
|
211
224
|
---
|
|
212
225
|
|
|
213
|
-
|
|
226
|
+
# Designed For
|
|
214
227
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
228
|
+
* GitHub Actions
|
|
229
|
+
* Documentation deployment
|
|
230
|
+
* Static site deployment
|
|
231
|
+
* Repository synchronization
|
|
232
|
+
* Artifact publishing
|
|
233
|
+
* Deployment pipelines
|
|
234
|
+
* CI automation
|
|
221
235
|
|
|
222
236
|
---
|
|
223
237
|
|
|
224
|
-
|
|
238
|
+
# License
|
|
225
239
|
|
|
226
|
-
MIT Yuki Akai
|
|
240
|
+
MIT © Yuki Akai
|
package/dist/public.d.ts
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
type AbsoluteDirectoryPath = string;
|
|
2
2
|
|
|
3
|
-
interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
interface GitOptions {
|
|
7
|
-
cwd: string;
|
|
8
|
-
repo: string;
|
|
9
|
-
branch: string;
|
|
10
|
-
token: string;
|
|
3
|
+
interface GitIdentity {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly email: string;
|
|
11
6
|
}
|
|
12
7
|
|
|
13
|
-
|
|
8
|
+
interface GitRepositoryOptions {
|
|
9
|
+
workingDirectory: AbsoluteDirectoryPath;
|
|
10
|
+
}
|
|
11
|
+
declare class GitRepository {
|
|
14
12
|
private options;
|
|
15
|
-
constructor(options:
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
private execGit;
|
|
19
|
-
private execGitInspectable;
|
|
20
|
-
clone(): Promise<void>;
|
|
13
|
+
constructor(options: GitRepositoryOptions);
|
|
14
|
+
private execute;
|
|
15
|
+
private execInspectable;
|
|
21
16
|
wipe(pattern: string[]): Promise<void>;
|
|
22
|
-
|
|
23
|
-
checkout(): Promise<void>;
|
|
24
|
-
|
|
17
|
+
setupIdentity(identity: GitIdentity): Promise<void>;
|
|
18
|
+
checkout(branch: string): Promise<void>;
|
|
19
|
+
checkoutOrphan(branch: string): Promise<void>;
|
|
20
|
+
pull(): Promise<void>;
|
|
21
|
+
pullRebase(branch: string): Promise<void>;
|
|
25
22
|
commit(message: string): Promise<void>;
|
|
26
23
|
add(pattern: string[]): Promise<void>;
|
|
27
24
|
push(): Promise<void>;
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
hasStagedChanges(): Promise<boolean>;
|
|
26
|
+
hasLocalBranch(branch: string): Promise<boolean>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type PreparedGitRepository = Omit<GitRepository, 'setupIdentity' | 'checkout' | 'checkoutOrphan' | 'pullRebase' | 'hasLocalBranch'>;
|
|
30
|
+
|
|
31
|
+
interface PrepareGitRepositoryOptions {
|
|
32
|
+
readonly repository: string;
|
|
33
|
+
readonly token: string;
|
|
34
|
+
readonly branch: string;
|
|
35
|
+
readonly directory: AbsoluteDirectoryPath;
|
|
36
|
+
identity: GitIdentity;
|
|
30
37
|
}
|
|
38
|
+
declare function prepareGitRepository(options: PrepareGitRepositoryOptions): Promise<PreparedGitRepository>;
|
|
39
|
+
|
|
40
|
+
declare const GITHUB_ACTIONS_IDENTITY: GitIdentity;
|
|
31
41
|
|
|
32
|
-
export {
|
|
42
|
+
export { type AbsoluteDirectoryPath, GITHUB_ACTIONS_IDENTITY, type GitIdentity, GitRepository, type PrepareGitRepositoryOptions, type PreparedGitRepository, prepareGitRepository };
|
package/dist/public.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{exec as
|
|
1
|
+
import{exec as m}from"@actions/exec";async function a(e){let t=await m("git",[...e.args],{cwd:e.workingDirectory})}async function c(e){return{exitCode:await m("git",[...e.args],{cwd:e.workingDirectory,ignoreReturnCode:!0})}}var s=class{constructor(t){this.options=t}execute(t){return a({workingDirectory:this.options.workingDirectory,args:t})}execInspectable(t){return c({workingDirectory:this.options.workingDirectory,args:t})}async wipe(t){await this.execute(["rm","-r","-f","--ignore-unmatch",...t]),await this.execute(["clean","-fdx","--",...t])}async setupIdentity(t){await this.execute(["config","user.name",t.name]),await this.execute(["config","user.email",t.email])}async checkout(t){await this.execute(["checkout",t])}async checkoutOrphan(t){await this.execute(["checkout","--orphan",t])}async pull(){await this.execute(["pull"])}async pullRebase(t){await this.execute(["pull","--rebase","origin",t])}async commit(t){await this.execute(["commit","-m",t])}async add(t){await this.execute(["add",...t])}async push(){await this.execute(["push","--set-upstream","origin","HEAD"])}async hasStagedChanges(){let t=await this.execInspectable(["diff","--cached","--quiet"]);if(t.exitCode===0)return!1;if(t.exitCode===1)return!0;throw new Error(`git diff failed with exit code ${t.exitCode}`)}async hasLocalBranch(t){let o=await this.execInspectable(["show-ref","--verify","--quiet",`refs/heads/${t}`]);if(o.exitCode===0)return!0;if(o.exitCode===1)return!1;throw new Error(`Failed to resolve local branch "${t}"`)}};var p=class{constructor(t){this.git=t}async initialize(t){if(await this.git.hasLocalBranch(t)){await this.git.checkout(t);return}await this.git.checkoutOrphan(t),await this.git.wipe(["."])}};var y=class{constructor(t){this.options=t}execInspectable(t){return c({workingDirectory:void 0,args:t})}async exists(t){let o=await this.execInspectable(["ls-remote","--exit-code","--heads",this.options.repositoryUrl,t]);switch(o.exitCode){case 0:return!0;case 2:return!1;default:throw new Error([`Failed to check remote branch "${t}"`,`Repository: ${this.options.repositoryUrl}`,`Exit code: ${o.exitCode}`].join(`
|
|
2
|
+
`))}}};import d from"path";var u=class{constructor(t){this.options=t}execute(t){return a({workingDirectory:d.dirname(this.options.destinationDirectory),args:t})}async clone(){await this.execute(["clone",this.options.repositoryUrl,this.options.destinationDirectory])}async cloneAtBranch(t){await this.execute(["clone","--depth=1","--branch",t,this.options.repositoryUrl,this.options.destinationDirectory])}};var l=class{static build(t){let{token:o,repository:n}=t;return`https://x-access-token:${o}@github.com/${n}.git`}};async function x(e){let t=l.build({repository:e.repository,token:e.token}),o=new y({repositoryUrl:t}),n=new u({repositoryUrl:t,destinationDirectory:e.directory});await o.exists(e.branch)?await n.cloneAtBranch(e.branch):await n.clone();let h=new s({workingDirectory:e.directory});return await new p(h).initialize(e.branch),await h.setupIdentity(e.identity),h}var f={name:"github-actions[bot]",email:"github-actions[bot]@users.noreply.github.com"};export{f as GITHUB_ACTIONS_IDENTITY,s as GitRepository,x as prepareGitRepository};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yukiakai/actions-git",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Lightweight Git client for GitHub Actions and CI workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/public.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"import": "./dist/public.js"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"test": "npx vitest run --reporter verbose --coverage",
|
|
13
|
+
"test": "echo npx vitest run --reporter verbose --coverage",
|
|
14
14
|
"format": "prettier --write **/*.{js,ts,json}",
|
|
15
15
|
"format:check": "prettier --check **/*.{js,ts,json}",
|
|
16
16
|
"lint": "eslint src/**/*.ts",
|