@logickernel/agileflow 0.16.0 → 0.16.1
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 +1 -1
- package/src/utils.js +65 -22
package/package.json
CHANGED
package/src/utils.js
CHANGED
|
@@ -98,7 +98,9 @@ function fetchTags() {
|
|
|
98
98
|
try {
|
|
99
99
|
const remotes = runWithOutput('git remote').trim();
|
|
100
100
|
if (!remotes) return false;
|
|
101
|
-
|
|
101
|
+
// --force allows updating local tags that conflict with remote tags.
|
|
102
|
+
// Avoid --prune-tags which can fail in shallow CI clones.
|
|
103
|
+
runWithOutput('git fetch --tags --force');
|
|
102
104
|
return true;
|
|
103
105
|
} catch {
|
|
104
106
|
return false;
|
|
@@ -112,16 +114,35 @@ function fetchTags() {
|
|
|
112
114
|
*/
|
|
113
115
|
function buildTagMap() {
|
|
114
116
|
try {
|
|
115
|
-
|
|
117
|
+
// %(objecttype) distinguishes lightweight (commit) from annotated (tag) refs.
|
|
118
|
+
// %(*objectname) is the peeled commit SHA for annotated tags, but may be empty
|
|
119
|
+
// in shallow clones where git has not computed the peeled ref.
|
|
120
|
+
const output = runWithOutput('git tag --format=%(refname:short)|%(objecttype)|%(*objectname)|%(objectname)').trim();
|
|
116
121
|
if (!output) return new Map();
|
|
117
122
|
const map = new Map();
|
|
118
123
|
for (const line of output.split('\n')) {
|
|
119
|
-
const [name, deref, obj] = line.split('|');
|
|
120
|
-
// Annotated tags dereference to the commit via %(*objectname);
|
|
121
|
-
// lightweight tags point directly via %(objectname).
|
|
122
|
-
const sha = (deref || obj || '').trim();
|
|
124
|
+
const [name, type, deref, obj] = line.split('|');
|
|
123
125
|
const tagName = (name || '').trim();
|
|
124
|
-
if (!
|
|
126
|
+
if (!tagName) continue;
|
|
127
|
+
|
|
128
|
+
let sha;
|
|
129
|
+
if (type === 'commit') {
|
|
130
|
+
// Lightweight tag: %(objectname) is the commit SHA directly.
|
|
131
|
+
sha = (obj || '').trim();
|
|
132
|
+
} else {
|
|
133
|
+
// Annotated tag: use peeled commit SHA if available.
|
|
134
|
+
sha = (deref || '').trim();
|
|
135
|
+
if (!sha) {
|
|
136
|
+
// Peeling unavailable (shallow clone) — dereference via rev-parse.
|
|
137
|
+
try {
|
|
138
|
+
sha = runWithOutput(`git rev-parse "${tagName}^{}"`).trim();
|
|
139
|
+
} catch {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!sha) continue;
|
|
125
146
|
if (!map.has(sha)) map.set(sha, []);
|
|
126
147
|
map.get(sha).push(tagName);
|
|
127
148
|
}
|
|
@@ -158,28 +179,50 @@ function expandCommitInfo(commits) {
|
|
|
158
179
|
if (!commits?.length) {
|
|
159
180
|
return { latestVersion: null, commits: [] };
|
|
160
181
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
.sort((a, b) => {
|
|
182
|
+
|
|
183
|
+
// Find the commit tagged with the highest semver version in the history.
|
|
184
|
+
// Using highest-version (not first-found) handles the case where a lower version
|
|
185
|
+
// was accidentally tagged on a recent commit (e.g. a failed CI run).
|
|
186
|
+
let bestIndex = -1;
|
|
187
|
+
let bestVersion = null;
|
|
188
|
+
|
|
189
|
+
for (let i = 0; i < commits.length; i++) {
|
|
190
|
+
const semverTags = commits[i].tags?.filter(tag => SEMVER_PATTERN.test(tag));
|
|
191
|
+
if (!semverTags?.length) continue;
|
|
192
|
+
|
|
193
|
+
const highest = semverTags.sort((a, b) => {
|
|
173
194
|
const pa = parseVersion(a);
|
|
174
195
|
const pb = parseVersion(b);
|
|
175
196
|
if (pb.major !== pa.major) return pb.major - pa.major;
|
|
176
197
|
if (pb.minor !== pa.minor) return pb.minor - pa.minor;
|
|
177
198
|
return pb.patch - pa.patch;
|
|
178
199
|
})[0];
|
|
179
|
-
|
|
200
|
+
|
|
201
|
+
if (!bestVersion) {
|
|
202
|
+
bestVersion = highest;
|
|
203
|
+
bestIndex = i;
|
|
204
|
+
} else {
|
|
205
|
+
const pBest = parseVersion(bestVersion);
|
|
206
|
+
const pCand = parseVersion(highest);
|
|
207
|
+
const isHigher =
|
|
208
|
+
pCand.major > pBest.major ||
|
|
209
|
+
(pCand.major === pBest.major && pCand.minor > pBest.minor) ||
|
|
210
|
+
(pCand.major === pBest.major && pCand.minor === pBest.minor && pCand.patch > pBest.patch);
|
|
211
|
+
if (isHigher) {
|
|
212
|
+
bestVersion = highest;
|
|
213
|
+
bestIndex = i;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (bestIndex === -1) {
|
|
219
|
+
return { latestVersion: null, commits };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Return only commits newer than the highest-version tag
|
|
180
223
|
return {
|
|
181
|
-
latestVersion,
|
|
182
|
-
commits: commits.slice(0,
|
|
224
|
+
latestVersion: bestVersion,
|
|
225
|
+
commits: commits.slice(0, bestIndex),
|
|
183
226
|
};
|
|
184
227
|
}
|
|
185
228
|
|