antcolony
All repositories: gitoria
7.3 KB
// deploy.hl — mission 027 (ticket antcolony#1, first live batch 2026-09-24): the DEPLOY GATE's two commands.//// Why: the creator can only test on the live site. A passed, complete report on a project whose registry has `live`// is therefore NOT "ready for you to test" (report.hl deployGate): it gets ONE line "Built — goes live with the next// deploy." (machine line `colony-report: S · sha256 H · controller pass · ready to deploy`) and the ticket stays// `in progress` — out of `next`, its lease never expires (lease.hl readyOf / leaseOf kind `ready`).//// ./colony ready every ticket waiting for a deploy (GETs only), grouped by project, with the live// site and the deploy note of the registry// ./colony deployed <project> <n> after the architect deployed: the readable comment — "Now live on <site> — <result>",// **Test:** as a numbered list, ≤ 3 details (questions, problems filed elsewhere,// Decided, not done …), machine line `colony-deployed: S · sha256 H` — from the// session's runs/<S>/report.json on THIS host; then `in progress → awaiting creator`// ("Ready for you to test — see the last comment."). Idempotent: a second call writes// nothing (a missing state change is repaired).import { env } from 'hl:proc'import { loadRegistry } from './registry.hl'import { getJson, postJson, readToken, ticketPath, pageUrl, allTickets } from './tickets.hl'import { readyOf } from './lease.hl'import { survey } from './next.hl'import { deployedCommentOf, siteName, linkOf, refLabel } from './report.hl'import { sha256 } from 'hl:crypto'import { NL, readJson, fromCwd, positionals } from './util.hl'static runsDirOf = () => {let r = env('COLONY_RUNS_DIR')if (r != null && r != '') { return fromCwd(r) }let home = env('COLONY_HOME')return home == null || home == '' ? './runs' : home + '/runs'}// `./colony ready`static runReady = (argv) => {let sv = survey()if (sv.error != null) {console.log('ready: ' + sv.error)return false}let n = 0for (e of sv.notEligible) {let t = e.tif (t.state == 'in progress' && t.readySession != null) {n = n + 1let m = sv.reg.projects[t.project]let live = m == null || m.live == null ? '(no live entry any more)' : (m.live.url != null ? m.live.url : m.live.host + ':' + m.live.folder)let dep = m == null || m.deploy == null ? '' : ' · deploy: ' + m.deployconsole.log('READY ' + t.project + t.ref + ' "' + t.subject + '" — built by session ' + t.readySession + ' · live ' + live + dep + ' · after the deploy: ./colony deployed ' + t.project + ' ' + t.number + ' · ' + pageUrl(t))}}console.log('READY: ' + n + ' ticket(s) waiting for a deploy' + (n > 0 ? ' — deploy, then `./colony deployed <project> <n>` for each' : ''))return true}// the filed questions / issues of a session (by their `source`) → { asked: [link], filed: [{ link, blocks, unknown }] }static filedOf = (session, report) => {let asked = []let filed = []let all = allTickets()if (all.error != null) { return { asked = asked filed = filed } }let pre = 'colony-report:' + session + ':'let qi = 0while (qi < report.questions.length) {for (t of all.tickets) { if (t.source == pre + 'questions:' + qi) { asked.push(linkOf(t)) } }qi = qi + 1}let ii = 0while (ii < report.issues.length) {for (t of all.tickets) {if (t.source == pre + 'issue:' + ii) { filed.push({ link = linkOf(t) blocks = report.issues[ii].blocks unknown = false }) }else if (t.source == pre + 'question:' + ii) { filed.push({ link = linkOf(t) blocks = false unknown = true }) }}ii = ii + 1}return { asked = asked filed = filed }}// `./colony deployed <project> <n>`static runDeployed = (argv) => {let pos = positionals(argv)if (pos.length != 3) {console.log('usage: deployed <project> <number>')return false}let project = pos[1]let number = pos[2]let ref = project + '#' + numberlet tk = readToken()if (tk.error != null) {console.log('deployed: REFUSED — ' + tk.error)return false}let got = getJson(ticketPath(project, number))if (got.status != 200) {console.log('deployed: REFUSED — ticket ' + ref + ' → ' + got.status)return false}let t = got.json.ticketlet events = got.json.events// already done? (idempotent: the deployed comment of the last ready session exists)let lastReady = nullfor (e of events) {if (e.kind == 'comment' && e.text != null) {for (l of e.text.split(NL)) {let x = l.trim()if (x.startsWith('colony-report: ') && x.endsWith(' · ready to deploy')) { lastReady = x.slice(15).split(' · ')[0].trim() }}}}let have = falseif (lastReady != null) {for (e of events) { if (e.kind == 'comment' && e.text != null && e.text.includes('colony-deployed: ' + lastReady + ' ·')) { have = true } }}let session = readyOf(events)if (session == null && !have) {console.log('deployed: REFUSED — ' + ref + ' is "' + t.state + '" and not waiting for a deploy (no "ready to deploy" report of a colony session' + (lastReady != null ? '; the last one, ' + lastReady + ', is void: the ticket left "in progress" or another session started' : '') + '). Nothing written.')return false}if (session == null) { session = lastReady }let reg = loadRegistry()let m = reg.projects[project]let site = m != null && m.live != null && m.live.url != null ? siteName(m.live.url) : projectlet token = tk.tokenif (have) {console.log(' HAVE the deployed comment of session ' + session + ' on ' + ref + ' — not written again')} else {let dir = runsDirOf() + '/' + sessionlet rj = readJson(dir + '/report.json')if (rj.error != null) {console.log('deployed: REFUSED — the report of session ' + session + ' is not on this host (' + rj.error + '); run `deployed` where the session ran. Nothing written.')return false}let r = rj.valueif (r.session != session || r.ticket != ref) {console.log('deployed: REFUSED — ' + dir + '/report.json is for ' + r.ticket + ' session ' + r.session + ', not ' + ref + ' session ' + session + '. Nothing written.')return false}let hash = sha256(JSON.stringify(r)).slice(0, 12)let f = filedOf(session, r)let text = deployedCommentOf(r, f.filed, f.asked, site, hash)let c = postJson(ticketPath(project, number) + '/comments', { text = text }, token)if (c.status != 201) {console.log('deployed: FAILED — comment on ' + ref + ': ' + c.status + ' ' + c.text)return false}console.log(' POSTED the deployed comment on ' + ref + ' ' + pageUrl(t))for (l of text.split(NL)) { console.log(' | ' + l) }t = c.json.ticket}if (t.state == 'in progress') {let s = postJson(ticketPath(project, number) + '/state', { state = 'awaiting creator' text = 'Ready for you to test — see the last comment.' }, token)if (s.status != 201) {console.log('deployed: FAILED — state of ' + ref + ': ' + s.status + ' ' + s.text + ' — re-run (idempotent)')return false}console.log(' STATE ' + ref + ': in progress → awaiting creator')} else {console.log(' STATE left as "' + t.state + '"')}console.log('DEPLOYED — ' + ref + ' (session ' + session + ', live on ' + site + ')' + (have ? ': nothing new' : ''))return true}
Branches
- mainmain branch
Latest commits
- 7f9660eeState of 2026-09-27, before the move to gitoriamre