7
7
createRefMutation ,
8
8
getRepositoryMetadata ,
9
9
GitHubClient ,
10
+ updateRefMutation ,
10
11
} from "./github/graphql/queries.js" ;
11
12
import type {
12
13
CreateCommitOnBranchMutationVariables ,
@@ -38,6 +39,11 @@ export type CommitFilesFromBase64Args = {
38
39
* The current branch, tag or commit that the new branch should be based on.
39
40
*/
40
41
base : GitBase ;
42
+ /**
43
+ * Push the commit even if the branch exists and does not match what was
44
+ * specified as the base.
45
+ */
46
+ force ?: boolean ;
41
47
/**
42
48
* The commit message
43
49
*/
@@ -58,7 +64,8 @@ const getBaseRef = (base: GitBase): string => {
58
64
59
65
const getOidFromRef = (
60
66
base : GitBase ,
61
- ref : ( GetRepositoryMetadataQuery [ "repository" ] & Record < never , never > ) [ "ref" ] ,
67
+ ref : ( GetRepositoryMetadataQuery [ "repository" ] &
68
+ Record < never , never > ) [ "baseRef" ] ,
62
69
) => {
63
70
if ( "commit" in base ) {
64
71
return base . commit ;
@@ -81,26 +88,29 @@ export const commitFilesFromBase64 = async ({
81
88
repository,
82
89
branch,
83
90
base,
91
+ force = false ,
84
92
message,
85
93
fileChanges,
86
94
log,
87
95
} : CommitFilesFromBase64Args ) : Promise < CommitFilesResult > => {
88
96
const repositoryNameWithOwner = `${ owner } /${ repository } ` ;
89
97
const baseRef = getBaseRef ( base ) ;
98
+ const targetRef = `refs/heads/${ branch } ` ;
90
99
91
100
log ?. debug ( `Getting repo info ${ repositoryNameWithOwner } ` ) ;
92
101
const info = await getRepositoryMetadata ( octokit , {
93
102
owner,
94
103
name : repository ,
95
- ref : baseRef ,
104
+ baseRef,
105
+ targetRef,
96
106
} ) ;
97
107
log ?. debug ( `Repo info: ${ JSON . stringify ( info , null , 2 ) } ` ) ;
98
108
99
109
if ( ! info ) {
100
110
throw new Error ( `Repository ${ repositoryNameWithOwner } not found` ) ;
101
111
}
102
112
103
- if ( ! info . ref ) {
113
+ if ( ! info . baseRef ) {
104
114
throw new Error ( `Ref ${ baseRef } not found` ) ;
105
115
}
106
116
@@ -109,39 +119,77 @@ export const commitFilesFromBase64 = async ({
109
119
* The commit oid to base the new commit on.
110
120
*
111
121
* Used both to create / update the new branch (if necessary),
112
- * and th ensure no changes have been made as we push the new commit.
122
+ * and to ensure no changes have been made as we push the new commit.
113
123
*/
114
- const baseOid = getOidFromRef ( base , info . ref ) ;
124
+ const baseOid = getOidFromRef ( base , info . baseRef ) ;
115
125
116
126
let refId : string ;
117
127
118
128
if ( "branch" in base && base . branch === branch ) {
119
129
log ?. debug ( `Committing to the same branch as base: ${ branch } (${ baseOid } )` ) ;
120
130
// Get existing branch refId
121
- refId = info . ref . id ;
131
+ refId = info . baseRef . id ;
122
132
} else {
123
- // Create branch as not committing to same branch
124
- // TODO: detect if branch already exists, and overwrite if so
125
- log ?. debug ( `Creating branch ${ branch } from commit ${ baseOid } }` ) ;
126
- const refIdCreation = await createRefMutation ( octokit , {
127
- input : {
128
- repositoryId,
129
- name : `refs/heads/${ branch } ` ,
130
- oid : baseOid ,
131
- } ,
132
- } ) ;
133
-
134
- log ?. debug (
135
- `Created branch with refId ${ JSON . stringify ( refIdCreation , null , 2 ) } ` ,
136
- ) ;
137
-
138
- const refIdStr = refIdCreation . createRef ?. ref ?. id ;
139
-
140
- if ( ! refIdStr ) {
141
- throw new Error ( `Failed to create branch ${ branch } ` ) ;
133
+ // Determine if the branch needs to be created or not
134
+ if ( info . targetBranch ?. target ?. oid ) {
135
+ // Branch already exists, check if it matches the base
136
+ if ( info . targetBranch . target . oid !== baseOid ) {
137
+ if ( force ) {
138
+ log ?. debug (
139
+ `Branch ${ branch } exists but does not match base ${ baseOid } , forcing update to base` ,
140
+ ) ;
141
+ const refIdUpdate = await updateRefMutation ( octokit , {
142
+ input : {
143
+ refId : info . targetBranch . id ,
144
+ oid : baseOid ,
145
+ } ,
146
+ } ) ;
147
+
148
+ log ?. debug (
149
+ `Updated branch with refId ${ JSON . stringify ( refIdUpdate , null , 2 ) } ` ,
150
+ ) ;
151
+
152
+ const refIdStr = refIdUpdate . updateRef ?. ref ?. id ;
153
+
154
+ if ( ! refIdStr ) {
155
+ throw new Error ( `Failed to create branch ${ branch } ` ) ;
156
+ }
157
+
158
+ refId = refIdStr ;
159
+ } else {
160
+ throw new Error (
161
+ `Branch ${ branch } exists already and does not match base ${ baseOid } , force is set to false` ,
162
+ ) ;
163
+ }
164
+ } else {
165
+ log ?. debug (
166
+ `Branch ${ branch } already exists and matches base ${ baseOid } ` ,
167
+ ) ;
168
+ refId = info . targetBranch . id ;
169
+ }
170
+ } else {
171
+ // Create branch as it does not exist yet
172
+ log ?. debug ( `Creating branch ${ branch } from commit ${ baseOid } }` ) ;
173
+ const refIdCreation = await createRefMutation ( octokit , {
174
+ input : {
175
+ repositoryId,
176
+ name : `refs/heads/${ branch } ` ,
177
+ oid : baseOid ,
178
+ } ,
179
+ } ) ;
180
+
181
+ log ?. debug (
182
+ `Created branch with refId ${ JSON . stringify ( refIdCreation , null , 2 ) } ` ,
183
+ ) ;
184
+
185
+ const refIdStr = refIdCreation . createRef ?. ref ?. id ;
186
+
187
+ if ( ! refIdStr ) {
188
+ throw new Error ( `Failed to create branch ${ branch } ` ) ;
189
+ }
190
+
191
+ refId = refIdStr ;
142
192
}
143
-
144
- refId = refIdStr ;
145
193
}
146
194
147
195
await log ?. debug ( `Creating commit on branch ${ branch } ` ) ;
0 commit comments