Skip to content

saga-continue stage=otzaria-published correlation=sefaria:33860162971:1:2026-09-04_12-50-33860162971-1:55560ab01678fdc30eed26f7da38ac70ad6d0e7a6de36ce17963c90aa9e66827 #37

saga-continue stage=otzaria-published correlation=sefaria:33860162971:1:2026-09-04_12-50-33860162971-1:55560ab01678fdc30eed26f7da38ac70ad6d0e7a6de36ce17963c90aa9e66827

saga-continue stage=otzaria-published correlation=sefaria:33860162971:1:2026-09-04_12-50-33860162971-1:55560ab01678fdc30eed26f7da38ac70ad6d0e7a6de36ce17963c90aa9e66827 #37

Workflow file for this run

name: Continue immutable weekly saga
run-name: saga-continue stage=${{ github.event.action || inputs.stage }} correlation=${{ github.event.client_payload.correlation_id || inputs.correlation_id }}
on:
repository_dispatch:
types: [otzaria-published, seforim-published]
workflow_dispatch:
inputs:
stage:
required: true
type: choice
options: [otzaria-published, seforim-published]
correlation_id:
required: true
type: string
saga_run_id:
required: true
type: string
saga_run_attempt:
required: true
type: string
child_run_id:
required: true
type: string
permissions:
contents: read
actions: read
jobs:
resolve:
name: Resolve untrusted callback to canonical saga identity
runs-on: ubuntu-latest
timeout-minutes: 20
outputs:
stage: ${{ steps.resolve.outputs.stage }}
correlation_id: ${{ steps.state.outputs.correlation_id }}
correlation_sha256: ${{ steps.state.outputs.correlation_sha256 }}
saga_run_id: ${{ steps.state.outputs.saga_run_id }}
saga_run_attempt: ${{ steps.state.outputs.saga_run_attempt }}
expected_links_commit: ${{ steps.state.outputs.expected_links_commit }}
seforim_tool_commit: ${{ steps.state.outputs.seforim_tool_commit }}
sefaria_tag: ${{ steps.state.outputs.sefaria_tag }}
sefaria_release_metadata_sha256: ${{ steps.state.outputs.sefaria_release_metadata_sha256 }}
sefaria_archive_sha256: ${{ steps.state.outputs.sefaria_archive_sha256 }}
fordb_tag: ${{ steps.state.outputs.fordb_tag }}
fordb_archive_sha256: ${{ steps.state.outputs.fordb_archive_sha256 }}
fordb_provenance_sha256: ${{ steps.state.outputs.fordb_provenance_sha256 }}
child_run_id: ${{ steps.resolve.outputs.child_run_id }}
child_run_attempt: ${{ steps.resolve.outputs.child_run_attempt }}
env:
GH_TOKEN: ${{ secrets.PIPELINE_TOKEN }}
REQUEST_STAGE: ${{ github.event_name == 'repository_dispatch' && github.event.action || inputs.stage }}
REQUEST_CORRELATION: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.correlation_id || inputs.correlation_id }}
REQUEST_SAGA_RUN_ID: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.saga_run_id || inputs.saga_run_id }}
REQUEST_SAGA_RUN_ATTEMPT: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.saga_run_attempt || inputs.saga_run_attempt }}
REQUEST_CHILD_RUN_ID: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.child_run_id || inputs.child_run_id }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
sparse-checkout: |
.github/scripts
sparse-checkout-cone-mode: true
persist-credentials: false
- name: Download and validate the original signed saga state
id: state
shell: bash
run: |
set -euo pipefail
case "$REQUEST_STAGE" in otzaria-published|seforim-published) ;; *) exit 2;; esac
[[ "$REQUEST_SAGA_RUN_ID" =~ ^[1-9][0-9]*$ ]]
[[ "$REQUEST_SAGA_RUN_ATTEMPT" =~ ^[1-9][0-9]*$ ]]
[[ "$REQUEST_CHILD_RUN_ID" =~ ^[1-9][0-9]*$ ]]
[[ "$REQUEST_CORRELATION" =~ ^sefaria:[1-9][0-9]*:[1-9][0-9]*:[A-Za-z0-9._-]+:[0-9a-f]{64}$ ]]
correlation_sha="$(printf '%s' "$REQUEST_CORRELATION" | sha256sum | cut -d' ' -f1)"
rm -rf saga-state
gh release download "saga-state-$correlation_sha-attempt-$REQUEST_SAGA_RUN_ATTEMPT" \
-R Otzaria/otzaria-library -p saga-state.json -p saga-state.sha256 -D saga-state
python3 .github/scripts/saga_contract.py --directory saga-state \
--expected-run-id "$REQUEST_SAGA_RUN_ID" --expected-correlation "$REQUEST_CORRELATION" \
--expected-run-attempt "$REQUEST_SAGA_RUN_ATTEMPT" \
--github-output "$GITHUB_OUTPUT"
gh api "repos/Otzaria/otzaria-library/actions/runs/$REQUEST_SAGA_RUN_ID" > saga-run.json
jq -e --arg title "sync-manual-links correlation=$REQUEST_CORRELATION" \
--argjson attempt "$REQUEST_SAGA_RUN_ATTEMPT" \
'.event=="workflow_dispatch" and .display_title==$title and .run_attempt==$attempt and
.status=="completed" and .conclusion=="success"' \
saga-run.json >/dev/null
- name: Verify callback child against GitHub, never the payload
id: resolve
shell: bash
run: |
set -euo pipefail
expected_commit="$(jq -r .expected_links_commit saga-state/saga-state.json)"
tool_commit="$(jq -r .seforim_tool_commit saga-state/saga-state.json)"
case "$REQUEST_STAGE" in
otzaria-published)
repo=Otzaria/otzaria-library
title="update-library mode=links_sync_mode correlation=$REQUEST_CORRELATION"
expected_head="*"
stage=s1 ;;
seforim-published)
repo=Otzaria/SeforimLibrary
title="manual-generate-release correlation=$REQUEST_CORRELATION"
# The workflow control plane may advance after the immutable
# payload commit was selected. The signed result below still
# has to name tool_commit exactly; run metadata only proves the
# workflow revision is a descendant, never an unrelated tree.
expected_head="*"
stage=s2 ;;
esac
gh api "repos/$repo/actions/runs/$REQUEST_CHILD_RUN_ID" > child-run.json
jq -e --arg title "$title" --arg head "$expected_head" \
'.event=="workflow_dispatch" and .display_title==$title and ($head=="*" or .head_sha==$head) and
.status=="completed" and .conclusion=="success" and
(.run_attempt|type)=="number" and .run_attempt>=1' child-run.json >/dev/null
if [ "$REQUEST_STAGE" = otzaria-published ]; then
child_head="$(jq -r .head_sha child-run.json)"
relation="$(gh api "repos/Otzaria/otzaria-library/compare/$expected_commit...$child_head" --jq .status)"
case "$relation" in identical|ahead) ;; *) echo "::error::Otzaria child workflow head does not descend from the saga commit"; exit 1;; esac
else
child_head="$(jq -r .head_sha child-run.json)"
relation="$(gh api "repos/Otzaria/SeforimLibrary/compare/$tool_commit...$child_head" --jq .status)"
case "$relation" in identical|ahead) ;; *) echo "::error::Seforim control head does not descend from the pinned payload commit"; exit 1;; esac
fi
echo "stage=$stage" >> "$GITHUB_OUTPUT"
echo "child_run_id=$REQUEST_CHILD_RUN_ID" >> "$GITHUB_OUTPUT"
echo "child_run_attempt=$(jq -r .run_attempt child-run.json)" >> "$GITHUB_OUTPUT"
continue:
name: Mutate only under canonical correlation mutex
needs: resolve
runs-on: ubuntu-latest
timeout-minutes: 45
concurrency:
group: saga-${{ needs.resolve.outputs.correlation_sha256 }}-${{ needs.resolve.outputs.stage }}
cancel-in-progress: false
queue: max
env:
GH_TOKEN: ${{ secrets.PIPELINE_TOKEN }}
STAGE: ${{ needs.resolve.outputs.stage }}
CORRELATION_ID: ${{ needs.resolve.outputs.correlation_id }}
CORRELATION_SHA: ${{ needs.resolve.outputs.correlation_sha256 }}
SAGA_RUN_ID: ${{ needs.resolve.outputs.saga_run_id }}
SAGA_RUN_ATTEMPT: ${{ needs.resolve.outputs.saga_run_attempt }}
EXPECTED_COMMIT: ${{ needs.resolve.outputs.expected_links_commit }}
TOOL_SHA: ${{ needs.resolve.outputs.seforim_tool_commit }}
SEFARIA_TAG: ${{ needs.resolve.outputs.sefaria_tag }}
SEFARIA_METADATA_SHA: ${{ needs.resolve.outputs.sefaria_release_metadata_sha256 }}
SEFARIA_ARCHIVE_SHA: ${{ needs.resolve.outputs.sefaria_archive_sha256 }}
PINNED_FORDB_TAG: ${{ needs.resolve.outputs.fordb_tag }}
PINNED_FORDB_SHA: ${{ needs.resolve.outputs.fordb_archive_sha256 }}
PINNED_FORDB_PROVENANCE_SHA: ${{ needs.resolve.outputs.fordb_provenance_sha256 }}
CALLBACK_CHILD_RUN_ID: ${{ needs.resolve.outputs.child_run_id }}
CALLBACK_CHILD_RUN_ATTEMPT: ${{ needs.resolve.outputs.child_run_attempt }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
sparse-checkout: |
.github/scripts
manual_links_sync.json
pipeline_result_contract.py
sparse-checkout-cone-mode: false
persist-credentials: false
- name: Re-check durable stage product inside the correlation mutex
id: stage_gate
shell: bash
run: |
set -euo pipefail
done=false
if [ "$STAGE" = s2 ]; then
title="saga-continue stage=seforim-published correlation=$CORRELATION_ID"
rows="$(TITLE="$title" gh api --paginate -X GET \
"repos/Otzaria/otzaria-library/actions/workflows/saga-continue.yml/runs" -f per_page=100 \
--jq '.workflow_runs[] | select(.display_title==env.TITLE and .status=="completed" and .conclusion=="success") | (.id|tostring)')"
if printf '%s\n' "$rows" | awk -v current="$GITHUB_RUN_ID" 'NF && $0!=current {found=1} END{exit !found}'; then
done=true
echo "S2 already has a successful durable completion; duplicate callback is a no-op."
fi
fi
echo "done=$done" >> "$GITHUB_OUTPUT"
- name: Validate exact Otzaria result and immutable release
id: otzaria
if: needs.resolve.outputs.stage == 's1'
shell: bash
run: |
set -euo pipefail
rm -rf child-result release-check && mkdir child-result release-check
gh release download "pipeline-result-run-$CALLBACK_CHILD_RUN_ID-$CALLBACK_CHILD_RUN_ATTEMPT" \
-R Otzaria/otzaria-library -p pipeline-result.json -p pipeline-result.sha256 -D child-result
python3 pipeline_result_contract.py validate-otzaria-result \
--json child-result/pipeline-result.json --sha256 child-result/pipeline-result.sha256 \
--correlation-id "$CORRELATION_ID" --expected-commit "$EXPECTED_COMMIT" \
--run-id "$CALLBACK_CHILD_RUN_ID" --run-attempt "$CALLBACK_CHILD_RUN_ATTEMPT"
tag="$(jq -r .tag child-result/pipeline-result.json)"
[[ "$(gh api "repos/Otzaria/otzaria-library/git/ref/tags/$tag" --jq .object.sha)" == "$EXPECTED_COMMIT" ]]
gh release download "$tag" -R Otzaria/otzaria-library -p otzaria_release_provenance.json -D release-check
gh release view "$tag" -R Otzaria/otzaria-library --json assets > release-check/remote-assets.json
python3 - <<'PY'
import hashlib
from pathlib import Path
import pipeline_result_contract as contract
result = contract.load_json(Path("child-result/pipeline-result.json"))
provenance = contract.load_json(Path("release-check/otzaria_release_provenance.json"))
contract.validate_provenance(provenance)
expected = {key: result[key] for key in contract.PROVENANCE_KEYS}
expected["correlation_id"] = result["release_correlation_id"]
if provenance != expected:
raise SystemExit("remote Otzaria provenance differs from exact child result")
prov_path=Path("release-check/otzaria_release_provenance.json")
if hashlib.sha256(prov_path.read_bytes()).hexdigest()!=result["release_provenance_sha256"]:
raise SystemExit("remote Otzaria provenance digest differs from child result")
expected_assets={item["name"]:(item["size"],"sha256:"+item["sha256"]) for item in [result["asset"],*result["auxiliary_assets"]]}
expected_assets[prov_path.name]=(prov_path.stat().st_size,"sha256:"+result["release_provenance_sha256"])
remote=contract.load_json(Path("release-check/remote-assets.json"),require_canonical=False)["assets"]
actual={item["name"]:(item["size"],item.get("digest")) for item in remote}
if actual!=expected_assets: raise SystemExit("remote Otzaria asset descriptors differ from exact child result")
PY
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "asset_sha256=$(jq -r .asset.sha256 child-result/pipeline-result.json)" >> "$GITHUB_OUTPUT"
- name: Resolve and verify immutable ForDB pointer
id: fordb
if: needs.resolve.outputs.stage == 's1'
shell: bash
run: |
set -euo pipefail
tag="$PINNED_FORDB_TAG"
sha="$PINNED_FORDB_SHA"
[[ "$tag" == "fordb-sha256-$sha" ]]
[[ "$PINNED_FORDB_PROVENANCE_SHA" =~ ^[0-9a-f]{64}$ ]]
rm -rf fordb-check && mkdir fordb-check
gh release download "$tag" -R Otzaria/otzaria-library \
-p fordb_latest.zip -p fordb_provenance.json -D fordb-check
[[ "$(sha256sum fordb-check/fordb_latest.zip | cut -d' ' -f1)" == "$sha" ]]
[[ "$(sha256sum fordb-check/fordb_provenance.json | cut -d' ' -f1)" == "$PINNED_FORDB_PROVENANCE_SHA" ]]
python3 - <<'PY'
import json,re
from pathlib import Path
def pairs(items):
out={}
for key,value in items:
if key in out: raise SystemExit(f"duplicate provenance key {key}")
out[key]=value
return out
value=json.loads(Path("fordb-check/fordb_provenance.json").read_text(),object_pairs_hook=pairs)
keys={"schema_version","archive","source_commit","validator_tool_sha","validated_library_tag"}
if set(value)!=keys or type(value["schema_version"]) is not int or value["schema_version"]!=1:
raise SystemExit("invalid ForDB provenance schema")
archive=value["archive"]
if set(archive)!={"name","sha256","size"} or archive["name"]!="fordb_latest.zip" or archive["sha256"]!=__import__('os').environ["PINNED_FORDB_SHA"]:
raise SystemExit("ForDB provenance archive mismatch")
if type(archive["size"]) is not int or archive["size"]<1: raise SystemExit("invalid ForDB archive size")
for field in ("source_commit","validator_tool_sha"):
if type(value[field]) is not str or not re.fullmatch(r"[0-9a-f]{40}",value[field]): raise SystemExit(f"invalid {field}")
if type(value["validated_library_tag"]) is not str or not re.fullmatch(r"[A-Za-z0-9._-]{1,100}",value["validated_library_tag"]):
raise SystemExit("invalid validated_library_tag")
Path("fordb-check/source-commit.txt").write_text(value["source_commit"]+"\n")
PY
[[ "$(gh api "repos/Otzaria/otzaria-library/git/ref/tags/$tag" --jq .object.sha)" == "$(cat fordb-check/source-commit.txt)" ]]
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "sha256=$sha" >> "$GITHUB_OUTPUT"
- name: Idempotently dispatch exact pinned Seforim build
if: needs.resolve.outputs.stage == 's1'
env:
OTZARIA_TAG: ${{ steps.otzaria.outputs.tag }}
OTZARIA_ASSET_SHA: ${{ steps.otzaria.outputs.asset_sha256 }}
FORDB_TAG: ${{ steps.fordb.outputs.tag }}
FORDB_ARCHIVE_SHA: ${{ steps.fordb.outputs.sha256 }}
shell: bash
run: |
set -euo pipefail
title="manual-generate-release correlation=$CORRELATION_ID"
tool_ref="$(jq -r .seforim_tool_ref manual_links_sync.json)"
[[ "$tool_ref" =~ ^refs/heads/[A-Za-z0-9._/-]+$ ]]
workflow_ref="${tool_ref#refs/heads/}"
head_sha="$(git ls-remote https://github.com/Otzaria/SeforimLibrary.git "$tool_ref" | awk 'NR==1 {print $1}')"
relation="$(gh api "repos/Otzaria/SeforimLibrary/compare/$TOOL_SHA...$head_sha" --jq .status)"
case "$relation" in identical|ahead) ;;
*) echo "::error::Seforim workflow head does not descend from the pinned payload commit"; exit 1 ;;
esac
set +e
existing="$(FIND_RUN_ATTEMPTS=1 bash .github/scripts/find_exact_workflow_run.sh \
Otzaria/SeforimLibrary manual-generate-release.yml "$title" "$head_sha")"
scan_rc=$?
set -e
if [ "$scan_rc" -eq 0 ]; then
state="$(gh api "repos/Otzaria/SeforimLibrary/actions/runs/$existing" --jq '.status+":"+(.conclusion//"")')"
case "$state" in completed:success|requested:*|waiting:*|pending:*|queued:*|in_progress:*) exit 0;;
*) echo "::error::existing Seforim child $existing is terminal but failed ($state)"; exit 1;; esac
fi
[ "$scan_rc" -eq 1 ] || exit "$scan_rc"
# Submit exactly once. A failed response is ambiguous, so let this
# continuation fail; reconcile-sagas will inspect the exact child title
# before rerunning this databaseId. No blind duplicate dispatch.
gh workflow run manual-generate-release.yml -R Otzaria/SeforimLibrary --ref "$workflow_ref" \
-f source_commit="$TOOL_SHA" -f sefaria_tag="$SEFARIA_TAG" \
-f sefaria_release_metadata_sha256="$SEFARIA_METADATA_SHA" \
-f sefaria_archive_sha256="$SEFARIA_ARCHIVE_SHA" \
-f otzaria_tag="$OTZARIA_TAG" -f otzaria_asset_sha256="$OTZARIA_ASSET_SHA" \
-f fordb_tag="$FORDB_TAG" -f fordb_archive_sha256="$FORDB_ARCHIVE_SHA" \
-f expected_links_commit="$EXPECTED_COMMIT" -f otzaria_target_commit="$EXPECTED_COMMIT" \
-f correlation_id="$CORRELATION_ID" -f saga_run_id="$SAGA_RUN_ID" \
-f saga_run_attempt="$SAGA_RUN_ATTEMPT"
echo "Seforim child submission accepted; S1 complete."
- name: Re-download authoritative Otzaria result for S2
id: s2_otzaria
if: needs.resolve.outputs.stage == 's2' && steps.stage_gate.outputs.done != 'true'
shell: bash
run: |
set -euo pipefail
title="update-library mode=links_sync_mode correlation=$CORRELATION_ID"
rows="$(TITLE="$title" gh api --paginate -X GET \
"repos/Otzaria/otzaria-library/actions/workflows/update-library.yml/runs" \
-f event=workflow_dispatch -f per_page=100 \
--jq '.workflow_runs[] | select(.display_title==env.TITLE and .status=="completed" and .conclusion=="success") | (.id|tostring)')"
matches="$(printf '%s\n' "$rows" | awk 'NF && !seen[$0]++')"
count="$(printf '%s\n' "$matches" | awk 'NF' | wc -l | tr -d ' ')"
if [ "$count" -ne 1 ]; then
echo "::error::Expected exactly one successful Otzaria child for the canonical correlation; found $count."
exit 1
fi
run_id="$matches"
attempt="$(gh api "repos/Otzaria/otzaria-library/actions/runs/$run_id" --jq .run_attempt)"
child_head="$(gh api "repos/Otzaria/otzaria-library/actions/runs/$run_id" --jq .head_sha)"
relation="$(gh api "repos/Otzaria/otzaria-library/compare/$EXPECTED_COMMIT...$child_head" --jq .status)"
case "$relation" in identical|ahead) ;;
*) echo "::error::Successful Otzaria child workflow head does not descend from the saga commit"; exit 1 ;;
esac
rm -rf child-result && mkdir child-result
gh release download "pipeline-result-run-$run_id-$attempt" \
-R Otzaria/otzaria-library -p pipeline-result.json -p pipeline-result.sha256 -D child-result
python3 pipeline_result_contract.py validate-otzaria-result \
--json child-result/pipeline-result.json --sha256 child-result/pipeline-result.sha256 \
--correlation-id "$CORRELATION_ID" --expected-commit "$EXPECTED_COMMIT" \
--run-id "$run_id" --run-attempt "$attempt"
- name: Validate Seforim result and every remote release byte
if: needs.resolve.outputs.stage == 's2' && steps.stage_gate.outputs.done != 'true'
shell: bash
run: |
set -euo pipefail
rm -rf build-result build-release-check && mkdir build-result build-release-check
gh release download "pipeline-result-run-$CALLBACK_CHILD_RUN_ID-$CALLBACK_CHILD_RUN_ATTEMPT" \
-R Otzaria/SeforimLibrary -p pipeline-result.json -p pipeline-result.sha256 -D build-result
FORDB_TAG="$(jq -r .fordb_tag build-result/pipeline-result.json)"
FORDB_SHA="$(jq -r .fordb_archive_sha256 build-result/pipeline-result.json)"
[[ "$FORDB_TAG" == "$PINNED_FORDB_TAG" && "$FORDB_SHA" == "$PINNED_FORDB_SHA" ]]
python3 pipeline_result_contract.py validate-seforim-result \
--json build-result/pipeline-result.json --sha256 build-result/pipeline-result.sha256 \
--correlation-id "$CORRELATION_ID" --run-id "$CALLBACK_CHILD_RUN_ID" \
--run-attempt "$CALLBACK_CHILD_RUN_ATTEMPT" --source-commit "$TOOL_SHA" \
--sefaria-tag "$SEFARIA_TAG" --sefaria-release-metadata-sha256 "$SEFARIA_METADATA_SHA" \
--sefaria-archive-sha256 "$SEFARIA_ARCHIVE_SHA" \
--otzaria-tag "$(jq -r .tag child-result/pipeline-result.json)" \
--otzaria-asset-sha256 "$(jq -r .asset.sha256 child-result/pipeline-result.json)" \
--fordb-tag "$FORDB_TAG" --fordb-archive-sha256 "$FORDB_SHA" \
--expected-links-commit "$EXPECTED_COMMIT" --otzaria-target-commit "$EXPECTED_COMMIT" \
--config-sha256 "$(jq -r .config_sha256 child-result/pipeline-result.json)" \
--source-links-tree-sha256 "$(jq -r .source_links_tree_sha256 child-result/pipeline-result.json)" \
--packaged-links-tree-sha256 "$(jq -r .packaged_links_tree_sha256 child-result/pipeline-result.json)" \
--lineage-sha256 "$(jq -r .lineage_sha256 child-result/pipeline-result.json)"
release_tag="$(jq -r .release_tag build-result/pipeline-result.json)"
[[ "$(gh api "repos/Otzaria/SeforimLibrary/git/ref/tags/$release_tag" --jq .object.sha)" == "$TOOL_SHA" ]]
gh release view "$release_tag" -R Otzaria/SeforimLibrary --json assets > build-release-check/remote-assets.json
python3 - <<'PY'
import hashlib, json
from pathlib import Path
result=json.loads(Path("build-result/pipeline-result.json").read_text())
expected={item["name"]:(item["size"],"sha256:"+item["sha256"]) for item in result["assets"]}
remote=json.loads(Path("build-release-check/remote-assets.json").read_text())["assets"]
actual={item["name"]:(item["size"],item.get("digest")) for item in remote}
if actual!=expected: raise SystemExit("remote Seforim release descriptors differ from exact child result")
PY
mkdir saga-complete
jq -cS -n --arg correlation_id "$CORRELATION_ID" --arg correlation_sha256 "$CORRELATION_SHA" \
--argjson saga_run_id "$SAGA_RUN_ID" --argjson seforim_run_id "$CALLBACK_CHILD_RUN_ID" \
--arg release_tag "$release_tag" \
'{schema_version:1,status:"complete",correlation_id:$correlation_id,correlation_sha256:$correlation_sha256,saga_run_id:$saga_run_id,seforim_run_id:$seforim_run_id,release_tag:$release_tag}' \
> saga-complete/saga-complete.json
sha256sum saga-complete/saga-complete.json | cut -d' ' -f1 > saga-complete/saga-complete.sha256
- name: Publish immutable saga completion release
if: needs.resolve.outputs.stage == 's2' && steps.stage_gate.outputs.done != 'true'
run: >-
bash .github/scripts/publish_release_handoff.sh
"saga-complete-${{ needs.resolve.outputs.correlation_sha256 }}-attempt-${GITHUB_RUN_ATTEMPT}"
"Immutable weekly saga completion ${{ needs.resolve.outputs.correlation_sha256 }}:${GITHUB_RUN_ATTEMPT}"
"$GITHUB_SHA" saga-complete/saga-complete.json saga-complete/saga-complete.sha256