mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
feat(ownership): idempotent, packaged snapshot publisher
The self-hosted publish timer has not produced an upload since it was enabled (manifest last updated 2026-07-14, a manual run), and failures were invisible. Make the job safe to run daily and easy to deploy: - publish-ownership-snapshot.sh: skip the upload when the published manifest already has the latest as-of date (pre-check via discover for XLSX sources, post-build check for legacy PDF); --force to override. Always ends with one line: RESULT: published|up-to-date <as-of> or RESULT: FAILED stage=<stage> (exit N). gh release create no longer requires a git checkout. - check-ownership-snapshot-freshness.sh: exit 1 when the published latest_as_of_date is older than --max-age-days (default 40). - flake: packages.ownership-publisher bundles the scripts with a pinned idx (curl-impersonate + mupdf) and jq/gh/sqlite/curl as bin/idx-ownership-publish and bin/idx-ownership-freshness, so hosts need no checkout, nix develop or cargo build at run time. Built in CI. - contrib/systemd + docs: daily 06:00 UTC timer, run semantics table, freshness alarm, packaged usage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017a5Cv5Z1NzdYKgKnTiAF4E
This commit is contained in:
parent
d4ec5015b9
commit
1f6f0ee02e
7 changed files with 237 additions and 44 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -57,6 +57,11 @@ jobs:
|
||||||
- name: Run default app
|
- name: Run default app
|
||||||
run: nix run .#default -- version
|
run: nix run .#default -- version
|
||||||
|
|
||||||
|
- name: Build ownership publisher
|
||||||
|
run: |
|
||||||
|
nix build .#ownership-publisher
|
||||||
|
./result/bin/idx-ownership-publish --help
|
||||||
|
|
||||||
install-script:
|
install-script:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ After=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
WorkingDirectory=/srv/idx-cli
|
|
||||||
Environment=HOME=/var/lib/idx-ownership-snapshot
|
Environment=HOME=/var/lib/idx-ownership-snapshot
|
||||||
EnvironmentFile=/etc/idx-ownership-snapshot.env
|
EnvironmentFile=/etc/idx-ownership-snapshot.env
|
||||||
ExecStart=/bin/sh -lc 'nix develop --command scripts/publish-ownership-snapshot.sh --build --idx-bin ./target/debug/idx --output-dir /var/lib/idx-ownership-snapshot/current --repo 0xrsydn/idx-cli --release-tag ownership-snapshot-current'
|
# Build once with `nix build github:0xrsydn/idx-cli#ownership-publisher -o /opt/idx-ownership-publisher`.
|
||||||
|
# Idempotent: exits 0 with "RESULT: up-to-date" when nothing newer exists.
|
||||||
|
ExecStart=/opt/idx-ownership-publisher/bin/idx-ownership-publish --output-dir /var/lib/idx-ownership-snapshot/current --repo 0xrsydn/idx-cli --release-tag ownership-snapshot-current --history 5
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Run monthly idx ownership snapshot publish job
|
Description=Daily idx ownership snapshot publish check
|
||||||
|
|
||||||
[Timer]
|
[Timer]
|
||||||
OnCalendar=*-*-02 09:00:00
|
# The publisher is idempotent, so a daily run retries automatically when IDX
|
||||||
|
# posts late or a run is blocked; most days end with "RESULT: up-to-date".
|
||||||
|
OnCalendar=*-*-* 06:00:00 UTC
|
||||||
Persistent=true
|
Persistent=true
|
||||||
RandomizedDelaySec=30m
|
RandomizedDelaySec=30m
|
||||||
Unit=idx-ownership-snapshot-publish.service
|
Unit=idx-ownership-snapshot-publish.service
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,44 @@ simple:
|
||||||
No Nix setup is required for end users. Nix is only an implementation detail for
|
No Nix setup is required for end users. Nix is only an implementation detail for
|
||||||
the maintainer host if that host already uses NixOS.
|
the maintainer host if that host already uses NixOS.
|
||||||
|
|
||||||
## Manual Command
|
## Packaged Publisher (recommended)
|
||||||
|
|
||||||
From a checked-out repo with GitHub auth already configured:
|
The flake exposes a self-contained publisher, so the host needs no checkout,
|
||||||
|
`nix develop`, or cargo build at run time:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix build github:0xrsydn/idx-cli#ownership-publisher
|
||||||
|
./result/bin/idx-ownership-publish --output-dir /var/lib/idx/ownership-snapshot/current --history 5
|
||||||
|
./result/bin/idx-ownership-freshness --max-age-days 40
|
||||||
|
```
|
||||||
|
|
||||||
|
`idx-ownership-publish` wraps `scripts/publish-ownership-snapshot.sh` with a
|
||||||
|
pinned `idx` (itself wrapped with curl-impersonate and mupdf) plus jq, gh,
|
||||||
|
sqlite and curl. On NixOS, add this repo as a flake input and run
|
||||||
|
`inputs.idx-cli.packages.${system}.ownership-publisher`; bump the input
|
||||||
|
(`nix flake update idx-cli`) to pick up fixes.
|
||||||
|
|
||||||
|
## Run Semantics
|
||||||
|
|
||||||
|
The publisher is idempotent and prints exactly one final line:
|
||||||
|
|
||||||
|
| Last line | Exit | Meaning |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `RESULT: published <as-of>` | 0 | a newer snapshot was uploaded |
|
||||||
|
| `RESULT: up-to-date <as-of>` | 0 | the published snapshot already has the latest report; nothing uploaded |
|
||||||
|
| `RESULT: FAILED stage=<stage> (exit N)` | N | failed in `check-published`, `discover`, `build-snapshot`, `stage-output`, or `upload` |
|
||||||
|
|
||||||
|
It checks the published manifest first and, for XLSX sources, compares as-of
|
||||||
|
dates before downloading anything, so it is cheap to run **daily**. `--force`
|
||||||
|
uploads regardless.
|
||||||
|
|
||||||
|
`idx-ownership-freshness` is the independent alarm: it exits 1 when the
|
||||||
|
published `latest_as_of_date` is older than `--max-age-days` (default 40). The
|
||||||
|
source is monthly and lands 2-3 days after month end, so 40 days only trips
|
||||||
|
when publishing has actually stopped working. Wire both to an `OnFailure=`
|
||||||
|
notification.
|
||||||
|
|
||||||
|
## Manual Command (from a checkout)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix develop --command scripts/publish-ownership-snapshot.sh \
|
nix develop --command scripts/publish-ownership-snapshot.sh \
|
||||||
|
|
@ -35,47 +70,17 @@ nix develop --command scripts/publish-ownership-snapshot.sh \
|
||||||
--release-tag ownership-snapshot-current
|
--release-tag ownership-snapshot-current
|
||||||
```
|
```
|
||||||
|
|
||||||
That helper:
|
## systemd Units
|
||||||
|
|
||||||
1. optionally builds `idx`
|
Examples: `contrib/systemd/idx-ownership-snapshot-publish.service` and
|
||||||
2. discovers the latest supported IDX/KSEI above-1% report (XLSX on the IDX
|
`contrib/systemd/idx-ownership-snapshot-publish.timer` (daily at 06:00 UTC).
|
||||||
Data Kepemilikan Saham page since the 2026-05-29 report; PDF announcements
|
|
||||||
before that)
|
|
||||||
3. imports it into an isolated temp DB
|
|
||||||
4. emits the SQLite snapshot and manifest
|
|
||||||
5. ensures the stable GitHub release exists
|
|
||||||
6. uploads the manifest and SQLite asset with `--clobber`
|
|
||||||
|
|
||||||
## systemd Service
|
Observed XLSX upload times (HTTP Last-Modified): 2026-06-03,
|
||||||
|
2026-07-02 03:55Z, 2026-08-02 01:50Z, 2026-09-02 03:51Z. With a daily,
|
||||||
|
idempotent run the exact day no longer matters.
|
||||||
|
|
||||||
Example service: [contrib/systemd/idx-ownership-snapshot-publish.service](/Users/rasyidanakbar/Development/myApp/idx-cli/contrib/systemd/idx-ownership-snapshot-publish.service)
|
Pass `--history <n>` to include earlier months so `idx ownership changes`
|
||||||
|
works straight from the synced snapshot (about 2.4 MB per extra month).
|
||||||
Important assumptions:
|
|
||||||
|
|
||||||
- the repo checkout lives at `/srv/idx-cli`
|
|
||||||
- a writable publish directory exists at `/var/lib/idx-ownership-snapshot/current`
|
|
||||||
- `GH_TOKEN` is provided via an env file such as `/etc/idx-ownership-snapshot.env`
|
|
||||||
- the host can run `nix develop`
|
|
||||||
|
|
||||||
## systemd Timer
|
|
||||||
|
|
||||||
Example timer: [contrib/systemd/idx-ownership-snapshot-publish.timer](/Users/rasyidanakbar/Development/myApp/idx-cli/contrib/systemd/idx-ownership-snapshot-publish.timer)
|
|
||||||
|
|
||||||
The sample timer uses:
|
|
||||||
|
|
||||||
- `OnCalendar=*-*-02 09:00:00`
|
|
||||||
- `Persistent=true`
|
|
||||||
- `RandomizedDelaySec=30m`
|
|
||||||
|
|
||||||
That is intentionally conservative. The ownership source is monthly, but the
|
|
||||||
exact publish day can drift. Observed XLSX upload times (HTTP Last-Modified):
|
|
||||||
2026-06-03, 2026-07-02 03:55Z, 2026-08-02 01:50Z, 2026-09-02 03:51Z, so a run
|
|
||||||
on the 2nd can occasionally land before the file exists; the 3rd is safer.
|
|
||||||
Start with an early-month schedule and adjust after observing a few real runs.
|
|
||||||
|
|
||||||
Pass `--history <n>` (for example via `services.idxOwnershipPublish.extraArgs =
|
|
||||||
[ "--history" "5" ];` in `clan-private`) to include earlier months so
|
|
||||||
`idx ownership changes` works straight from the synced snapshot.
|
|
||||||
|
|
||||||
## Clan Integration Later
|
## Clan Integration Later
|
||||||
|
|
||||||
|
|
|
||||||
48
flake.nix
48
flake.nix
|
|
@ -48,14 +48,62 @@
|
||||||
--prefix PATH : "${lib.makeBinPath runtimeDeps}"
|
--prefix PATH : "${lib.makeBinPath runtimeDeps}"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
# Self-contained ownership snapshot publisher for scheduled hosts
|
||||||
|
# (e.g. a NixOS systemd timer): no checkout, `nix develop` or cargo
|
||||||
|
# build at run time. Wraps the repo scripts with a pinned `idx`.
|
||||||
|
publisherTools = with pkgs; [
|
||||||
|
bash
|
||||||
|
coreutils
|
||||||
|
curl
|
||||||
|
gawk
|
||||||
|
gh
|
||||||
|
gnugrep
|
||||||
|
gnused
|
||||||
|
jq
|
||||||
|
sqlite
|
||||||
|
];
|
||||||
|
ownershipPublisher = pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
pname = "idx-ownership-publisher";
|
||||||
|
version = cargoManifest.package.version;
|
||||||
|
src = lib.fileset.toSource {
|
||||||
|
root = ./.;
|
||||||
|
fileset = lib.fileset.unions [
|
||||||
|
./scripts/build-ownership-snapshot.sh
|
||||||
|
./scripts/build-latest-ownership-snapshot.sh
|
||||||
|
./scripts/publish-ownership-snapshot.sh
|
||||||
|
./scripts/check-ownership-snapshot-freshness.sh
|
||||||
|
];
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [ pkgs.makeWrapper ];
|
||||||
|
dontBuild = true;
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p "$out/libexec/idx-ownership" "$out/bin"
|
||||||
|
cp scripts/*.sh "$out/libexec/idx-ownership/"
|
||||||
|
chmod +x "$out"/libexec/idx-ownership/*.sh
|
||||||
|
patchShebangs "$out/libexec/idx-ownership"
|
||||||
|
|
||||||
|
makeWrapper "$out/libexec/idx-ownership/publish-ownership-snapshot.sh" \
|
||||||
|
"$out/bin/idx-ownership-publish" \
|
||||||
|
--prefix PATH : "${lib.makeBinPath ([ idxPackage ] ++ publisherTools)}" \
|
||||||
|
--add-flags "--idx-bin ${idxPackage}/bin/idx"
|
||||||
|
makeWrapper "$out/libexec/idx-ownership/check-ownership-snapshot-freshness.sh" \
|
||||||
|
"$out/bin/idx-ownership-freshness" \
|
||||||
|
--prefix PATH : "${lib.makeBinPath publisherTools}"
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
meta.mainProgram = "idx-ownership-publish";
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages.default = idxPackage;
|
packages.default = idxPackage;
|
||||||
|
packages.ownership-publisher = ownershipPublisher;
|
||||||
apps.default = {
|
apps.default = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${idxPackage}/bin/idx";
|
program = "${idxPackage}/bin/idx";
|
||||||
};
|
};
|
||||||
checks.default = idxPackage;
|
checks.default = idxPackage;
|
||||||
|
checks.ownership-publisher = ownershipPublisher;
|
||||||
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
inputsFrom = [ idxPackage ];
|
inputsFrom = [ idxPackage ];
|
||||||
|
|
|
||||||
62
scripts/check-ownership-snapshot-freshness.sh
Executable file
62
scripts/check-ownership-snapshot-freshness.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Fail when the published ownership snapshot is older than expected, so a
|
||||||
|
# publish job that keeps failing (or keeps finding nothing new) gets noticed.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
Usage: scripts/check-ownership-snapshot-freshness.sh [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--manifest-url <url> Published manifest (default: the ownership-snapshot-current
|
||||||
|
release of 0xrsydn/idx-cli)
|
||||||
|
--max-age-days <n> Allowed age of latest_as_of_date in days (default: 40;
|
||||||
|
the source is monthly and lands 2-3 days after month end)
|
||||||
|
--now <YYYY-MM-DD> Reference date instead of today (for testing)
|
||||||
|
--help Show this help
|
||||||
|
|
||||||
|
Exit status: 0 fresh, 1 stale, 2 usage error, 3 manifest unreadable.
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
MANIFEST_URL="https://github.com/0xrsydn/idx-cli/releases/download/ownership-snapshot-current/ownership-snapshot-manifest.json"
|
||||||
|
MAX_AGE_DAYS="40"
|
||||||
|
NOW="$(date -u +%F)"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--manifest-url) MANIFEST_URL="${2:-}"; shift 2 ;;
|
||||||
|
--max-age-days) MAX_AGE_DAYS="${2:-}"; shift 2 ;;
|
||||||
|
--now) NOW="${2:-}"; shift 2 ;;
|
||||||
|
--help|-h) usage; exit 0 ;;
|
||||||
|
*) echo "unknown argument: $1" >&2; usage >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! [[ "$MAX_AGE_DAYS" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "--max-age-days must be a non-negative integer" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MANIFEST_URL" =~ ^https?:// ]]; then
|
||||||
|
manifest="$(curl --fail --silent --show-error --location --retry 3 "$MANIFEST_URL")" || {
|
||||||
|
echo "FRESHNESS: unreadable manifest $MANIFEST_URL" >&2
|
||||||
|
exit 3
|
||||||
|
}
|
||||||
|
else
|
||||||
|
manifest="$(cat "$MANIFEST_URL")" || exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
as_of="$(jq -r '.snapshot.latest_as_of_date // empty' <<< "$manifest" 2>/dev/null || true)"
|
||||||
|
if [[ -z "$as_of" ]]; then
|
||||||
|
echo "FRESHNESS: manifest has no snapshot.latest_as_of_date" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
age_days=$(( ($(date -u -d "$NOW" +%s) - $(date -u -d "$as_of" +%s)) / 86400 ))
|
||||||
|
if (( age_days > 10#$MAX_AGE_DAYS )); then
|
||||||
|
printf 'FRESHNESS: stale latest_as_of_date=%s age_days=%d max=%s\n' "$as_of" "$age_days" "$MAX_AGE_DAYS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf 'FRESHNESS: ok latest_as_of_date=%s age_days=%d max=%s\n' "$as_of" "$age_days" "$MAX_AGE_DAYS"
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|
@ -9,6 +9,13 @@ Usage: scripts/publish-ownership-snapshot.sh --output-dir <dir> [options]
|
||||||
Build and publish the latest supported IDX/KSEI ownership snapshot to the stable
|
Build and publish the latest supported IDX/KSEI ownership snapshot to the stable
|
||||||
GitHub release used by `idx ownership sync`.
|
GitHub release used by `idx ownership sync`.
|
||||||
|
|
||||||
|
Safe to run daily: unless --force is given, it skips the upload when the
|
||||||
|
published snapshot already has the latest as-of date. The last line is always
|
||||||
|
one of:
|
||||||
|
RESULT: published <as-of>
|
||||||
|
RESULT: up-to-date <as-of>
|
||||||
|
RESULT: FAILED stage=<stage> (exit <code>)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--idx-bin <path> idx binary to use (default: ./target/debug/idx)
|
--idx-bin <path> idx binary to use (default: ./target/debug/idx)
|
||||||
--output-dir <dir> Directory to write the copied snapshot and manifest
|
--output-dir <dir> Directory to write the copied snapshot and manifest
|
||||||
|
|
@ -18,6 +25,7 @@ Options:
|
||||||
(default: ownership-snapshot-current)
|
(default: ownership-snapshot-current)
|
||||||
--history <n> Also include the <n> previous monthly above-1% reports
|
--history <n> Also include the <n> previous monthly above-1% reports
|
||||||
in the snapshot (passed to the builder; default: 0)
|
in the snapshot (passed to the builder; default: 0)
|
||||||
|
--force Upload even if the published snapshot is up to date
|
||||||
--build Run `cargo build` before publishing
|
--build Run `cargo build` before publishing
|
||||||
--keep-workdir Keep the temp workdir created by the builder helper
|
--keep-workdir Keep the temp workdir created by the builder helper
|
||||||
--help Show this help
|
--help Show this help
|
||||||
|
|
@ -31,7 +39,16 @@ RELEASE_TAG="ownership-snapshot-current"
|
||||||
BUILD_FIRST="0"
|
BUILD_FIRST="0"
|
||||||
KEEP_WORKDIR="0"
|
KEEP_WORKDIR="0"
|
||||||
HISTORY="0"
|
HISTORY="0"
|
||||||
|
FORCE="0"
|
||||||
PUBLISH_WORKDIR=""
|
PUBLISH_WORKDIR=""
|
||||||
|
STAGE="arguments"
|
||||||
|
|
||||||
|
on_error() {
|
||||||
|
local status=$?
|
||||||
|
printf 'RESULT: FAILED stage=%s (exit %s)\n' "$STAGE" "$status" >&2
|
||||||
|
exit "$status"
|
||||||
|
}
|
||||||
|
trap on_error ERR
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
@ -55,6 +72,10 @@ while [[ $# -gt 0 ]]; do
|
||||||
HISTORY="${2:-}"
|
HISTORY="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--force)
|
||||||
|
FORCE="1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--build)
|
--build)
|
||||||
BUILD_FIRST="1"
|
BUILD_FIRST="1"
|
||||||
shift
|
shift
|
||||||
|
|
@ -111,6 +132,15 @@ cleanup() {
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Published manifest, or empty when none exists yet.
|
||||||
|
published_manifest() {
|
||||||
|
gh release download "$RELEASE_TAG" \
|
||||||
|
--repo "$REPO_FULL_NAME" \
|
||||||
|
--pattern ownership-snapshot-manifest.json \
|
||||||
|
--output - 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
STAGE="build"
|
||||||
if [[ "$BUILD_FIRST" == "1" ]]; then
|
if [[ "$BUILD_FIRST" == "1" ]]; then
|
||||||
printf 'Building idx...\n'
|
printf 'Building idx...\n'
|
||||||
cargo build
|
cargo build
|
||||||
|
|
@ -122,6 +152,27 @@ if ! "$IDX_BIN" version >/dev/null 2>&1; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
STAGE="check-published"
|
||||||
|
PUBLISHED_MANIFEST="$(published_manifest)"
|
||||||
|
PUBLISHED_AS_OF="$(jq -r '.snapshot.latest_as_of_date // empty' <<< "$PUBLISHED_MANIFEST" 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [[ "$FORCE" != "1" && -n "$PUBLISHED_AS_OF" ]]; then
|
||||||
|
STAGE="discover"
|
||||||
|
# Cheap pre-check: XLSX reports carry their as-of date, so an unchanged
|
||||||
|
# month is detected without downloading or building anything.
|
||||||
|
LATEST_AS_OF="$(
|
||||||
|
"$IDX_BIN" -o json ownership discover --family above1 --limit 1 |
|
||||||
|
jq -r '.[0] | select(.status == "supported") | .as_of_date // empty'
|
||||||
|
)"
|
||||||
|
if [[ -n "$LATEST_AS_OF" && ! "$LATEST_AS_OF" > "$PUBLISHED_AS_OF" ]]; then
|
||||||
|
printf 'Published snapshot %s is current (latest source report: %s).\n' \
|
||||||
|
"$PUBLISHED_AS_OF" "$LATEST_AS_OF"
|
||||||
|
printf 'RESULT: up-to-date %s\n' "$PUBLISHED_AS_OF"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
STAGE="build-snapshot"
|
||||||
build_args=(
|
build_args=(
|
||||||
--idx-bin "$IDX_BIN"
|
--idx-bin "$IDX_BIN"
|
||||||
--output-dir "$PUBLISH_WORKDIR"
|
--output-dir "$PUBLISH_WORKDIR"
|
||||||
|
|
@ -154,6 +205,18 @@ if [[ "${#sqlite_matches[@]}" -ne 1 ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
STAGED_SQLITE_PATH="${sqlite_matches[0]}"
|
STAGED_SQLITE_PATH="${sqlite_matches[0]}"
|
||||||
|
BUILT_AS_OF="$(jq -r '.snapshot.latest_as_of_date' "$STAGED_MANIFEST_PATH")"
|
||||||
|
|
||||||
|
# Post-build check covers legacy PDF sources, whose as-of date is only known
|
||||||
|
# after import.
|
||||||
|
if [[ "$FORCE" != "1" && -n "$PUBLISHED_AS_OF" && ! "$BUILT_AS_OF" > "$PUBLISHED_AS_OF" ]]; then
|
||||||
|
printf 'Built snapshot %s is not newer than published %s; skipping upload.\n' \
|
||||||
|
"$BUILT_AS_OF" "$PUBLISHED_AS_OF"
|
||||||
|
printf 'RESULT: up-to-date %s\n' "$PUBLISHED_AS_OF"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
STAGE="stage-output"
|
||||||
|
|
||||||
rm -f "$OUTPUT_DIR/ownership-snapshot-manifest.json"
|
rm -f "$OUTPUT_DIR/ownership-snapshot-manifest.json"
|
||||||
if [[ "${#existing_snapshot_paths[@]}" -gt 0 ]]; then
|
if [[ "${#existing_snapshot_paths[@]}" -gt 0 ]]; then
|
||||||
|
|
@ -166,13 +229,19 @@ cp "$STAGED_SQLITE_PATH" "$OUTPUT_DIR/"
|
||||||
MANIFEST_PATH="$OUTPUT_DIR/ownership-snapshot-manifest.json"
|
MANIFEST_PATH="$OUTPUT_DIR/ownership-snapshot-manifest.json"
|
||||||
SQLITE_PATH="$OUTPUT_DIR/$(basename "$STAGED_SQLITE_PATH")"
|
SQLITE_PATH="$OUTPUT_DIR/$(basename "$STAGED_SQLITE_PATH")"
|
||||||
|
|
||||||
|
STAGE="upload"
|
||||||
if gh release view "$RELEASE_TAG" --repo "$REPO_FULL_NAME" >/dev/null 2>&1; then
|
if gh release view "$RELEASE_TAG" --repo "$REPO_FULL_NAME" >/dev/null 2>&1; then
|
||||||
printf 'Release %s already exists.\n' "$RELEASE_TAG"
|
printf 'Release %s already exists.\n' "$RELEASE_TAG"
|
||||||
else
|
else
|
||||||
printf 'Creating stable snapshot release %s...\n' "$RELEASE_TAG"
|
printf 'Creating stable snapshot release %s...\n' "$RELEASE_TAG"
|
||||||
|
target_args=()
|
||||||
|
# Packaged runs (Nix store) have no git checkout; let GitHub pick the default branch.
|
||||||
|
if git_head="$(git rev-parse HEAD 2>/dev/null)"; then
|
||||||
|
target_args=(--target "$git_head")
|
||||||
|
fi
|
||||||
gh release create "$RELEASE_TAG" \
|
gh release create "$RELEASE_TAG" \
|
||||||
--repo "$REPO_FULL_NAME" \
|
--repo "$REPO_FULL_NAME" \
|
||||||
--target "$(git rev-parse HEAD)" \
|
"${target_args[@]}" \
|
||||||
--title "Ownership Snapshot Current" \
|
--title "Ownership Snapshot Current" \
|
||||||
--notes "Stable release for idx ownership snapshot artifacts consumed by \`idx ownership sync\`." \
|
--notes "Stable release for idx ownership snapshot artifacts consumed by \`idx ownership sync\`." \
|
||||||
--latest=false
|
--latest=false
|
||||||
|
|
@ -188,3 +257,4 @@ gh release upload "$RELEASE_TAG" \
|
||||||
printf 'Published manifest: https://github.com/%s/releases/download/%s/ownership-snapshot-manifest.json\n' \
|
printf 'Published manifest: https://github.com/%s/releases/download/%s/ownership-snapshot-manifest.json\n' \
|
||||||
"$REPO_FULL_NAME" "$RELEASE_TAG"
|
"$REPO_FULL_NAME" "$RELEASE_TAG"
|
||||||
printf 'Published SQLite: %s\n' "$SQLITE_PATH"
|
printf 'Published SQLite: %s\n' "$SQLITE_PATH"
|
||||||
|
printf 'RESULT: published %s\n' "$BUILT_AS_OF"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue