Skip to content

Commit c26efb4

Browse files
committed
refactor: refactor release
1 parent d616e62 commit c26efb4

3 files changed

Lines changed: 76 additions & 15 deletions

File tree

lib/package/release.js

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default class Publish {
2222
#previousRelease;
2323
#currentRelease;
2424
#isMajorRelease;
25+
#originalBranch;
2526
#currentBranch;
2627
#previousBranch;
2728
#changelog;
@@ -63,29 +64,45 @@ export default class Publish {
6364
// package is not releasable
6465
if ( !this.#pkg.isReleaseEnabled ) return result( [ 500, "Package release is disabled" ] );
6566

66-
// get changelog
67-
res = await this.getChangelog();
68-
if ( !res.ok ) return res;
69-
7067
// get git status
7168
res = await this.#pkg.git.getStatus();
7269
if ( !res.ok ) return res;
7370
const status = res.data;
7471

72+
// check for uncommited changes
73+
if ( status.isDirty ) return result( [ 500, "working copy or sub-repositories has uncommited changes or untracked files" ] );
74+
75+
// get changelog
76+
res = await this.getChangelog();
77+
if ( !res.ok ) return res;
78+
7579
this.#previousBranch = `v${ this.#previousRelease?.majorNumber || "0" }.x`;
7680

77-
// check branch
81+
// detached head
7882
if ( !status.head.isBranchHead ) {
7983
return result( [ 500, "Release on tbe detached head is not possible" ] );
8084
}
81-
else {
82-
if ( status.head.branch !== this.#previousBranch ) {
83-
return result( [ 500, `You should be on the release branch "${ this.#previousBranch }" to make this release` ] );
85+
86+
// not a release branch head
87+
else if ( status.head.branch !== this.#previousBranch ) {
88+
this.#originalBranch = status.head.branch;
89+
90+
// check allowed branch
91+
if ( this.#pkg.cliConfig?.release.allowedBranches && !this.#pkg.cliConfig.release.allowedBranches.includes( this.#originalBranch ) ) {
92+
return result( [ 500, "Unable to create release from the current branch" ] );
8493
}
85-
}
8694

87-
// check for uncommited changes
88-
if ( status.isDirty ) return result( [ 500, "working copy or sub-repositories has uncommited changes or untracked files" ] );
95+
// previous release commit must be a branch head for the previous branch
96+
if ( this.#previousRelease ) {
97+
res = await this.#pkg.git.getCommit( { "commitRef": this.#previousRelease.versionString } );
98+
if ( !res.ok ) return res;
99+
const previousReleaseCommit = res.data;
100+
101+
if ( !previousReleaseCommit.branches.has( this.#previousBranch ) ) {
102+
return result( [ 500, `Release "${ this.#previousRelease.versionString }" must be a release branch "${ this.#previousBranch }" head` ] );
103+
}
104+
}
105+
}
89106

90107
// create new version
91108
res = this.#changelog.getNextVersion( this.#stable
@@ -206,7 +223,26 @@ export default class Publish {
206223
}
207224
}
208225

209-
// major release
226+
// prepare release branch
227+
if ( this.#originalBranch ) {
228+
229+
// merge the previous release branch with the original branch
230+
if ( this.#previousRelease ) {
231+
res = await this.#pkg.git.exec( [ "switch", this.#previousBranch ] );
232+
if ( !res.ok ) return res;
233+
234+
res = await this.#pkg.git.exec( [ "merge", "--no-edit", "--quiet", "--ff-only", this.#originalBranch ] );
235+
if ( !res.ok ) return res;
236+
}
237+
238+
// create release branch
239+
else {
240+
res = await this.#pkg.git.exec( [ "switch", "--create", this.#previousBranch ] );
241+
if ( !res.ok ) return res;
242+
}
243+
}
244+
245+
// prepare major release
210246
if ( this.#isMajorRelease ) {
211247

212248
// create and switch major release branch
@@ -292,11 +328,11 @@ export default class Publish {
292328
// push, if has upstream
293329
if ( this.#pkg.git.upstream ) {
294330

295-
// track current branch
331+
// track current release branch
296332
if ( this.#isMajorRelease ) {
297333
res = await repeatAction(
298334
async () => {
299-
process.stdout.write( `Setting upstream for branch "${ this.#currentBranch }" ... ` );
335+
process.stdout.write( `Setting upstream for the branch "${ this.#currentBranch }" ... ` );
300336

301337
const params = [
302338

@@ -415,6 +451,26 @@ export default class Publish {
415451
}
416452
}
417453

454+
// restore original branch state
455+
if ( this.#originalBranch ) {
456+
res = await this.#pkg.git.exec( [ "switch", this.#originalBranch ] );
457+
if ( !res.ok ) return res;
458+
459+
res = await this.#pkg.git.exec( [ "merge", "--no-edit", "--quiet", "--ff-only", this.#currentBranch ] );
460+
if ( !res.ok ) return res;
461+
462+
if ( this.#pkg.git.upstream ) {
463+
res = await this.#pkg.git.exec( [ "config", "--get", `branch.${ this.#originalBranch }.remote` ] );
464+
if ( !res.ok ) return res;
465+
466+
// push, if original branch is tracked
467+
if ( res.data ) {
468+
res = await this.#pkg.git.exec( [ "push" ] );
469+
if ( !res.ok ) return res;
470+
}
471+
}
472+
}
473+
418474
return result( 200 );
419475
}
420476

resources/cli.config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ meta:
5353
release:
5454
enabled: false
5555
allowMajorTag: false
56+
allowedBranches: [main]
5657

5758
docker:
5859
composeFile: compose.yaml

resources/schemas/cli.config.schema.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,12 @@ properties:
110110
properties:
111111
enabled: { type: boolean }
112112
allowMajorTag: { type: boolean }
113+
allowedBranches:
114+
anyOf:
115+
- type: "null"
116+
- { type: array, items: { type: string }, minItems: 1, uniqueItems: true }
113117
additionalProperties: false
114-
required: [enabled, allowMajorTag]
118+
required: [enabled, allowMajorTag, allowedBranches]
115119

116120
docker:
117121
type: object

0 commit comments

Comments
 (0)