diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d1d4d8b..646c8cd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -226,6 +226,7 @@ jobs: set -euo pipefail # 版と dist-tag が一致するまで待つ(npm の registry は公開の直後に古い応答を返すことがある)。 # 404 の JSON・JSON でない出力では抜けない。待つのは経過時間で、1 回の npm view にも上限を付ける + # trustedPublisher だけが欠けるときは、同じ待ちの予算の中で間隔を置いて取り直す(公開の直後は古い応答が返る) [ -n "${VERSION}" ] || { echo "::error::VERSION が空(verify job の出力を確認)"; exit 1; } JUDGE=' let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{ @@ -238,12 +239,13 @@ jobs: const prov=ok&&!!(p.dist&&p.dist.attestations&&p.dist.attestations.provenance); let t=null; try{t=JSON.parse(process.env.TP_JSON||"")}catch(e){t=null} const tp=!!t&&typeof t==="object"&&!Array.isArray(t)&&!t.error&&typeof t.id==="string"&&t.id!==""; - console.log(`- registry: version=${ok?p.version:"(応答なし)"} dist-tags.${tag}=${tagOk} provenance=${prov} trustedPublisher=${tp}`); const errs=[]; if(!ver)errs.push(`${want} が registry で見えない`); if(!tagOk)errs.push(`dist-tag ${tag} が ${want} を指していない`); if(!prov)errs.push("provenance が付いていない"); if(!tp)errs.push("trustedPublisher が付いていない"); + if(errs.length===1&&!tp&&process.env.TP_RETRY==="1"){process.exit(2)} + console.log(`- registry: version=${ok?p.version:"(応答なし)"} dist-tags.${tag}=${tagOk} provenance=${prov} trustedPublisher=${tp}`); if(errs.length){for(const m of errs)console.log(`::error::${m}`);console.log("::error::公開は済んだが照合に落ちた(取り消しはできない)。後続の公開を止める");process.exit(1)} })' START=${SECONDS} @@ -261,10 +263,25 @@ jobs: if [ "${ELAPSED}" -ge "${NEXT_NOTE}" ]; then echo "まだ見えない(経過 ${ELAPSED} 秒)"; NEXT_NOTE=$(( NEXT_NOTE + 60 )); fi sleep "${CONFIRM_INTERVAL_SECONDS}" done - TP=$(timeout "${CONFIRM_VIEW_TIMEOUT_SECONDS}" npm view "${NAME}@${VERSION}" _npmUser.trustedPublisher --json 2>/dev/null || true) - if ! printf '%s' "${J}" | FINAL=1 TP_JSON="${TP}" node -e "${JUDGE}" | tee -a "$GITHUB_STEP_SUMMARY"; then + TP_TRIES=0 + while :; do + TP_TRIES=$(( TP_TRIES + 1 )) + TP=$(timeout "${CONFIRM_VIEW_TIMEOUT_SECONDS}" npm view "${NAME}@${VERSION}" _npmUser.trustedPublisher --json 2>/dev/null || true) + ELAPSED=$(( SECONDS - START )) + RETRY=1 + if [ "${TIMED_OUT}" = 1 ] || [ "${ELAPSED}" -ge "${CONFIRM_WAIT_SECONDS}" ] || [ "${TP_TRIES}" -ge "${MAX_TRIES}" ]; then RETRY=0; fi + RC=0 + printf '%s' "${J}" | FINAL=1 TP_RETRY="${RETRY}" TP_JSON="${TP}" node -e "${JUDGE}" | tee -a "$GITHUB_STEP_SUMMARY" || RC=$? + if [ "${RC}" = 0 ]; then break; fi + if [ "${RC}" = 2 ]; then + echo "trustedPublisher がまだ見えない(${TP_TRIES} 回目・経過 ${ELAPSED} 秒)。取り直す" + sleep "${CONFIRM_INTERVAL_SECONDS}" + continue + fi if [ "${TIMED_OUT}" = 1 ]; then echo "::error::registry の反映待ちが上限(${CONFIRM_WAIT_SECONDS} 秒)に達した。公開は済んでいる。registry の反映を後から照合する" | tee -a "$GITHUB_STEP_SUMMARY" + elif [ "${TP_TRIES}" -gt 1 ]; then + echo "::error::trustedPublisher の反映を ${TP_TRIES} 回取り直したが見えない(待ちの上限 ${CONFIRM_WAIT_SECONDS} 秒)。公開は済んでいる。registry の反映を後から照合する" | tee -a "$GITHUB_STEP_SUMMARY" fi exit 1 - fi + done