@wyxos/zephyr 0.9.2 → 0.9.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wyxos/zephyr",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "A streamlined deployment tool for web applications with intelligent Laravel project detection",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -97,6 +97,41 @@ function formatVersionReferenceLabel(reference, currentVersion) {
97
97
  return `${prefix} ${reference.shortHash} (${reference.version})`
98
98
  }
99
99
 
100
+
101
+ async function readRecentAppCommitSubjects(rootDir, versionReference, {runCommand} = {}) {
102
+ if (!versionReference?.hash || typeof runCommand !== 'function') {
103
+ return ''
104
+ }
105
+
106
+ try {
107
+ const {stdout = ''} = await runCommand('git', [
108
+ 'log',
109
+ '--format=%s',
110
+ '--max-count=80',
111
+ `${versionReference.hash}..HEAD`
112
+ ], {
113
+ capture: true,
114
+ cwd: rootDir
115
+ })
116
+
117
+ return stdout.trim()
118
+ } catch {
119
+ return ''
120
+ }
121
+ }
122
+
123
+ function inferMinimumReleaseTypeFromCommitSubjects(commitSubjects) {
124
+ if (/breaking change|breaking changes|^[a-z]+(?:\(.+\))?!:/im.test(commitSubjects)) {
125
+ return 'major'
126
+ }
127
+
128
+ if (/\bfeat(?:\(.+\))?:/im.test(commitSubjects)) {
129
+ return 'minor'
130
+ }
131
+
132
+ return null
133
+ }
134
+
100
135
  async function resolveDeploymentVersionValue(rootDir, {
101
136
  versionArg = null,
102
137
  pkg,
@@ -112,6 +147,7 @@ async function resolveDeploymentVersionValue(rootDir, {
112
147
 
113
148
  const versionBumps = await readVersionBumpCommits(rootDir, {runCommand})
114
149
  const versionReference = selectVersionSuggestionReference(pkg.version, versionBumps)
150
+ const commitSubjects = await readRecentAppCommitSubjects(rootDir, versionReference, {runCommand})
115
151
 
116
152
  return await resolveReleaseType({
117
153
  currentVersion: pkg.version,
@@ -123,7 +159,8 @@ async function resolveDeploymentVersionValue(rootDir, {
123
159
  logStep: logProcessing,
124
160
  logWarning,
125
161
  latestTag: versionReference?.hash ?? null,
126
- referenceLabel: formatVersionReferenceLabel(versionReference, pkg.version)
162
+ referenceLabel: formatVersionReferenceLabel(versionReference, pkg.version),
163
+ minimumReleaseType: inferMinimumReleaseTypeFromCommitSubjects(commitSubjects)
127
164
  })
128
165
  }
129
166
 
@@ -16,6 +16,15 @@ export const RELEASE_TYPES = [
16
16
  'prerelease'
17
17
  ]
18
18
  const STABLE_RELEASE_TYPES = ['major', 'minor', 'patch']
19
+ const RELEASE_TYPE_WEIGHTS = {
20
+ prerelease: 0,
21
+ prepatch: 1,
22
+ patch: 1,
23
+ preminor: 2,
24
+ minor: 2,
25
+ premajor: 3,
26
+ major: 3
27
+ }
19
28
 
20
29
  function sanitizeSuggestedReleaseType(message, allowedTypes = RELEASE_TYPES) {
21
30
  if (typeof message !== 'string') {
@@ -70,6 +79,17 @@ function inferReleaseTypeHeuristically({
70
79
  return 'patch'
71
80
  }
72
81
 
82
+ function applyReleaseTypeFloor(releaseType, floorReleaseType) {
83
+ const releaseWeight = RELEASE_TYPE_WEIGHTS[releaseType] ?? -1
84
+ const floorWeight = RELEASE_TYPE_WEIGHTS[floorReleaseType] ?? -1
85
+
86
+ if (floorWeight > releaseWeight) {
87
+ return floorReleaseType
88
+ }
89
+
90
+ return releaseType
91
+ }
92
+
73
93
  function resolveSuggestedReleaseTypeOptions(currentVersion = '0.0.0') {
74
94
  const parsedVersion = semver.parse(currentVersion)
75
95
 
@@ -167,7 +187,8 @@ async function suggestReleaseType(rootDir = process.cwd(), {
167
187
  logStep,
168
188
  logWarning,
169
189
  latestTag = null,
170
- referenceLabel = null
190
+ referenceLabel = null,
191
+ minimumReleaseType = null
171
192
  } = {}) {
172
193
  const context = await buildReleaseSuggestionContext(rootDir, {
173
194
  runCommand,
@@ -177,7 +198,10 @@ async function suggestReleaseType(rootDir = process.cwd(), {
177
198
  referenceLabel
178
199
  })
179
200
  const allowedSuggestedReleaseTypes = resolveSuggestedReleaseTypeOptions(currentVersion)
180
- const heuristicReleaseType = inferReleaseTypeHeuristically(context)
201
+ const heuristicReleaseType = applyReleaseTypeFloor(
202
+ inferReleaseTypeHeuristically(context),
203
+ sanitizeSuggestedReleaseType(minimumReleaseType, allowedSuggestedReleaseTypes)
204
+ )
181
205
 
182
206
  if (!commandExistsImpl('codex')) {
183
207
  return {
@@ -234,10 +258,12 @@ async function suggestReleaseType(rootDir = process.cwd(), {
234
258
  }
235
259
  }
236
260
 
261
+ const flooredReleaseType = applyReleaseTypeFloor(releaseType, heuristicReleaseType)
262
+
237
263
  return {
238
264
  ...context,
239
- releaseType,
240
- source: 'codex'
265
+ releaseType: flooredReleaseType,
266
+ source: flooredReleaseType === releaseType ? 'codex' : 'codex+heuristic-floor'
241
267
  }
242
268
  } catch (error) {
243
269
  logWarning?.(`Codex could not suggest a release type: ${error.message}`)
@@ -265,7 +291,8 @@ export async function resolveReleaseType({
265
291
  logStep,
266
292
  logWarning,
267
293
  latestTag = null,
268
- referenceLabel = null
294
+ referenceLabel = null,
295
+ minimumReleaseType = null
269
296
  } = {}) {
270
297
  if (releaseType) {
271
298
  return releaseType
@@ -278,7 +305,8 @@ export async function resolveReleaseType({
278
305
  logStep,
279
306
  logWarning,
280
307
  latestTag,
281
- referenceLabel
308
+ referenceLabel,
309
+ minimumReleaseType
282
310
  })
283
311
  const rangeLabel = suggested.referenceLabel || suggested.latestTag
284
312
  ? `based on changes since ${suggested.referenceLabel || suggested.latestTag}`