Merge develop into master for #167
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Liste les issues Gitea ouvertes pour un milestone donné (ex. 0.1.0).
|
||||
* Usage : node scripts/gitea-list-open-issues-by-milestone.js [milestone]
|
||||
* Token : .gitea-token (racine), GITEA_TOKEN, ou docs/27_BRIEFING-FRONTEND.md
|
||||
*/
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const repoRoot = path.join(__dirname, '..');
|
||||
const REPO = 'jmartin/petitspas';
|
||||
const milestoneWanted = (process.argv[2] || '0.1.0').trim();
|
||||
|
||||
let token = process.env.GITEA_TOKEN;
|
||||
if (!token) {
|
||||
try {
|
||||
const tokenFile = path.join(repoRoot, '.gitea-token');
|
||||
if (fs.existsSync(tokenFile)) token = fs.readFileSync(tokenFile, 'utf8').trim();
|
||||
} catch (_) {}
|
||||
}
|
||||
if (!token) {
|
||||
try {
|
||||
const briefing = fs.readFileSync(
|
||||
path.join(repoRoot, 'docs/27_BRIEFING-FRONTEND.md'),
|
||||
'utf8',
|
||||
);
|
||||
const m = briefing.match(/Token:\s*(giteabu_[a-f0-9]+)/);
|
||||
if (m) token = m[1].trim();
|
||||
} catch (_) {}
|
||||
}
|
||||
if (!token) {
|
||||
console.error('Token non trouvé : .gitea-token ou GITEA_TOKEN');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function getJson(apiPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const opts = {
|
||||
hostname: 'git.ptits-pas.fr',
|
||||
path: `/api/v1/repos/${REPO}${apiPath}`,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: 'token ' + token,
|
||||
Accept: 'application/json',
|
||||
},
|
||||
};
|
||||
const req = https.request(opts, (res) => {
|
||||
let d = '';
|
||||
res.on('data', (c) => (d += c));
|
||||
res.on('end', () => {
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`HTTP ${res.statusCode}: ${d.slice(0, 500)}`));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
resolve(JSON.parse(d));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchAllOpenIssues() {
|
||||
const out = [];
|
||||
let page = 1;
|
||||
const limit = 50;
|
||||
for (;;) {
|
||||
const qs = new URLSearchParams({
|
||||
state: 'open',
|
||||
type: 'all',
|
||||
page: String(page),
|
||||
limit: String(limit),
|
||||
});
|
||||
const batch = await getJson(`/issues?${qs}`);
|
||||
if (!Array.isArray(batch) || batch.length === 0) break;
|
||||
out.push(...batch);
|
||||
if (batch.length < limit) break;
|
||||
page += 1;
|
||||
if (page > 40) break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function milestoneMatches(m, wanted) {
|
||||
if (!m) return false;
|
||||
const t = (m.title || '').trim();
|
||||
return t === wanted || t === `v${wanted}`;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
let milestones;
|
||||
try {
|
||||
milestones = await getJson('/milestones?state=all');
|
||||
} catch (e) {
|
||||
milestones = [];
|
||||
console.warn('Milestones non lisibles:', e.message);
|
||||
}
|
||||
|
||||
const known = Array.isArray(milestones)
|
||||
? milestones.map((m) => m.title).filter(Boolean)
|
||||
: [];
|
||||
if (known.length) {
|
||||
console.log('Milestones connus sur le dépôt :', known.join(', '));
|
||||
}
|
||||
|
||||
const issues = await fetchAllOpenIssues();
|
||||
const filtered = issues.filter((i) => milestoneMatches(i.milestone, milestoneWanted));
|
||||
|
||||
console.log('');
|
||||
console.log(`## Issues ouvertes — milestone « ${milestoneWanted} » (${filtered.length})`);
|
||||
console.log('');
|
||||
if (filtered.length === 0) {
|
||||
console.log(
|
||||
'Aucune issue ouverte avec ce milestone. Vérifier sur Gitea que les tickets ' +
|
||||
'0.1.0 portent bien le milestone, ou élargir la requête.',
|
||||
);
|
||||
console.log('');
|
||||
console.log(`(Total issues ouvertes sans filtre milestone : ${issues.length})`);
|
||||
const withM = issues.filter((i) => i.milestone);
|
||||
if (withM.length) {
|
||||
console.log('');
|
||||
console.log('Issues ouvertes qui ont *un* milestone :');
|
||||
for (const i of withM) {
|
||||
console.log(`- #${i.number} [${i.milestone.title}] ${i.title}`);
|
||||
}
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
for (const i of filtered.sort((a, b) => a.number - b.number)) {
|
||||
const labels = (i.labels || []).map((l) => l.name).join(', ');
|
||||
console.log(`- **#${i.number}** — ${i.title}`);
|
||||
if (labels) console.log(` - Labels : ${labels}`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user