@yukiakai/actions-git 1.0.7 → 2.0.2
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,146 @@ 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
|
-
if (await git.hasChanges()) {
|
|
65
|
-
await git.commit('deploy: update docs');
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
if (await repository.hasStagedChanges()) {
|
|
56
|
+
await repository.commit('deploy: update documentation');
|
|
57
|
+
await repository.push();
|
|
68
58
|
}
|
|
69
59
|
```
|
|
70
60
|
|
|
71
61
|
---
|
|
72
62
|
|
|
73
|
-
|
|
63
|
+
# API
|
|
74
64
|
|
|
75
|
-
|
|
65
|
+
## `prepareGitRepository(options)`
|
|
76
66
|
|
|
77
|
-
|
|
67
|
+
Prepare a repository for automated Git workflows.
|
|
78
68
|
|
|
79
69
|
```ts
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
interface PrepareGitRepositoryOptions {
|
|
71
|
+
repository: string;
|
|
82
72
|
token: string;
|
|
83
73
|
branch: string;
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
74
|
+
workingDirectory: string;
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Clone the repository into the target working directory.
|
|
76
|
+
identity: GitIdentity;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
95
79
|
|
|
96
|
-
|
|
80
|
+
Returns:
|
|
97
81
|
|
|
98
|
-
```
|
|
99
|
-
|
|
82
|
+
```ts
|
|
83
|
+
Promise<PreparedGitRepository>
|
|
100
84
|
```
|
|
101
85
|
|
|
102
|
-
|
|
86
|
+
The returned repository only exposes workflow operations. Repository initialization APIs are intentionally kept internal.
|
|
103
87
|
|
|
104
88
|
---
|
|
105
89
|
|
|
106
|
-
|
|
90
|
+
# Built-in Identities
|
|
107
91
|
|
|
108
|
-
|
|
92
|
+
The library provides reusable identities for common CI environments.
|
|
109
93
|
|
|
110
|
-
|
|
94
|
+
## `GITHUB_ACTIONS_IDENTITY`
|
|
111
95
|
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
|
|
96
|
+
```ts
|
|
97
|
+
import {
|
|
98
|
+
GITHUB_ACTIONS_IDENTITY,
|
|
99
|
+
} from '@yukiakai/actions-git';
|
|
115
100
|
```
|
|
116
101
|
|
|
117
|
-
|
|
102
|
+
Equivalent to:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
{
|
|
106
|
+
name: 'github-actions[bot]',
|
|
107
|
+
email: 'github-actions[bot]@users.noreply.github.com',
|
|
108
|
+
}
|
|
109
|
+
```
|
|
118
110
|
|
|
119
|
-
|
|
111
|
+
You can also provide your own identity.
|
|
120
112
|
|
|
121
|
-
|
|
113
|
+
```ts
|
|
114
|
+
identity: {
|
|
115
|
+
name: 'Yuki Akai',
|
|
116
|
+
email: 'yuki@example.com',
|
|
117
|
+
}
|
|
118
|
+
```
|
|
122
119
|
|
|
123
|
-
|
|
120
|
+
---
|
|
124
121
|
|
|
125
|
-
|
|
126
|
-
- `git checkout <branch>`
|
|
122
|
+
# PreparedGitRepository
|
|
127
123
|
|
|
128
|
-
|
|
129
|
-
- creates orphan branch
|
|
130
|
-
- wipes working tree
|
|
124
|
+
Represents a repository that has already been prepared for write operations.
|
|
131
125
|
|
|
132
126
|
---
|
|
133
127
|
|
|
134
128
|
## `wipe(patterns)`
|
|
135
129
|
|
|
136
|
-
Remove tracked and untracked files
|
|
130
|
+
Remove tracked and untracked files.
|
|
137
131
|
|
|
138
132
|
```ts
|
|
139
|
-
await
|
|
133
|
+
await repository.wipe(['.']);
|
|
140
134
|
```
|
|
141
135
|
|
|
142
|
-
Internally
|
|
136
|
+
Internally executes:
|
|
143
137
|
|
|
144
138
|
```bash
|
|
145
139
|
git rm -r -f --ignore-unmatch
|
|
146
140
|
git clean -fdx
|
|
147
141
|
```
|
|
148
142
|
|
|
149
|
-
Useful for deployment workflows where the workspace must be fully reset.
|
|
150
|
-
|
|
151
143
|
---
|
|
152
144
|
|
|
153
|
-
## `
|
|
145
|
+
## `add(patterns)`
|
|
154
146
|
|
|
155
|
-
|
|
147
|
+
Stage files.
|
|
156
148
|
|
|
157
|
-
```
|
|
158
|
-
|
|
149
|
+
```ts
|
|
150
|
+
await repository.add([
|
|
151
|
+
'dist',
|
|
152
|
+
'package.json',
|
|
153
|
+
]);
|
|
159
154
|
```
|
|
160
155
|
|
|
161
156
|
---
|
|
162
157
|
|
|
163
|
-
## `
|
|
158
|
+
## `hasStagedChanges()`
|
|
164
159
|
|
|
165
|
-
|
|
160
|
+
Check whether staged changes exist.
|
|
166
161
|
|
|
167
|
-
|
|
168
|
-
|
|
162
|
+
Internally executes:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
git diff --cached --quiet
|
|
169
166
|
```
|
|
170
167
|
|
|
168
|
+
Returns:
|
|
169
|
+
|
|
170
|
+
* `true` if staged changes exist.
|
|
171
|
+
* `false` otherwise.
|
|
172
|
+
|
|
171
173
|
---
|
|
172
174
|
|
|
173
175
|
## `commit(message)`
|
|
@@ -175,52 +177,64 @@ await git.add(['dist', 'package.json']);
|
|
|
175
177
|
Create a commit.
|
|
176
178
|
|
|
177
179
|
```ts
|
|
178
|
-
await
|
|
180
|
+
await repository.commit(
|
|
181
|
+
'deploy: update documentation',
|
|
182
|
+
);
|
|
179
183
|
```
|
|
180
184
|
|
|
181
185
|
---
|
|
182
186
|
|
|
183
187
|
## `push()`
|
|
184
188
|
|
|
185
|
-
Push the current branch
|
|
189
|
+
Push the current checked-out branch.
|
|
186
190
|
|
|
187
191
|
```ts
|
|
188
|
-
await
|
|
192
|
+
await repository.push();
|
|
189
193
|
```
|
|
190
194
|
|
|
191
|
-
|
|
195
|
+
The current `HEAD` is pushed to `origin`.
|
|
192
196
|
|
|
193
|
-
|
|
197
|
+
---
|
|
194
198
|
|
|
195
|
-
|
|
199
|
+
# Typical Workflow
|
|
196
200
|
|
|
197
201
|
```ts
|
|
198
|
-
const
|
|
199
|
-
|
|
202
|
+
const repository = await prepareGitRepository({
|
|
203
|
+
repository: 'owner/repository',
|
|
204
|
+
token: process.env.GITHUB_TOKEN!,
|
|
205
|
+
branch: 'gh-pages',
|
|
206
|
+
workingDirectory: '.deploy',
|
|
200
207
|
|
|
201
|
-
|
|
208
|
+
identity: GITHUB_ACTIONS_IDENTITY,
|
|
209
|
+
});
|
|
202
210
|
|
|
203
|
-
|
|
204
|
-
git diff --cached --quiet
|
|
205
|
-
```
|
|
211
|
+
await repository.wipe(['.']);
|
|
206
212
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
await repository.add(['dist']);
|
|
214
|
+
|
|
215
|
+
if (!await repository.hasStagedChanges()) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
await repository.commit('deploy');
|
|
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 executeInspectable;
|
|
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";var s=class{static async execute(t){let r=await m("git",[...t.args],{cwd:t.workingDirectory})}static async inspect(t){return{exitCode:await m("git",[...t.args],{cwd:t.workingDirectory,ignoreReturnCode:!0})}}};var n=class{constructor(t){this.options=t}execute(t){return s.execute({workingDirectory:this.options.workingDirectory,args:t})}executeInspectable(t){return s.inspect({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.executeInspectable(["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 r=await this.executeInspectable(["show-ref","--verify","--quiet",`refs/heads/${t}`]);if(r.exitCode===0)return!0;if(r.exitCode===1)return!1;throw new Error(`Failed to resolve local branch "${t}"`)}};var c=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 p=class{constructor(t){this.options=t}execInspectable(t){return s.inspect({workingDirectory:void 0,args:t})}async exists(t){let r=await this.execInspectable(["ls-remote","--exit-code","--heads",this.options.repositoryUrl,t]);switch(r.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: ${r.exitCode}`].join(`
|
|
2
|
+
`))}}};import h from"path";var y=class{constructor(t){this.options=t}execute(t){return s.execute({workingDirectory:h.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 u=class{static build(t){let{token:r,repository:a}=t;return`https://x-access-token:${r}@github.com/${a}.git`}};async function d(e){let t=u.build({repository:e.repository,token:e.token}),r=new p({repositoryUrl:t}),a=new y({repositoryUrl:t,destinationDirectory:e.directory});await r.exists(e.branch)?await a.cloneAtBranch(e.branch):await a.clone();let l=new n({workingDirectory:e.directory});return await new c(l).initialize(e.branch),await l.setupIdentity(e.identity),l}var x={name:"github-actions[bot]",email:"github-actions[bot]@users.noreply.github.com"};export{x as GITHUB_ACTIONS_IDENTITY,n as GitRepository,d as prepareGitRepository};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yukiakai/actions-git",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
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",
|