-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathcore.ts
More file actions
184 lines (161 loc) · 4.79 KB
/
core.ts
File metadata and controls
184 lines (161 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import {
createCommitOnBranchQuery,
createRefMutation,
getRepositoryMetadata,
updateRefMutation,
} from "./github/graphql/queries.js";
import type {
CreateCommitOnBranchMutationVariables,
GetRepositoryMetadataQuery,
} from "./github/graphql/generated/operations.js";
import {
CommitFilesFromBase64Args,
CommitFilesResult,
GitBase,
} from "./interface.js";
import { CommitMessage } from "./github/graphql/generated/types.js";
const getBaseRef = (base: GitBase): string => {
if ("branch" in base) {
return `refs/heads/${base.branch}`;
} else if ("tag" in base) {
return `refs/tags/${base.tag}`;
} else {
return "HEAD";
}
};
const getOidFromRef = (
base: GitBase,
ref: (GetRepositoryMetadataQuery["repository"] &
Record<never, never>)["baseRef"],
) => {
if ("commit" in base) {
return base.commit;
}
if (!ref?.target) {
throw new Error(`Could not determine oid from ref: ${JSON.stringify(ref)}`);
}
if ("target" in ref.target) {
return ref.target.target.oid;
}
return ref.target.oid;
};
export const commitFilesFromBase64 = async ({
octokit,
owner,
repo,
branch,
base,
force = false,
message,
fileChanges,
log,
}: CommitFilesFromBase64Args): Promise<CommitFilesResult> => {
const repositoryNameWithOwner = `${owner}/${repo}`;
const baseRef = getBaseRef(base);
const targetRef = `refs/heads/${branch}`;
log?.debug(`Getting repo info ${repositoryNameWithOwner}`);
const info = await getRepositoryMetadata(octokit, {
owner,
repo,
baseRef,
targetRef,
});
log?.debug(`Repo info: ${JSON.stringify(info, null, 2)}`);
if (!info) {
throw new Error(`Repository ${repositoryNameWithOwner} not found`);
}
const repositoryId = info.id;
/**
* The commit oid to base the new commit on.
*
* Used both to create / update the new branch (if necessary),
* and to ensure no changes have been made as we push the new commit.
*/
const baseOid = getOidFromRef(base, info.baseRef);
let refId: string;
if ("branch" in base && base.branch === branch) {
log?.debug(`Committing to the same branch as base: ${branch} (${baseOid})`);
// Get existing branch refId
if (!info.baseRef) {
throw new Error(`Ref ${baseRef} not found`);
}
refId = info.baseRef.id;
} else {
// Determine if the branch needs to be created or not
if (info.targetBranch?.target?.oid) {
// Branch already exists, check if it matches the base
if (info.targetBranch.target.oid !== baseOid) {
if (force) {
log?.debug(
`Branch ${branch} exists but does not match base ${baseOid}, forcing update to base`,
);
const refIdUpdate = await updateRefMutation(octokit, {
input: {
refId: info.targetBranch.id,
oid: baseOid,
force: true,
},
});
log?.debug(
`Updated branch with refId ${JSON.stringify(refIdUpdate, null, 2)}`,
);
const refIdStr = refIdUpdate.updateRef?.ref?.id;
if (!refIdStr) {
throw new Error(`Failed to create branch ${branch}`);
}
refId = refIdStr;
} else {
throw new Error(
`Branch ${branch} exists already and does not match base ${baseOid}, force is set to false`,
);
}
} else {
log?.debug(
`Branch ${branch} already exists and matches base ${baseOid}`,
);
refId = info.targetBranch.id;
}
} else {
// Create branch as it does not exist yet
log?.debug(`Creating branch ${branch} from commit ${baseOid}}`);
const refIdCreation = await createRefMutation(octokit, {
input: {
repositoryId,
name: `refs/heads/${branch}`,
oid: baseOid,
},
});
log?.debug(
`Created branch with refId ${JSON.stringify(refIdCreation, null, 2)}`,
);
const refIdStr = refIdCreation.createRef?.ref?.id;
if (!refIdStr) {
throw new Error(`Failed to create branch ${branch}`);
}
refId = refIdStr;
}
}
const finalMessage: CommitMessage =
typeof message === "string"
? {
headline: message.split("\n")[0]?.trim() ?? "",
body: message.split("\n").slice(1).join("\n").trim(),
}
: message;
await log?.debug(`Creating commit on branch ${branch}`);
const createCommitMutation: CreateCommitOnBranchMutationVariables = {
input: {
branch: {
id: refId,
},
expectedHeadOid: baseOid,
message: finalMessage,
fileChanges,
},
};
log?.debug(JSON.stringify(createCommitMutation, null, 2));
const result = await createCommitOnBranchQuery(octokit, createCommitMutation);
return {
refId: result.createCommitOnBranch?.ref?.id ?? null,
};
};