@orkastery/cli 0.5.6 → 0.6.0
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/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +37 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
- package/adapters/openclaw/README.md +81 -9
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +118 -4
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +3 -1
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +51 -46
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +94 -40
- package/dist/branch-de-estado.js +16 -8
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +2 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +500 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +183 -0
- package/dist/ci.js +248 -45
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +47 -39
- package/dist/claims.js +10 -9
- package/dist/company-brain-client.js +10 -3
- package/dist/company-brain-migration.js +11 -5
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +25 -8
- package/dist/conducao.js +84 -29
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +111 -87
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +81 -74
- package/dist/doctor-forja.js +345 -0
- package/dist/doctor-pulse-cron.js +113 -1
- package/dist/doctor.js +164 -6
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +143 -43
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +21 -18
- package/dist/evalrunner.js +35 -32
- package/dist/fabrica-batida.js +34 -21
- package/dist/fabrica-estado.js +13 -10
- package/dist/fix.js +21 -19
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +123 -80
- package/dist/handoff.js +23 -13
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +51 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +44 -1
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +34 -31
- package/dist/horario.js +16 -0
- package/dist/hosts.js +104 -134
- package/dist/index.js +848 -548
- package/dist/indice-vetorial.js +14 -12
- package/dist/init.js +11 -2
- package/dist/integracoes-locais.js +2 -0
- package/dist/intelligence-graph-cli.js +123 -69
- package/dist/intelligence-graph-query.js +37 -22
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +31 -1
- package/dist/licoes.js +12 -11
- package/dist/locale-accounts.js +220 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +76 -4
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +290 -0
- package/dist/locale-gerados.js +5 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +83 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +140 -2
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +145 -6
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +169 -66
- package/dist/locale-thread.js +149 -5
- package/dist/locale-verify.js +80 -4
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +553 -9
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +287 -11
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +10 -5
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +10 -2
- package/dist/master.js +118 -41
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-install.js +73 -8
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +82 -14
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +68 -24
- package/dist/mcp-transportes.js +17 -0
- package/dist/memoria.js +63 -58
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +17 -18
- package/dist/network-roadmap.js +85 -49
- package/dist/noctum-aceite.js +789 -0
- package/dist/noctum-arco.js +540 -33
- package/dist/noctum-capacidade.js +3 -3
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +482 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1169 -0
- package/dist/noctum-envelope.js +252 -16
- package/dist/noctum-execucao.js +95 -23
- package/dist/noctum-fechamento.js +405 -0
- package/dist/noctum-fila.js +43 -9
- package/dist/noctum-guarda.js +256 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +383 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +362 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +591 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +827 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +639 -0
- package/dist/ocupacao.js +3 -1
- package/dist/onboarding.js +16 -5
- package/dist/orkmind.js +39 -23
- package/dist/orquestracao.js +31 -35
- package/dist/parado-no-condutor.js +146 -124
- package/dist/phase.js +53 -27
- package/dist/policies.js +33 -0
- package/dist/postura-local.js +4 -3
- package/dist/procedencia.js +9 -14
- package/dist/projeto-alvo.js +59 -20
- package/dist/prompts.js +136 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +143 -27
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +136 -3
- package/dist/ratelimit.js +12 -4
- package/dist/recall.js +14 -13
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +63 -45
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +228 -73
- package/dist/roadmap-reservas.js +32 -32
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +117 -43
- package/dist/runtime-escada.js +423 -0
- package/dist/runtime-profiles.js +103 -46
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +355 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +188 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +19 -2
- package/dist/session-watcher-claude.js +74 -19
- package/dist/session-watcher.js +156 -10
- package/dist/sessoes-contas.js +9 -0
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +59 -58
- package/dist/ship-publicar.js +263 -92
- package/dist/ship.js +160 -17
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +9 -9
- package/dist/thread.js +121 -18
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +5 -2
- package/dist/varredura-acoes.js +507 -0
- package/dist/verify.js +472 -29
- package/dist/worktree-local.js +12 -10
- package/dist/worktree.js +81 -85
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +9 -4
- package/references/security-checklist.md +3 -3
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.chamadorDaApi = exports.limiteBaixo = exports.chaveDoLogin = exports.MAX_PAGINAS = exports.POR_PAGINA = exports.ESPERA_MAXIMA_DO_LIMITE_MS = exports.PRAZO_DA_API_MS = void 0;
|
|
37
|
+
exports.temLogin = temLogin;
|
|
38
|
+
exports.lerSaidaHttp = lerSaidaHttp;
|
|
39
|
+
exports.chamarApi = chamarApi;
|
|
40
|
+
exports.proximaPagina = proximaPagina;
|
|
41
|
+
exports.paginarPelaApi = paginarPelaApi;
|
|
42
|
+
exports.paginarApi = paginarApi;
|
|
43
|
+
/**
|
|
44
|
+
* A chamada a API REST da forja pela CLI ja logada (`gh api`, `glab api`). O host vai sempre explicito (`CLI_DA_FORJA`),
|
|
45
|
+
* o corpo vai pelo stdin, a resposta vem com o status e os cabecalhos (`-i`), o ambiente e reduzido e o diretorio e
|
|
46
|
+
* neutro. O erro sai tipado pelo status HTTP. Um 429 em leitura espera o `tentarEm` uma vez, ate 60 s, e repete;
|
|
47
|
+
* escrita nunca se repete sozinha (quem chamou rele o estado antes de agir). No `glab`, que faz o pedido anonimo quando
|
|
48
|
+
* nao tem login no host, o login e conferido antes da primeira chamada de cada host do processo. A paginacao segue o
|
|
49
|
+
* `Link` (ou o `x-next-page` do GitLab) ate 10 paginas de 100; passou disso, `forja.incompleto`.
|
|
50
|
+
*/
|
|
51
|
+
const os = __importStar(require("node:os"));
|
|
52
|
+
const forja_1 = require("../forja");
|
|
53
|
+
const cli_1 = require("./cli");
|
|
54
|
+
const executor_1 = require("./executor");
|
|
55
|
+
exports.PRAZO_DA_API_MS = 30_000;
|
|
56
|
+
exports.ESPERA_MAXIMA_DO_LIMITE_MS = 60_000;
|
|
57
|
+
exports.POR_PAGINA = 100;
|
|
58
|
+
exports.MAX_PAGINAS = 10;
|
|
59
|
+
const TETO_DA_SAIDA = 32 * 1024 * 1024;
|
|
60
|
+
const PRAZO_DO_LOGIN_MS = 15_000;
|
|
61
|
+
const LOGINS = new Map();
|
|
62
|
+
const falha = (codigo, detalhe) => ({ ok: false, erro: { codigo, detalhe } });
|
|
63
|
+
const dormir = (ms) => { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); };
|
|
64
|
+
/** A chave do login: o host como a CLI o guarda, `host` ou `host:porta`, nunca com o caminho base. */
|
|
65
|
+
const chaveDoLogin = (f) => (0, cli_1.hostDaApi)(f);
|
|
66
|
+
exports.chaveDoLogin = chaveDoLogin;
|
|
67
|
+
/**
|
|
68
|
+
* A CLI do tipo tem login no host exato? O codigo de saida, e a saida quando a CLI nao filtra o host sozinha.
|
|
69
|
+
* `binario`: o caminho absoluto da CLI a rodar, sem busca no PATH.
|
|
70
|
+
*/
|
|
71
|
+
function temLogin(f, rodar = executor_1.rodarCli, binario) {
|
|
72
|
+
const cli = cli_1.CLI_DA_FORJA[f.tipo];
|
|
73
|
+
const s = rodar({ cmd: cli.cmd, args: cli.login(f), prazoMs: PRAZO_DO_LOGIN_MS, maxBuffer: 1024 * 1024, ...cli.ambiente(f),
|
|
74
|
+
cwd: os.tmpdir(), reduzido: true, ...(binario !== undefined ? { binario } : {}) });
|
|
75
|
+
return s.status === 0 && (cli.confirmaLogin?.(f, `${s.stdout}\n${s.stderr}`) ?? true);
|
|
76
|
+
}
|
|
77
|
+
/** A saida de `-i`: `HTTP/x NNN texto`, os cabecalhos ate a linha vazia (CRLF ou LF) e o corpo. */
|
|
78
|
+
function lerSaidaHttp(stdout) {
|
|
79
|
+
const linha = /^HTTP\/\d(?:\.\d)? (\d{3})\b[^\n]*\n/.exec(stdout);
|
|
80
|
+
if (!linha)
|
|
81
|
+
return null;
|
|
82
|
+
const resto = stdout.slice(linha[0].length);
|
|
83
|
+
const cabecalhos = {};
|
|
84
|
+
let pos = 0;
|
|
85
|
+
for (;;) {
|
|
86
|
+
const fim = resto.indexOf('\n', pos);
|
|
87
|
+
if (fim < 0)
|
|
88
|
+
return null;
|
|
89
|
+
const l = resto.slice(pos, fim).replace(/\r$/, '');
|
|
90
|
+
pos = fim + 1;
|
|
91
|
+
if (l === '')
|
|
92
|
+
break;
|
|
93
|
+
const dois = l.indexOf(':');
|
|
94
|
+
if (dois > 0)
|
|
95
|
+
cabecalhos[l.slice(0, dois).trim().toLowerCase()] = l.slice(dois + 1).trim();
|
|
96
|
+
}
|
|
97
|
+
return { status: Number(linha[1]), cabecalhos, corpo: resto.slice(pos) };
|
|
98
|
+
}
|
|
99
|
+
const inteiro = (v) => (v !== undefined && /^\d+$/.test(v) ? Number(v) : null);
|
|
100
|
+
function limiteDe(c) {
|
|
101
|
+
const reset = inteiro(c['ratelimit-reset'] ?? c['x-ratelimit-reset']);
|
|
102
|
+
return { restante: inteiro(c['ratelimit-remaining'] ?? c['x-ratelimit-remaining']), total: inteiro(c['ratelimit-limit'] ?? c['x-ratelimit-limit']),
|
|
103
|
+
reiniciaEm: reset === null ? null : new Date(reset * 1000).toISOString() };
|
|
104
|
+
}
|
|
105
|
+
/** A cota abaixo de 10 %: os consumidores de fundo (pulse, espera de CI) espacam as chamadas. */
|
|
106
|
+
const limiteBaixo = (l) => l.restante !== null && l.total !== null && l.total > 0 && l.restante < l.total * 0.1;
|
|
107
|
+
exports.limiteBaixo = limiteBaixo;
|
|
108
|
+
/** Quando tentar de novo: o `Retry-After` (segundos ou data) ou o reset da cota (epoch em segundos). */
|
|
109
|
+
function tentarEmDe(c, agora) {
|
|
110
|
+
const espera = c['retry-after'];
|
|
111
|
+
if (espera && /^\d+$/.test(espera))
|
|
112
|
+
return new Date(agora + Number(espera) * 1000).toISOString();
|
|
113
|
+
if (espera && Number.isFinite(Date.parse(espera)))
|
|
114
|
+
return new Date(Date.parse(espera)).toISOString();
|
|
115
|
+
const reset = inteiro(c['ratelimit-reset'] ?? c['x-ratelimit-reset']);
|
|
116
|
+
return reset === null ? null : new Date(reset * 1000).toISOString();
|
|
117
|
+
}
|
|
118
|
+
/** A mensagem do corpo de erro (`message` no GitHub e no GitLab, que as vezes a da como objeto). */
|
|
119
|
+
function mensagemDoCorpo(texto) {
|
|
120
|
+
try {
|
|
121
|
+
const j = JSON.parse(texto);
|
|
122
|
+
const m = j && typeof j === 'object' ? j.message ?? j.error ?? j.error_description : undefined;
|
|
123
|
+
return typeof m === 'string' ? m : m === undefined ? '' : JSON.stringify(m);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return texto.trim().slice(0, 200);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function erroDoStatus(h, pedido, agora) {
|
|
130
|
+
const texto = mensagemDoCorpo(h.corpo);
|
|
131
|
+
const detalhe = (0, forja_1.detalheSeguro)(`HTTP ${h.status} ${pedido.metodo} ${pedido.caminho}${texto ? `: ${texto}` : ''}`);
|
|
132
|
+
// O GitHub responde 403, e nao 429, quando a cota primaria acaba (`x-ratelimit-remaining: 0`) e na secundaria.
|
|
133
|
+
// O limite secundario pode vir com a cota primaria sobrando e sem `Retry-After`: so a mensagem o diz, e a espera
|
|
134
|
+
// minima recomendada e de 60 s (o reset da cota primaria nao vale para ele).
|
|
135
|
+
const secundario = h.status === 403 && !('retry-after' in h.cabecalhos) && h.cabecalhos['x-ratelimit-remaining'] !== '0'
|
|
136
|
+
&& /rate limit/i.test(texto);
|
|
137
|
+
const cota = h.status === 429 || (h.status === 403 && (h.cabecalhos['x-ratelimit-remaining'] === '0' || 'retry-after' in h.cabecalhos)) || secundario;
|
|
138
|
+
if (cota) {
|
|
139
|
+
const tentarEm = secundario ? new Date(agora + 60_000).toISOString() : tentarEmDe(h.cabecalhos, agora);
|
|
140
|
+
return { codigo: 'forja.limite', detalhe, ...(tentarEm ? { tentarEm } : {}) };
|
|
141
|
+
}
|
|
142
|
+
const codigo = h.status === 401 ? 'forja.sem-login' : h.status === 403 ? 'forja.sem-permissao'
|
|
143
|
+
: h.status === 404 ? 'forja.nao-achei' : h.status === 409 ? 'forja.conflito' : h.status >= 500 ? 'forja.indisponivel' : 'forja.pedido-recusado';
|
|
144
|
+
return { codigo, detalhe };
|
|
145
|
+
}
|
|
146
|
+
function umaChamada(f, pedido, rodar, agora) {
|
|
147
|
+
const cli = cli_1.CLI_DA_FORJA[f.tipo];
|
|
148
|
+
const prazoMs = pedido.prazoMs ?? exports.PRAZO_DA_API_MS;
|
|
149
|
+
const comCorpo = pedido.corpo !== undefined;
|
|
150
|
+
const s = rodar({ cmd: cli.cmd, args: cli.api(f, pedido.metodo, pedido.caminho, comCorpo), entrada: comCorpo ? JSON.stringify(pedido.corpo) : undefined,
|
|
151
|
+
prazoMs, maxBuffer: TETO_DA_SAIDA, ...cli.ambiente(f), cwd: os.tmpdir(), reduzido: true });
|
|
152
|
+
if (s.erro === 'ENOENT')
|
|
153
|
+
return falha('forja.ausente', `${cli.cmd}: ENOENT`);
|
|
154
|
+
// O estouro do teto tambem mata o processo com SIGTERM: vem antes do prazo.
|
|
155
|
+
if (s.erro === 'ENOBUFS')
|
|
156
|
+
return falha('forja.resposta-invalida', (0, forja_1.detalheSeguro)(`${pedido.metodo} ${pedido.caminho}: saida > ${TETO_DA_SAIDA} B`));
|
|
157
|
+
if (s.erro === 'ETIMEDOUT' || s.sinal === 'SIGTERM')
|
|
158
|
+
return falha('forja.indisponivel', `${cli.cmd}: ${Math.round(prazoMs / 1000)} s`);
|
|
159
|
+
const h = lerSaidaHttp(s.stdout);
|
|
160
|
+
if (!h) {
|
|
161
|
+
const texto = `${s.stderr}\n${s.stdout}`;
|
|
162
|
+
const semLogin = /auth login|not logged|not been authenticated|no token|GH_TOKEN|GITLAB_TOKEN/i.test(texto);
|
|
163
|
+
return falha(semLogin ? 'forja.sem-login' : 'forja.indisponivel', (0, forja_1.detalheSeguro)(s.stderr || s.stdout || `${cli.cmd}: ${s.status}`));
|
|
164
|
+
}
|
|
165
|
+
if (h.status < 200 || h.status >= 300)
|
|
166
|
+
return { ok: false, erro: erroDoStatus(h, pedido, agora) };
|
|
167
|
+
let corpo = null;
|
|
168
|
+
if (h.corpo.trim()) {
|
|
169
|
+
try {
|
|
170
|
+
corpo = JSON.parse(h.corpo);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return falha('forja.resposta-invalida', (0, forja_1.detalheSeguro)(`HTTP ${h.status} ${pedido.metodo} ${pedido.caminho}`));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return { ok: true, valor: { status: h.status, corpo, cabecalhos: h.cabecalhos, limite: limiteDe(h.cabecalhos) } };
|
|
177
|
+
}
|
|
178
|
+
function chamarApi(f, pedido, opcoes = {}) {
|
|
179
|
+
const rodar = opcoes.rodar ?? executor_1.rodarCli, agoraMs = opcoes.agoraMs ?? Date.now, esperar = opcoes.esperar ?? dormir;
|
|
180
|
+
const cli = cli_1.CLI_DA_FORJA[f.tipo];
|
|
181
|
+
// Um caminho com `-` na frente seria lido pela CLI como opcao.
|
|
182
|
+
if (pedido.caminho.startsWith('-'))
|
|
183
|
+
return falha('forja.pedido-recusado', (0, forja_1.detalheSeguro)(`${pedido.metodo} ${pedido.caminho}: caminho com - na frente`));
|
|
184
|
+
if (cli.loginAntes) {
|
|
185
|
+
const logins = opcoes.logins ?? LOGINS, chave = (0, exports.chaveDoLogin)(f);
|
|
186
|
+
let comLogin = logins.get(chave);
|
|
187
|
+
// So o login confirmado fica guardado: uma falha passageira nao marca o host como sem login pelo resto do processo.
|
|
188
|
+
if (comLogin === undefined) {
|
|
189
|
+
comLogin = temLogin(f, rodar);
|
|
190
|
+
if (comLogin)
|
|
191
|
+
logins.set(chave, true);
|
|
192
|
+
}
|
|
193
|
+
if (!comLogin)
|
|
194
|
+
return falha('forja.sem-login', `${cli.cmd} ${chave}`);
|
|
195
|
+
}
|
|
196
|
+
const r = umaChamada(f, pedido, rodar, agoraMs());
|
|
197
|
+
if (r.ok || r.erro.codigo !== 'forja.limite' || pedido.metodo !== 'GET' || !r.erro.tentarEm)
|
|
198
|
+
return r;
|
|
199
|
+
const espera = Date.parse(r.erro.tentarEm) - agoraMs();
|
|
200
|
+
if (espera > exports.ESPERA_MAXIMA_DO_LIMITE_MS)
|
|
201
|
+
return r;
|
|
202
|
+
esperar(Math.max(0, espera));
|
|
203
|
+
return umaChamada(f, pedido, rodar, agoraMs());
|
|
204
|
+
}
|
|
205
|
+
const chamadorDaApi = (f, opcoes = {}) => (p) => chamarApi(f, p, opcoes);
|
|
206
|
+
exports.chamadorDaApi = chamadorDaApi;
|
|
207
|
+
/** O numero da proxima pagina: do `Link` `rel="next"` ou do `x-next-page`. `sem-numero`: ha proxima sem `page=`. */
|
|
208
|
+
function proximaPagina(cabecalhos) {
|
|
209
|
+
const link = cabecalhos.link;
|
|
210
|
+
// O header inteiro, sem cortar na virgula: a URL do next pode ter virgula (`labels=a,b`). Com `rel=next` e sem o
|
|
211
|
+
// numero lido, `sem-numero`, nunca o fim da lista.
|
|
212
|
+
if (link && /\brel="?next\b/.test(link)) {
|
|
213
|
+
const m = /<([^>]*)>\s*;\s*rel="?next\b/.exec(link);
|
|
214
|
+
const pagina = m ? /[?&]page=(\d+)/.exec(m[1]) : null;
|
|
215
|
+
return pagina ? Number(pagina[1]) : 'sem-numero';
|
|
216
|
+
}
|
|
217
|
+
return inteiro(cabecalhos['x-next-page'] || undefined);
|
|
218
|
+
}
|
|
219
|
+
function comPagina(caminho, pagina) {
|
|
220
|
+
const corte = caminho.indexOf('?');
|
|
221
|
+
const base = corte < 0 ? caminho : caminho.slice(0, corte);
|
|
222
|
+
const consulta = new URLSearchParams(corte < 0 ? '' : caminho.slice(corte + 1));
|
|
223
|
+
consulta.set('per_page', String(exports.POR_PAGINA));
|
|
224
|
+
consulta.set('page', String(pagina));
|
|
225
|
+
return `${base}?${consulta.toString()}`;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Le as paginas de uma lista (GET) por um chamador ja ligado a forja, pelo numero que a forja manda. `itens` extrai a
|
|
229
|
+
* lista do corpo (`null`: fora do formato); sem ele, o corpo tem de ser a lista. Mais de 10 paginas: `forja.incompleto`,
|
|
230
|
+
* nunca a lista curta.
|
|
231
|
+
*/
|
|
232
|
+
function paginarPelaApi(api, p) {
|
|
233
|
+
const extrair = p.itens ?? ((corpo) => (Array.isArray(corpo) ? corpo : null));
|
|
234
|
+
const itens = [];
|
|
235
|
+
let pagina = 1;
|
|
236
|
+
for (let lidas = 1; lidas <= exports.MAX_PAGINAS; lidas++) {
|
|
237
|
+
const r = api({ metodo: 'GET', caminho: comPagina(p.caminho, pagina), prazoMs: p.prazoMs });
|
|
238
|
+
if (!r.ok)
|
|
239
|
+
return r;
|
|
240
|
+
const lista = extrair(r.valor.corpo);
|
|
241
|
+
if (!lista)
|
|
242
|
+
return falha('forja.resposta-invalida', (0, forja_1.detalheSeguro)(p.caminho));
|
|
243
|
+
itens.push(...lista);
|
|
244
|
+
const proxima = proximaPagina(r.valor.cabecalhos);
|
|
245
|
+
if (proxima === null)
|
|
246
|
+
return { ok: true, valor: { itens, paginas: lidas } };
|
|
247
|
+
if (proxima === 'sem-numero' || proxima <= pagina)
|
|
248
|
+
return falha('forja.resposta-invalida', (0, forja_1.detalheSeguro)(`${p.caminho}: next`));
|
|
249
|
+
pagina = proxima;
|
|
250
|
+
}
|
|
251
|
+
return falha('forja.incompleto', (0, forja_1.detalheSeguro)(`${p.caminho} > ${exports.MAX_PAGINAS}x${exports.POR_PAGINA}`));
|
|
252
|
+
}
|
|
253
|
+
/** `paginarPelaApi` com o chamador da forja `f`. */
|
|
254
|
+
function paginarApi(f, p, opcoes = {}) {
|
|
255
|
+
return paginarPelaApi((0, exports.chamadorDaApi)(f, opcoes), p);
|
|
256
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.VALIDADE_DO_CACHE_MS = void 0;
|
|
37
|
+
exports.dirDoCacheDaForja = dirDoCacheDaForja;
|
|
38
|
+
exports.lerDoCache = lerDoCache;
|
|
39
|
+
exports.gravarNoCache = gravarNoCache;
|
|
40
|
+
/**
|
|
41
|
+
* O cache da forja: um arquivo JSON por raiz do estado (`.orkastery/cache/forja.json`) com o que vale 24 h, a versao do
|
|
42
|
+
* servidor e o tipo sondado de um host. Arquivo ilegivel e entrada vencida (ou datada no futuro alem da folga do
|
|
43
|
+
* relogio) sao ignorados; escrita que falha tambem: o cache e conveniencia, e sem ele a leitura consulta de novo.
|
|
44
|
+
*/
|
|
45
|
+
const fs = __importStar(require("node:fs"));
|
|
46
|
+
const path = __importStar(require("node:path"));
|
|
47
|
+
const estado_thread_1 = require("../estado-thread");
|
|
48
|
+
const manifest_1 = require("../manifest");
|
|
49
|
+
exports.VALIDADE_DO_CACHE_MS = 24 * 60 * 60 * 1000;
|
|
50
|
+
const ARQUIVO = 'forja.json';
|
|
51
|
+
const FOLGA_DO_RELOGIO_MS = 5 * 60 * 1000;
|
|
52
|
+
/** O diretorio do cache da raiz (a da arvore principal, tambem numa worktree); `null` sem estado legivel. */
|
|
53
|
+
function dirDoCacheDaForja(raiz) {
|
|
54
|
+
try {
|
|
55
|
+
return path.join((0, manifest_1.dirEstado)((0, estado_thread_1.raizDoEstado)(raiz)), 'cache');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function todos(dir) {
|
|
62
|
+
try {
|
|
63
|
+
const j = JSON.parse(fs.readFileSync(path.join(dir, ARQUIVO), 'utf8'));
|
|
64
|
+
return j && typeof j === 'object' && !Array.isArray(j) ? j : {};
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** A entrada da chave gravada ha menos de 24 h, ou `null`. */
|
|
71
|
+
function lerDoCache(dir, chave, agoraMs) {
|
|
72
|
+
if (!dir)
|
|
73
|
+
return null;
|
|
74
|
+
const e = todos(dir)[chave];
|
|
75
|
+
if (!e || typeof e !== 'object' || Array.isArray(e))
|
|
76
|
+
return null;
|
|
77
|
+
const t = Date.parse(String(e.lidoEm));
|
|
78
|
+
return Number.isFinite(t) && t <= agoraMs + FOLGA_DO_RELOGIO_MS && agoraMs - t < exports.VALIDADE_DO_CACHE_MS ? e : null;
|
|
79
|
+
}
|
|
80
|
+
/** Grava a entrada com `lidoEm`; pasta 700 e arquivo 600, os modos do estado do projeto. */
|
|
81
|
+
function gravarNoCache(dir, chave, valor, agoraMs) {
|
|
82
|
+
if (!dir)
|
|
83
|
+
return;
|
|
84
|
+
try {
|
|
85
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
86
|
+
fs.writeFileSync(path.join(dir, ARQUIVO), `${JSON.stringify({ ...todos(dir), [chave]: { ...valor, lidoEm: new Date(agoraMs).toISOString() } }, null, 2)}\n`, { mode: 0o600 });
|
|
87
|
+
}
|
|
88
|
+
catch { /* sem escrita, a proxima leitura consulta de novo */ }
|
|
89
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLI_DA_FORJA = exports.hostDaApi = void 0;
|
|
4
|
+
exports.versaoAbaixo = versaoAbaixo;
|
|
5
|
+
/** `host` ou `host:porta`, sem a porta padrao do HTTPS e sem o caminho base: e tambem a chave do login da CLI. */
|
|
6
|
+
const hostDaApi = (f) => (f.porta !== null && f.porta !== 443 ? `${f.host}:${f.porta}` : f.host);
|
|
7
|
+
exports.hostDaApi = hostDaApi;
|
|
8
|
+
const SEM_PROMPT = { GH_PROMPT_DISABLED: '1', GH_NO_UPDATE_NOTIFIER: '1', GLAB_CHECK_UPDATE: 'false', GLAB_SEND_TELEMETRY: 'false', NO_COLOR: '1' };
|
|
9
|
+
/** O host com porta: o `gh` recusa `--hostname host:porta` (medido no 2.102.0) e o recebe por `GH_HOST`. */
|
|
10
|
+
const comPorta = (f) => (0, exports.hostDaApi)(f) !== f.host;
|
|
11
|
+
const hostnameDoGh = (f) => (comPorta(f) ? [] : ['--hostname', f.host]);
|
|
12
|
+
exports.CLI_DA_FORJA = {
|
|
13
|
+
github: {
|
|
14
|
+
cmd: 'gh',
|
|
15
|
+
// 2.18.0, medida: `pr list --json` com `headRefOid`, `api -i`, `auth status --hostname`, `auth git-credential`, `--body-file`.
|
|
16
|
+
minima: '2.18.0',
|
|
17
|
+
loginAntes: false,
|
|
18
|
+
// O gh nao tem opcao de CA; o Go le SSL_CERT_FILE no Linux. O GH_HOST herdado sai, salvo quando e o nosso (host:porta).
|
|
19
|
+
ambiente: (f) => ({
|
|
20
|
+
acrescentar: { ...SEM_PROMPT, ...(comPorta(f) ? { GH_HOST: (0, exports.hostDaApi)(f) } : {}), ...(f.ca ? { SSL_CERT_FILE: f.ca } : {}) },
|
|
21
|
+
apagar: [...(comPorta(f) ? [] : ['GH_HOST']), 'GH_REPO', 'GH_FORCE_TTY'],
|
|
22
|
+
}),
|
|
23
|
+
api: (f, metodo, caminho, comCorpo) => ['api', ...hostnameDoGh(f), '-i', '--method', metodo,
|
|
24
|
+
'-H', 'Accept: application/vnd.github+json', caminho, ...(comCorpo ? ['--input', '-'] : [])],
|
|
25
|
+
login: (f) => ['auth', 'status', ...hostnameDoGh(f)],
|
|
26
|
+
// Com porta, o `auth status` roda sem `--hostname` e sai 0 se QUALQUER host tem login: so vale a linha de login
|
|
27
|
+
// do host:porta exato, nos dois formatos do gh (`Logged in to H as U` e `Logged in to H account U`).
|
|
28
|
+
confirmaLogin: (f, saida) => !comPorta(f)
|
|
29
|
+
|| new RegExp(`Logged in to ${(0, exports.hostDaApi)(f).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')} (?:as|account) `).test(saida),
|
|
30
|
+
entrar: (f) => (comPorta(f) ? [`GH_HOST=${(0, exports.hostDaApi)(f)}`, 'gh', 'auth', 'login'] : ['gh', 'auth', 'login', '--hostname', f.host]),
|
|
31
|
+
lerVersao: (s) => /^gh version (\d+\.\d+\.\d+)/m.exec(s)?.[1] ?? null,
|
|
32
|
+
},
|
|
33
|
+
gitlab: {
|
|
34
|
+
cmd: 'glab',
|
|
35
|
+
// 1.121.0, medida: GITLAB_HOST com porta, login com subcaminho, `auth git-credential`, GLAB_CA_CERT, `api -i`.
|
|
36
|
+
minima: '1.121.0',
|
|
37
|
+
loginAntes: true,
|
|
38
|
+
ambiente: (f) => ({
|
|
39
|
+
acrescentar: { ...SEM_PROMPT, GITLAB_HOST: (0, exports.hostDaApi)(f), ...(f.ca ? { GLAB_CA_CERT: f.ca } : {}) },
|
|
40
|
+
// Estas mudariam o host ou a CA por fora do GITLAB_HOST.
|
|
41
|
+
apagar: ['GITLAB_URI', 'GL_HOST', 'GITLAB_API_HOST', 'CA_CERT'],
|
|
42
|
+
}),
|
|
43
|
+
// Sem Content-Type, o GitLab ignora o corpo do `--input -` (medido).
|
|
44
|
+
api: (_f, metodo, caminho, comCorpo) => ['api', '-i', '--method', metodo, caminho,
|
|
45
|
+
...(comCorpo ? ['-H', 'Content-Type: application/json', '--input', '-'] : [])],
|
|
46
|
+
login: (f) => ['auth', 'status', '--hostname', (0, exports.hostDaApi)(f)],
|
|
47
|
+
entrar: (f, http) => ['glab', 'auth', 'login', '--hostname', `${(0, exports.hostDaApi)(f)}${f.caminhoBase}`, ...(http ? ['--api-protocol', 'http'] : []), '--stdin'],
|
|
48
|
+
lerVersao: (s) => /^glab (?:version )?(\d+\.\d+\.\d+)/m.exec(s)?.[1] ?? null,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
/** `versao` (x.y.z) abaixo de `minima`? */
|
|
52
|
+
function versaoAbaixo(versao, minima) {
|
|
53
|
+
const a = versao.split('.').map(Number), b = minima.split('.').map(Number);
|
|
54
|
+
for (let i = 0; i < 3; i++) {
|
|
55
|
+
const x = a[i] ?? 0, y = b[i] ?? 0;
|
|
56
|
+
if (x !== y)
|
|
57
|
+
return x < y;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* O contrato neutro da forja. Os tipos abaixo moram aqui e `forja.ts` os
|
|
4
|
+
* reexporta com o mesmo nome; nenhum depende de `gh` ou `glab`.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TIPOS_DE_FORJA = void 0;
|
|
8
|
+
/** Os tipos de forja que o registro conhece, na ordem em que a sondagem os tenta. Sem import: o manifesto o le. */
|
|
9
|
+
exports.TIPOS_DE_FORJA = ['github', 'gitlab'];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hostComPorta = exports.HOST_DO_REMOTO = void 0;
|
|
4
|
+
exports.lerHostDoRemoto = lerHostDoRemoto;
|
|
5
|
+
exports.lerEnderecoDoRemoto = lerEnderecoDoRemoto;
|
|
6
|
+
/** Um parser só para as três formas de URL, com porta e subgrupos. */
|
|
7
|
+
/** O host que o parser aceita: minusculas, rotulos sem hifen na ponta (nunca comeca por `-`). */
|
|
8
|
+
exports.HOST_DO_REMOTO = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/;
|
|
9
|
+
const HOST = exports.HOST_DO_REMOTO;
|
|
10
|
+
const SEGMENTO = /^[A-Za-z0-9_.-]+$/;
|
|
11
|
+
function caminhoValido(bruto) {
|
|
12
|
+
const c = bruto.replace(/^\/+/, '').replace(/\/+$/, '').replace(/\.git$/, '');
|
|
13
|
+
const partes = c.split('/');
|
|
14
|
+
return partes.length >= 2 && partes.every((p) => SEGMENTO.test(p) && p !== '.' && p !== '..') ? partes.join('/') : null;
|
|
15
|
+
}
|
|
16
|
+
/** Protocolo, host e porta de uma URL de remoto (https, http, ssh, git ou scp), com o caminho sem validar. */
|
|
17
|
+
function lerHostDoRemoto(url) {
|
|
18
|
+
const t = url.trim();
|
|
19
|
+
const esquema = /^(https?|ssh|git|git\+ssh|ssh\+git):\/\/(?:[^@/]*@)?([^/:?#@]+)(?::(\d+))?\/([^?#\s]+)$/i.exec(t);
|
|
20
|
+
if (esquema) {
|
|
21
|
+
const host = esquema[2].toLowerCase();
|
|
22
|
+
if (!HOST.test(host))
|
|
23
|
+
return null;
|
|
24
|
+
const p = esquema[1].toLowerCase();
|
|
25
|
+
const protocolo = p === 'https' ? 'https' : p === 'http' ? 'http' : p === 'git' ? 'git' : 'ssh';
|
|
26
|
+
return { protocolo, host, porta: esquema[3] ? Number(esquema[3]) : null, caminhoBruto: esquema[4].replace(/^\/+/, '') };
|
|
27
|
+
}
|
|
28
|
+
const scp = /^(?:[^@\s/:]+@)?([^:\s/@]+):(?!\/\/)([^\s]+)$/.exec(t);
|
|
29
|
+
if (!scp)
|
|
30
|
+
return null;
|
|
31
|
+
const host = scp[1].toLowerCase();
|
|
32
|
+
return HOST.test(host) ? { protocolo: 'scp', host, porta: null, caminhoBruto: scp[2].replace(/^\/+/, '') } : null;
|
|
33
|
+
}
|
|
34
|
+
function lerEnderecoDoRemoto(url) {
|
|
35
|
+
const lido = lerHostDoRemoto(url);
|
|
36
|
+
const caminho = lido ? caminhoValido(lido.caminhoBruto) : null;
|
|
37
|
+
if (!lido || !caminho || (lido.porta !== null && (lido.porta < 1 || lido.porta > 65535)))
|
|
38
|
+
return null;
|
|
39
|
+
return { protocolo: lido.protocolo, host: lido.host, porta: lido.porta, caminho };
|
|
40
|
+
}
|
|
41
|
+
/** `host` ou `host:porta`, a forma que `--hostname` do `gh` e do `glab` aceita. */
|
|
42
|
+
const hostComPorta = (e) => (e.porta ? `${e.host}:${e.porta}` : e.host);
|
|
43
|
+
exports.hostComPorta = hostComPorta;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.estadoDoCheck = estadoDoCheck;
|
|
4
|
+
/** Os estados de commit status (GitHub e GitLab) e de job (GitLab) que reprovam: falha, erro e cancelamento. */
|
|
5
|
+
const VERMELHOS = new Set(['failure', 'error', 'failed', 'canceled', 'cancelled', 'canceling']);
|
|
6
|
+
/** O job que espera uma pessoa (`manual`) ou que a pipeline pulou (`skipped`): nao e verde para o gate. */
|
|
7
|
+
const BLOQUEADOS = new Set(['manual', 'skipped']);
|
|
8
|
+
/**
|
|
9
|
+
* O estado de um check, igual para o gate e para o pulse. O que cada um exige e dele. O check-run (GitHub) decide pela
|
|
10
|
+
* conclusao; o commit status (GitHub e GitLab) e o job de pipeline (GitLab) decidem pelo estado: `success` e verde,
|
|
11
|
+
* falha, erro e cancelamento sao vermelhos, `manual` e `skipped` sao bloqueados, e o resto (em fila, rodando,
|
|
12
|
+
* pendente, criado, aguardando recurso, preparando, agendado) e pendente.
|
|
13
|
+
*/
|
|
14
|
+
function estadoDoCheck(fonte, status, conclusao) {
|
|
15
|
+
const s = status.toLowerCase();
|
|
16
|
+
if (fonte !== 'check-run')
|
|
17
|
+
return s === 'success' ? 'verde' : VERMELHOS.has(s) ? 'vermelho' : BLOQUEADOS.has(s) ? 'bloqueado' : 'pendente';
|
|
18
|
+
if (s !== 'completed')
|
|
19
|
+
return 'pendente';
|
|
20
|
+
const c = (conclusao ?? '').toLowerCase();
|
|
21
|
+
return c === 'success' ? 'verde' : c === 'neutral' || c === 'skipped' ? 'bloqueado' : 'vermelho';
|
|
22
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ambienteReduzido = ambienteReduzido;
|
|
37
|
+
exports.rodarCli = rodarCli;
|
|
38
|
+
/**
|
|
39
|
+
* O unico ponto que roda a CLI da forja. Sem shell e sem token: a CLI usa a autenticacao que ja tem. Cada consumidor
|
|
40
|
+
* diz o prazo, o teto de saida e o ambiente; a CI e a entrega externa usam 32 MiB, como a leitura da forja, e o gh
|
|
41
|
+
* e achado pelo `acharBinario` salvo nos consumidores que pedem `procurarBinario: false`.
|
|
42
|
+
*/
|
|
43
|
+
const node_child_process_1 = require("node:child_process");
|
|
44
|
+
const path = __importStar(require("node:path"));
|
|
45
|
+
const rede_forja_1 = require("../rede-forja");
|
|
46
|
+
/** O que a CLI da forja le do ambiente: o resto (chaves de outros servicos, `NODE_OPTIONS`) nao chega a ela. */
|
|
47
|
+
const VARIAVEIS_DA_CLI = new Set(['PATH', 'HOME', 'USER', 'LOGNAME', 'LANG', 'LC_ALL', 'LC_MESSAGES', 'TMPDIR', 'XDG_CONFIG_HOME',
|
|
48
|
+
'XDG_DATA_HOME', 'XDG_STATE_HOME', 'XDG_CACHE_HOME', 'XDG_RUNTIME_DIR', 'DBUS_SESSION_BUS_ADDRESS', 'SSL_CERT_FILE', 'SSL_CERT_DIR',
|
|
49
|
+
'HTTPS_PROXY', 'HTTP_PROXY', 'NO_PROXY', 'https_proxy', 'http_proxy', 'no_proxy', 'ORK_BINARIOS_EXTRA', 'NO_COLOR']);
|
|
50
|
+
const PREFIXOS_DA_CLI = ['GH_', 'GLAB_', 'GITLAB_', 'GITHUB_'];
|
|
51
|
+
/** O ambiente reduzido: os tokens que a CLI le do ambiente passam sem o `ork` le-los. */
|
|
52
|
+
function ambienteReduzido(env) {
|
|
53
|
+
const saida = {};
|
|
54
|
+
for (const [nome, valor] of Object.entries(env)) {
|
|
55
|
+
if (valor !== undefined && (VARIAVEIS_DA_CLI.has(nome) || PREFIXOS_DA_CLI.some((p) => nome.startsWith(p))))
|
|
56
|
+
saida[nome] = valor;
|
|
57
|
+
}
|
|
58
|
+
return saida;
|
|
59
|
+
}
|
|
60
|
+
function rodarCli(c) {
|
|
61
|
+
const env = { ...(c.base ?? (c.reduzido ? ambienteReduzido(process.env) : process.env)), ...(c.acrescentar ?? {}) };
|
|
62
|
+
for (const nome of c.apagar ?? [])
|
|
63
|
+
delete env[nome];
|
|
64
|
+
if (c.binario !== undefined && !path.isAbsolute(c.binario)) {
|
|
65
|
+
return { status: null, stdout: '', stderr: '', sinal: null, erro: 'EINVAL', mensagemDoErro: 'binario sem caminho absoluto' };
|
|
66
|
+
}
|
|
67
|
+
const exe = c.binario ?? (c.procurarBinario === false ? null : (0, rede_forja_1.acharBinario)(c.cmd, { env })) ?? c.cmd;
|
|
68
|
+
const r = (0, node_child_process_1.spawnSync)(exe, [...c.args], {
|
|
69
|
+
cwd: c.cwd, input: c.entrada, encoding: 'utf8', timeout: c.prazoMs, maxBuffer: c.maxBuffer, env,
|
|
70
|
+
});
|
|
71
|
+
return { status: r.status, stdout: (r.stdout ?? '').toString(), stderr: (r.stderr ?? '').toString(), sinal: r.signal ?? null,
|
|
72
|
+
...(r.error ? { erro: r.error.code ?? r.error.message, mensagemDoErro: r.error.message } : {}) };
|
|
73
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checksNoCommitGithub = checksNoCommitGithub;
|
|
4
|
+
exports.estadoDeCiGithub = estadoDeCiGithub;
|
|
5
|
+
/** Uma pagina tem no maximo 100 itens; 10 paginas (1000 check-runs) e o teto da leitura. */
|
|
6
|
+
const POR_PAGINA = 100;
|
|
7
|
+
const MAX_PAGINAS = 10;
|
|
8
|
+
function chamar(e, caminho) {
|
|
9
|
+
const r = e.executor({ repository: e.repository, sha: e.sha, context: e.context, host: e.host, caminho });
|
|
10
|
+
// Sem trim aqui: quem formata o detalhe (ci.ts) apara e corta, como sempre fez.
|
|
11
|
+
if (!r.ok)
|
|
12
|
+
return { ok: false, erro: { codigo: 'forja.indisponivel', detalhe: r.stderr || r.stdout } };
|
|
13
|
+
try {
|
|
14
|
+
return { ok: true, valor: JSON.parse(r.stdout) };
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return { ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe: '' } };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const invalida = (detalhe = '') => ({ ok: false, erro: { codigo: 'forja.resposta-invalida', detalhe } });
|
|
21
|
+
/**
|
|
22
|
+
* Le as paginas 1..10 ate uma pagina curta. `itens` extrai a lista da resposta (`null`: fora do formato). Passou do
|
|
23
|
+
* teto sem pagina curta: `forja.resposta-invalida` com detalhe `incompleto`.
|
|
24
|
+
*/
|
|
25
|
+
function paginar(e, caminho, itens) {
|
|
26
|
+
const todos = [];
|
|
27
|
+
for (let pagina = 1; pagina <= MAX_PAGINAS; pagina++) {
|
|
28
|
+
const lido = chamar(e, caminho(pagina));
|
|
29
|
+
if (!lido.ok)
|
|
30
|
+
return lido;
|
|
31
|
+
const lista = itens(lido.valor);
|
|
32
|
+
if (!lista)
|
|
33
|
+
return invalida();
|
|
34
|
+
todos.push(...lista);
|
|
35
|
+
if (lista.length < POR_PAGINA)
|
|
36
|
+
return { ok: true, valor: todos };
|
|
37
|
+
}
|
|
38
|
+
return invalida('incompleto');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Os check-runs (paginados, filtrados por nome no servidor e de novo aqui) e os commit statuses (paginados, os mais
|
|
42
|
+
* novos primeiro) com o nome `context` no commit. Resposta fora do formato, de qualquer das duas chamadas, e
|
|
43
|
+
* `forja.resposta-invalida`; lista que passa do teto de paginas tambem, com detalhe `incompleto`: nunca vira ausente.
|
|
44
|
+
*/
|
|
45
|
+
function checksNoCommitGithub(e) {
|
|
46
|
+
const base = `repos/${e.repository}/commits/${e.sha}`;
|
|
47
|
+
// A lista so termina numa pagina curta. O `total_count` nao encerra a leitura (um valor baixo cortaria a lista
|
|
48
|
+
// cedo); ele so confere: lista que acabou antes do total declarado esta incompleta. Mais itens que o total nao e
|
|
49
|
+
// erro (um run novo entre duas paginas).
|
|
50
|
+
let total = null;
|
|
51
|
+
const lidosRuns = paginar(e, (pagina) => `${base}/check-runs?check_name=${encodeURIComponent(e.context)}&filter=all&per_page=${POR_PAGINA}&page=${pagina}`, (valor) => {
|
|
52
|
+
const payload = valor;
|
|
53
|
+
if (!payload || typeof payload !== 'object' || !Array.isArray(payload.check_runs))
|
|
54
|
+
return null;
|
|
55
|
+
if (typeof payload.total_count === 'number')
|
|
56
|
+
total = Math.max(total ?? 0, payload.total_count);
|
|
57
|
+
return payload.check_runs;
|
|
58
|
+
});
|
|
59
|
+
if (!lidosRuns.ok)
|
|
60
|
+
return lidosRuns;
|
|
61
|
+
if (total !== null && lidosRuns.valor.length < total)
|
|
62
|
+
return invalida('incompleto');
|
|
63
|
+
const runs = lidosRuns.valor;
|
|
64
|
+
// O GitHub lista toda transicao de todo contexto: um vermelho do `ork-verify` pode estar alem da primeira pagina.
|
|
65
|
+
const lidosStatuses = paginar(e, (pagina) => `${base}/statuses?per_page=${POR_PAGINA}&page=${pagina}`, (valor) => (Array.isArray(valor) ? valor : null));
|
|
66
|
+
if (!lidosStatuses.ok)
|
|
67
|
+
return lidosStatuses;
|
|
68
|
+
const statuses = lidosStatuses.valor;
|
|
69
|
+
const valor = [
|
|
70
|
+
...runs.filter((c) => c && c.name === e.context).map((c, i) => ({
|
|
71
|
+
nome: c.name, fonte: 'check-run', produtor: c.app?.slug ?? null, status: c.status ?? 'unknown',
|
|
72
|
+
conclusao: c.conclusion ?? null, url: c.html_url ?? null, concluidoEm: c.completed_at ?? null,
|
|
73
|
+
ordem: Number.isSafeInteger(c.id) ? c.id : i,
|
|
74
|
+
})),
|
|
75
|
+
// Os statuses vem do mais novo para o mais velho: sem id, a ordem de reserva decresce com a posicao.
|
|
76
|
+
...statuses.filter((s) => s && s.context === e.context).map((s, i) => ({
|
|
77
|
+
nome: s.context, fonte: 'commit-status', produtor: s.creator?.login ?? null, status: s.state ?? 'unknown',
|
|
78
|
+
conclusao: null, url: s.target_url ?? null, concluidoEm: s.updated_at ?? null,
|
|
79
|
+
ordem: Number.isSafeInteger(s.id) ? s.id : -i,
|
|
80
|
+
})),
|
|
81
|
+
];
|
|
82
|
+
return { ok: true, valor };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A mesma leitura pela API da forja ja resolvida: os check-runs e os statuses do commit, pelo chamador em vez do
|
|
86
|
+
* `ExecutorCi`. O GitHub nao testa commit temporario fora do lido: `mescladoSemVinculo` e sempre falso.
|
|
87
|
+
*/
|
|
88
|
+
function estadoDeCiGithub(e) {
|
|
89
|
+
const executor = (input) => {
|
|
90
|
+
const r = e.api({ metodo: 'GET', caminho: input.caminho ?? `repos/${input.repository}/commits/${input.sha}/check-runs` });
|
|
91
|
+
return r.ok ? { ok: true, code: 0, stdout: JSON.stringify(r.valor.corpo), stderr: '' } : { ok: false, code: 1, stdout: '', stderr: r.erro.detalhe };
|
|
92
|
+
};
|
|
93
|
+
const lido = checksNoCommitGithub({ repository: e.repo, sha: e.sha, context: e.context, executor });
|
|
94
|
+
return lido.ok ? { ok: true, valor: { checks: lido.valor, mescladoSemVinculo: false } } : lido;
|
|
95
|
+
}
|