From e4facad401a7ac366515e2192b1c72fec733f8e7 Mon Sep 17 00:00:00 2001 From: Nawid Salehie <102778966+Nawid3333@users.noreply.github.com> Date: Thu, 1 Oct 2026 02:57:35 +0200 Subject: [PATCH] ci: watch the silero VAD model and dash.js's vtt.js for new releases (U1) vendored-updates.yml, daily. A newer snakers4/silero-vad release with other model bytes gets a PR on vendored/silero-vad- (the model replaced, TAG and SHA256 moved in tools/verify-vad.mjs), with CI dispatched on it; a model missing at its path gets an issue. A dash.js release that changes contrib/videojs-vtt.js/vtt.js gets an issue with the changed lines and a compare link. Assigned + @mention; never raised twice; closes itself once the pin reaches the release; a newer release closes the older item. libsamplerate, the third item U1 listed, left with the re-encoder (#101). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/vendored-updates.yml | 304 +++++++++++++++++++++++ CLAUDE.md | 14 ++ docs/maintenance.md | 20 ++ tests/workflows/vendored-updates.test.sh | 202 +++++++++++++++ 4 files changed, 540 insertions(+) create mode 100644 .github/workflows/vendored-updates.yml create mode 100644 tests/workflows/vendored-updates.test.sh diff --git a/.github/workflows/vendored-updates.yml b/.github/workflows/vendored-updates.yml new file mode 100644 index 000000000..f5f60f097 --- /dev/null +++ b/.github/workflows/vendored-updates.yml @@ -0,0 +1,304 @@ +name: Vendored updates + +# Two vendored files no other workflow watches (U1): +# +# chrome/player/modules/vad/silero_vad_half.onnx - snakers4/silero-vad's published +# half-precision model, shipped as released and pinned by TAG and SHA256 in +# tools/verify-vad.mjs. When a newer release publishes it with other bytes, a pull +# request "Vendored model update: silero-vad " on vendored/silero-vad- +# replaces it and moves the pin, and CI is started on it (this token's push starts +# none): the voice detector's reference e2e decides. If the model is not at the path +# the pin knows, an issue, "Silero VAD : the model file moved", instead. +# chrome/player/modules/vtt.mjs - dash.js's contrib/videojs-vtt.js/vtt.js with the +# changes tools/verify-vtt.mjs re-applies, pinned to a dash.js tag. When the newest +# dash.js release changes that file, an issue "vtt.js changed in dash.js ": the +# changes may need re-deriving, so a person moves the pin. +# +# Each is assigned to the owner and @mentions them. A title is never raised twice, open or +# closed: closing one skips that release for good. Each closes itself once its pin is at +# its tag or later, and a newer release's item closes the older ones. Nothing merges here: +# the pull request waits for the owner (update-prs.yml merges no vendored/ branch). + +on: + schedule: + - cron: '45 6 * * *' + workflow_dispatch: + +permissions: {} # each job asks for what it needs + +concurrency: + group: vendored-updates + cancel-in-progress: false + +jobs: + model: + name: Check snakers4/silero-vad for a new model + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: write # push the vendored/silero-vad- branch + pull-requests: write # open it, close the ones it replaces + issues: write # the "model file moved" issue; this job's own failure + actions: write # start CI on the branch + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + OWNER: ${{ github.repository_owner }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + UPSTREAM: 'snakers4/silero-vad' + MODEL_PATH: 'src/silero_vad/data/silero_vad_half.onnx' + VENDORED: 'chrome/player/modules/vad/silero_vad_half.onnx' + PREFIX: 'Vendored model update: silero-vad ' + MOVED_PREFIX: 'Silero VAD ' + MOVED_SUFFIX: ': the model file moved' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Open a pull request for a new model + run: | + set -euo pipefail + # The token goes to the one git command that needs it; .git/config never holds it. + auth=$(printf 'x-access-token:%s' "$GH_TOKEN" | base64 -w0) + authgit() { git -c "http.https://github.com/.extraheader=AUTHORIZATION: basic $auth" "$@"; } + # ge A B: A is B or newer (version order: v6.10 after v6.9). + ge() { [ "$1" = "$2" ] || [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n 1)" = "$1" ]; } + + pinned_tag=$(sed -n "s/^const TAG = '\(.*\)';\$/\1/p" tools/verify-vad.mjs) + pinned_sha=$(sed -n "s/^const SHA256 = '\([0-9a-f]\{64\}\)';\$/\1/p" tools/verify-vad.mjs) + if [ -z "$pinned_tag" ] || [ -z "$pinned_sha" ]; then + echo "tools/verify-vad.mjs has no TAG or SHA256 line in the form this reads." + exit 1 + fi + release=$(gh api "repos/$UPSTREAM/releases/latest") + # Another project's data: only a plain version goes into titles, branches and URLs. + latest=$(jq -r .tag_name <<< "$release") + if ! [[ "$latest" =~ ^v?[0-9]+(\.[0-9]+){0,3}$ ]]; then + echo "$UPSTREAM's latest release is tagged '$latest', not a version." + exit 1 + fi + release_url="https://github.com/$UPSTREAM/releases/tag/$latest" + echo "Pinned: $pinned_tag. Latest release: $latest." + + # This job's items, open or closed: number, state, title. + gh api --paginate "repos/$GH_REPO/issues?state=all&per_page=100" \ + --jq '.[] | select(.user.login == "github-actions[bot]" and ((.title | startswith(env.PREFIX)) or ((.title | startswith(env.MOVED_PREFIX)) and (.title | endswith(env.MOVED_SUFFIX))))) | [.number, .state, (.pull_request != null), .title] | @tsv' \ + > "$RUNNER_TEMP/mine.tsv" + + # Closes each open item whose release the pin has reached, and, once one for the + # latest release exists ($1), every older one. + close_pass() { + while IFS=$'\t' read -r number state is_pr title; do + [ "$state" = open ] || continue + tag=${title#"$PREFIX"} + tag=${tag#"$MOVED_PREFIX"} + tag=${tag%"$MOVED_SUFFIX"} + if ge "$pinned_tag" "$tag"; then + why="tools/verify-vad.mjs pins silero-vad $pinned_tag now." + elif [ -n "${1-}" ] && [ "$tag" != "$latest" ]; then + why="silero-vad $latest is out: $1 replaces this one." + else + continue + fi + if [ "$is_pr" = true ]; then + gh pr close "$number" --delete-branch --comment "$why" + else + gh issue close "$number" --comment "$why" + fi + echo "Closed #$number ($title)" + done < "$RUNNER_TEMP/mine.tsv" + } + + if [ "$latest" = "$pinned_tag" ] || ! ge "$latest" "$pinned_tag"; then + echo "Nothing newer than the pin." + close_pass + exit 0 + fi + pr_title="$PREFIX$latest" + moved_title="$MOVED_PREFIX$latest$MOVED_SUFFIX" + if awk -F '\t' -v a="$pr_title" -v b="$moved_title" '$4 == a || $4 == b {found = 1} END {exit !found}' "$RUNNER_TEMP/mine.tsv"; then + echo "silero-vad $latest was raised before." + close_pass "the $latest item" + exit 0 + fi + + code=$(curl -sS --max-time 120 -o "$RUNNER_TEMP/model.onnx" -w '%{http_code}' \ + "https://raw.githubusercontent.com/$UPSTREAM/$latest/$MODEL_PATH") + if [ "$code" = 404 ]; then + # shellcheck disable=SC2016 # backticks are Markdown + printf '@%s silero-vad %s is out (%s), but `%s` is not there at that tag: the model the extension ships (`%s`, pinned in `tools/verify-vad.mjs`) moved or is gone. Find where the release puts the half-precision model, replace the file and the TAG and SHA256 lines, and run `pnpm run verify:vad`. This issue closes itself once the pin is at %s or later; closing it skips %s.\n' \ + "$OWNER" "$latest" "$release_url" "$MODEL_PATH" "$VENDORED" "$latest" "$latest" > "$RUNNER_TEMP/body.md" + url=$(gh issue create --title "$moved_title" --assignee "$OWNER" --body-file "$RUNNER_TEMP/body.md") + echo "Opened $url" + close_pass "$url" + exit 0 + fi + if [ "$code" != 200 ]; then + echo "The model at $latest answered HTTP $code." + exit 1 + fi + new_sha=$(sha256sum "$RUNNER_TEMP/model.onnx" | cut -d' ' -f1) + if [ "$new_sha" = "$pinned_sha" ]; then + echo "silero-vad $latest publishes the same model, byte for byte: nothing to do." + close_pass + exit 0 + fi + + branch="vendored/silero-vad-$latest" + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git checkout -q -B "$branch" + cp "$RUNNER_TEMP/model.onnx" "$VENDORED" + sed -i -e "s/^const TAG = '$pinned_tag';\$/const TAG = '$latest';/" \ + -e "s/^const SHA256 = '$pinned_sha';\$/const SHA256 = '$new_sha';/" tools/verify-vad.mjs + grep -qxF "const TAG = '$latest';" tools/verify-vad.mjs + grep -qxF "const SHA256 = '$new_sha';" tools/verify-vad.mjs + git add -- "$VENDORED" tools/verify-vad.mjs + git commit -q -m "deps(vad): silero-vad $latest's model (was $pinned_tag)" + authgit push -q -f origin "$branch" + + # shellcheck disable=SC2016 # backticks are Markdown + printf '@%s silero-vad %s is out (%s) and publishes the voice detector'"'"'s model with other bytes. This replaces `%s` with it and moves TAG and SHA256 in `tools/verify-vad.mjs` (was %s).\n\nCI runs on this branch: the voice detector'"'"'s reference e2e decides whether the new model still scores the fixed signal as the reference runtime did. Merge it when green; close it to skip %s.\n' \ + "$OWNER" "$latest" "$release_url" "$VENDORED" "$pinned_tag" "$latest" > "$RUNNER_TEMP/body.md" + url=$(gh pr create --base main --head "$branch" --title "$pr_title" --assignee "$OWNER" --body-file "$RUNNER_TEMP/body.md") + echo "Opened $url" + # This token's push starts no workflow; a dispatch does. + gh workflow run ci.yml --ref "$branch" + close_pass "$url" + + # A failed run of this workflow is emailed only to whoever started it (for the schedule, + # whoever last changed the cron line): one issue while it is open, assigned and + # @mentioning the owner, as wsl-releases.yml does. A failure while it is open adds a + # comment to it. + - name: Report the model job's own failure + if: failure() + env: + TITLE: 'Vendored updates workflow failed (model)' + run: | + set -euo pipefail + number=$(gh issue list --state open --limit 200 --json number,title \ + --jq '[.[] | select(.title == env.TITLE)][0].number // empty') || number='' + if [ -n "$number" ]; then + printf '@%s Failed again: %s\n' "$OWNER" "$RUN_URL" > "$RUNNER_TEMP/comment.md" + gh issue comment "$number" --body-file "$RUNNER_TEMP/comment.md" + exit 0 + fi + printf '@%s vendored-updates.yml failed: %s\n\nThe run log names the failed command. Close this issue once it is fixed; a later failure opens a new one.\n' \ + "$OWNER" "$RUN_URL" > "$RUNNER_TEMP/body.md" + gh issue create --title "$TITLE" --assignee "$OWNER" --body-file "$RUNNER_TEMP/body.md" + + vtt: + name: Check dash.js for a changed vtt.js + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read # the checkout + issues: write # the "vtt.js changed" issue; this job's own failure + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + OWNER: ${{ github.repository_owner }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + UPSTREAM: 'Dash-Industry-Forum/dash.js' + VTT_PATH: 'contrib/videojs-vtt.js/vtt.js' + PREFIX: 'vtt.js changed in dash.js ' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Open the issue for a changed vtt.js + run: | + set -euo pipefail + ge() { [ "$1" = "$2" ] || [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n 1)" = "$1" ]; } + + pinned_tag=$(grep -oE 'Dash-Industry-Forum/dash\.js/v[0-9]+(\.[0-9]+)*/' tools/verify-vtt.mjs | head -n 1 | cut -d/ -f3) + if [ -z "$pinned_tag" ]; then + echo "tools/verify-vtt.mjs names no dash.js tag in the form this reads." + exit 1 + fi + latest=$(gh api "repos/$UPSTREAM/releases/latest" --jq .tag_name) + if ! [[ "$latest" =~ ^v[0-9]+(\.[0-9]+){0,3}$ ]]; then + echo "$UPSTREAM's latest release is tagged '$latest', not a version." + exit 1 + fi + echo "Pinned: $pinned_tag. Latest release: $latest." + title="$PREFIX$latest" + + gh api --paginate "repos/$GH_REPO/issues?state=all&per_page=100" \ + --jq '.[] | select(.pull_request == null and .user.login == "github-actions[bot]" and (.title | startswith(env.PREFIX))) | [.number, .state, .title] | @tsv' \ + > "$RUNNER_TEMP/mine.tsv" + + # Closes each open issue whose release the pin has reached, and, once one for the + # latest release exists ($1), every older one. + close_pass() { + while IFS=$'\t' read -r number state old; do + [ "$state" = open ] || continue + tag=${old#"$PREFIX"} + if ge "$pinned_tag" "$tag"; then + gh issue close "$number" --comment "tools/verify-vtt.mjs pins dash.js $pinned_tag now." + elif [ -n "${1-}" ] && [ "$tag" != "$latest" ]; then + gh issue close "$number" --reason 'not planned' --comment "dash.js $latest is out: $1 replaces this one." + else + continue + fi + echo "Closed #$number ($old)" + done < "$RUNNER_TEMP/mine.tsv" + } + + if [ "$latest" = "$pinned_tag" ] || ! ge "$latest" "$pinned_tag"; then + echo "Nothing newer than the pin." + close_pass + exit 0 + fi + if awk -F '\t' -v t="$title" '$3 == t {found = 1} END {exit !found}' "$RUNNER_TEMP/mine.tsv"; then + echo "dash.js $latest was raised before." + close_pass "the $latest issue" + exit 0 + fi + + base="https://raw.githubusercontent.com/$UPSTREAM" + code=$(curl -sS --max-time 60 -o "$RUNNER_TEMP/old.js" -w '%{http_code}' "$base/$pinned_tag/$VTT_PATH") + if [ "$code" != 200 ]; then + echo "$VTT_PATH at the pinned $pinned_tag answered HTTP $code." + exit 1 + fi + code=$(curl -sS --max-time 60 -o "$RUNNER_TEMP/new.js" -w '%{http_code}' "$base/$latest/$VTT_PATH") + if [ "$code" = 200 ] && cmp -s "$RUNNER_TEMP/old.js" "$RUNNER_TEMP/new.js"; then + echo "dash.js $latest has the same vtt.js, byte for byte: nothing to do." + close_pass + exit 0 + fi + if [ "$code" = 200 ]; then + change=$(diff "$RUNNER_TEMP/old.js" "$RUNNER_TEMP/new.js" | grep -c '^[<>]' || true) + what="changes $change lines of it: https://github.com/$UPSTREAM/compare/$pinned_tag...$latest" + elif [ "$code" = 404 ]; then + what="no longer has it at $VTT_PATH" + else + echo "$VTT_PATH at $latest answered HTTP $code." + exit 1 + fi + # shellcheck disable=SC2016 # backticks are Markdown + printf '@%s dash.js %s is out and %s.\n\n`chrome/player/modules/vtt.mjs` is that file at dash.js %s with the changes `tools/verify-vtt.mjs` re-applies. Move the tag in its UPSTREAM line to %s and run `pnpm run verify:vtt`: it says where a change no longer applies. This issue closes itself once the pin is at %s or later; closing it skips %s.\n' \ + "$OWNER" "$latest" "$what" "$pinned_tag" "$latest" "$latest" "$latest" > "$RUNNER_TEMP/body.md" + url=$(gh issue create --title "$title" --assignee "$OWNER" --body-file "$RUNNER_TEMP/body.md") + echo "Opened $url" + close_pass "$url" + + - name: Report the vtt.js job's own failure + if: failure() + env: + TITLE: 'Vendored updates workflow failed (vtt.js)' + run: | + set -euo pipefail + number=$(gh issue list --state open --limit 200 --json number,title \ + --jq '[.[] | select(.title == env.TITLE)][0].number // empty') || number='' + if [ -n "$number" ]; then + printf '@%s Failed again: %s\n' "$OWNER" "$RUN_URL" > "$RUNNER_TEMP/comment.md" + gh issue comment "$number" --body-file "$RUNNER_TEMP/comment.md" + exit 0 + fi + printf '@%s vendored-updates.yml failed: %s\n\nThe run log names the failed command. Close this issue once it is fixed; a later failure opens a new one.\n' \ + "$OWNER" "$RUN_URL" > "$RUNNER_TEMP/body.md" + gh issue create --title "$TITLE" --assignee "$OWNER" --body-file "$RUNNER_TEMP/body.md" diff --git a/CLAUDE.md b/CLAUDE.md index 4203d4fc0..2fc040cf5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1270,6 +1270,20 @@ the change went in. it; the real gh uses gojq, built in, and the filters avoid the one difference found (jq 1.7 splits `""` into `[]`, gojq into `[""]`). The test passed with gojq 0.12.19 swapped in too. +- **`vendored-updates.yml`** (daily, 06:45 UTC), 2026-10-01, U1: the two vendored files no + other workflow watches. **The silero VAD model:** a newer snakers4/silero-vad release whose + half-precision model has other bytes gets a PR on `vendored/silero-vad-` with the + model replaced and TAG/SHA256 moved in `tools/verify-vad.mjs`, and CI dispatched on it + (the reference e2e decides); update-prs.yml leaves `vendored/` branches to the owner. A + model missing at its path gets an issue, "Silero VAD : the model file moved". + **vtt.js:** a dash.js release that changes `contrib/videojs-vtt.js/vtt.js` gets an issue, + "vtt.js changed in dash.js ", with the changed-line count and a compare link: a + person moves `tools/verify-vtt.mjs`'s tag and re-runs `verify:vtt`. Each item is assigned + + @mention, is never raised twice (closing it skips that release), closes itself once its + pin reaches its tag, and a newer release's item closes older ones. On 2026-10-01 both + were current in effect: silero-vad v6.2.3 and dash.js v5.2.1 publish the same bytes as + the pins (v6.2.1, v5.1.0). `tests/workflows/vendored-updates.test.sh`: 10 scenarios + (real git pushing to a local bare origin), and 7 undone rules each fail it. - **`dependency-review.yml`** fails a PR that adds a package with a high-severity advisory. Since 2026-09-30 it also runs on `workflow_dispatch`, which `sync-upstream.yml` and `patched-libraries.yml` send next to CI's: their PRs are opened by the workflow token, so diff --git a/docs/maintenance.md b/docs/maintenance.md index 2f3a806e2..2f9d7b5b2 100644 --- a/docs/maintenance.md +++ b/docs/maintenance.md @@ -186,3 +186,23 @@ image pinned in a form Dependabot does not update: - Node only in `.nvmrc`, pnpm only in `package.json`'s `packageManager`, npm packages in `package.json` and `pnpm-lock.yaml`, mpv in `.github/mpv-build.json`: each has its updater in the table above. + +## Vendored files + +Two files the extension ships come from another project without a package manager: +`vendored-updates.yml` (daily) watches them. + +- **The voice detector's model** (`chrome/player/modules/vad/silero_vad_half.onnx`, from + snakers4/silero-vad): a newer release with a different model opens a pull request, + "Vendored model update: silero-vad ", with the model and its pin in + `tools/verify-vad.mjs` replaced, and starts CI on it. The voice detector's reference test + decides; merge it when green, close it to skip that release. If the model is not where + the release used to keep it, an issue tells you so instead. +- **vtt.js** (`chrome/player/modules/vtt.mjs`, from dash.js): a dash.js release that changes + the file opens an issue, "vtt.js changed in dash.js ". Move the tag in + `tools/verify-vtt.mjs` and run `pnpm run verify:vtt`, which says where FastStream's changes + no longer apply. + +Each closes itself once its pin reaches the release; a newer release closes the older one. +If the workflow itself fails, it opens "Vendored updates workflow failed (model)" or +"(vtt.js)". diff --git a/tests/workflows/vendored-updates.test.sh b/tests/workflows/vendored-updates.test.sh new file mode 100644 index 000000000..acda8bd9b --- /dev/null +++ b/tests/workflows/vendored-updates.test.sh @@ -0,0 +1,202 @@ +#!/usr/bin/env bash +# vendored-updates.yml: the silero-vad model pull request (with the model and its pin +# moved, pushed to a branch and CI started), the "model file moved" issue, the vtt.js +# issue, which ones close, and what is never raised twice. The model step runs real git +# in a scratch repository whose origin is a local bare one; gh and curl are stubs that +# answer from fixture files and log what they are asked. +source "$(dirname "$0")/lib.sh" + +here=$(mktemp -d) +trap 'rm -rf "$here"' EXIT +model_step=$here/model.sh +vtt_step=$here/vtt.sh +step_script vendored-updates.yml 'Open a pull request for a new model' > "$model_step" || exit 1 +step_script vendored-updates.yml 'Open the issue for a changed vtt.js' > "$vtt_step" || exit 1 +step_script vendored-updates.yml "Report the model job's own failure" > /dev/null || exit 1 +step_script vendored-updates.yml "Report the vtt.js job's own failure" > /dev/null || exit 1 + +mkdir -p "$here/bin" +cat > "$here/bin/gh" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +jqf='' +args=("$@") +for ((i = 0; i < ${#args[@]}; i++)); do + if [ "${args[i]}" = --jq ]; then jqf=${args[i + 1]-}; fi +done +case "$1 $2" in + "api repos/$UPSTREAM/releases/latest") + if [ -n "$jqf" ]; then jq -r "$jqf" "$FIX/release.json"; else cat "$FIX/release.json"; fi ;; + 'api --paginate') + [ "$3" = "repos/$GH_REPO/issues?state=all&per_page=100" ] || { echo "stub gh: unexpected api path $3" >&2; exit 2; } + jq -r "$jqf" "$FIX/issues.json" ;; + 'issue create' | 'pr create') + { + printf '%s' "$(printf '%s' "$1" | tr a-z A-Z)CREATE"; printf ' [%s]' "${@:3}"; printf '\n' + while [ $# -gt 0 ]; do + if [ "$1" = --body-file ]; then echo '--- body:'; cat "$2"; echo '--- end body'; fi + shift + done + } >> "$LOG" + echo "https://github.com/$GH_REPO/issues/99" ;; + 'issue close' | 'pr close') + { printf '%s' "$(printf '%s' "$1" | tr a-z A-Z)CLOSE"; printf ' [%s]' "${@:3}"; printf '\n'; } >> "$LOG" ;; + 'workflow run') + { printf 'DISPATCH'; printf ' [%s]' "${@:3}"; printf '\n'; } >> "$LOG" ;; + *) + echo "stub gh: unexpected call: $*" >&2; exit 2 ;; +esac +EOF +# curl: -o FILE -w '%{http_code}' URL, answered from $FIX/urls/, or 404. +cat > "$here/bin/curl" <<'EOF' +#!/usr/bin/env bash +out='' url='' +while [ $# -gt 0 ]; do + case "$1" in + -o) out=$2; shift ;; + -w|--max-time) shift ;; + -*) ;; + *) url=$1 ;; + esac + shift +done +echo "CURL [$url]" >> "$LOG" +f="$FIX/urls/$(printf '%s' "$url" | tr '/:' '__')" +if [ -f "$f" ]; then cp "$f" "$out"; printf 200; else : > "$out"; printf 404; fi +EOF +chmod +x "$here/bin/gh" "$here/bin/curl" + +export GH_TOKEN=stub GH_REPO='Nawid3333/FastStream' OWNER='Nawid3333' +export RUN_URL='https://github.com/Nawid3333/FastStream/actions/runs/1' +bot='{"login":"github-actions[bot]"}' +human='{"login":"Nawid3333"}' +OLD_SHA=$(printf 'old model' | sha256sum | cut -d' ' -f1) + +# fixtures : a fresh scenario. +fixtures() { + export FIX="$here/fix" RUNNER_TEMP="$here/fix/tmp" LOG="$here/fix/log" + rm -rf "$FIX" + mkdir -p "$RUNNER_TEMP" "$FIX/urls" + : > "$LOG" + printf '{"tag_name":"%s"}' "$1" > "$FIX/release.json" + printf '%s' "$2" > "$FIX/issues.json" +} +# serve : what curl gets for that URL. +serve() { printf '%s' "$2" > "$FIX/urls/$(printf '%s' "$1" | tr '/:' '__')"; } + +# A checkout of this repository as the model job has it: the model, its pin, a bare origin. +repo() { + local work=$FIX/work + git init -q -b main "$work" + mkdir -p "$work/chrome/player/modules/vad" "$work/tools" + printf 'old model' > "$work/chrome/player/modules/vad/silero_vad_half.onnx" + printf "// pin\nconst TAG = 'v6.2.1';\nconst PUBLISHED = 'x';\nconst SHA256 = '%s';\n" "$OLD_SHA" > "$work/tools/verify-vad.mjs" + printf "const UPSTREAM =\n 'https://raw.githubusercontent.com/Dash-Industry-Forum/dash.js/v5.1.0/' +\n 'contrib/videojs-vtt.js/vtt.js';\n" > "$work/tools/verify-vtt.mjs" + git -C "$work" -c user.name=t -c user.email=t@t add -A + git -C "$work" -c user.name=t -c user.email=t@t commit -q -m init + git init -q --bare "$FIX/origin.git" + git -C "$work" remote add origin "$FIX/origin.git" +} +run() { + echo "$1" + ( + cd "$FIX/work" || exit 9 + PATH="$here/bin:$PATH" run_step "$2" + ) > "$FIX/out" 2>&1 + status=$? +} +model_env() { export UPSTREAM='snakers4/silero-vad' MODEL_PATH='src/silero_vad/data/silero_vad_half.onnx' VENDORED='chrome/player/modules/vad/silero_vad_half.onnx' PREFIX='Vendored model update: silero-vad ' MOVED_PREFIX='Silero VAD ' MOVED_SUFFIX=': the model file moved'; } +vtt_env() { export UPSTREAM='Dash-Industry-Forum/dash.js' VTT_PATH='contrib/videojs-vtt.js/vtt.js' PREFIX='vtt.js changed in dash.js '; } +model_url() { echo "https://raw.githubusercontent.com/snakers4/silero-vad/$1/src/silero_vad/data/silero_vad_half.onnx"; } +vtt_url() { echo "https://raw.githubusercontent.com/Dash-Industry-Forum/dash.js/$1/contrib/videojs-vtt.js/vtt.js"; } + +model_env +fixtures v6.3.0 "[{\"number\":40,\"state\":\"open\",\"title\":\"Vendored model update: silero-vad v6.2.5\",\"user\":$bot,\"pull_request\":{}},{\"number\":41,\"state\":\"open\",\"title\":\"Vendored model update: silero-vad v6.2.0\",\"user\":$bot,\"pull_request\":{}},{\"number\":42,\"state\":\"open\",\"title\":\"Vendored model update: silero-vad v6.9\",\"user\":$human,\"pull_request\":{}}]" +repo +serve "$(model_url v6.3.0)" 'new model' +run 'm1 a newer release with a new model -> a branch with it and the pin, a PR, CI, older PRs closed' "$model_step" +NEW_SHA=$(printf 'new model' | sha256sum | cut -d' ' -f1) +check 'succeeds' test "$status" -eq 0 +check 'pushes vendored/silero-vad-v6.3.0 with the new model' test "$(git -C "$FIX/origin.git" show vendored/silero-vad-v6.3.0:chrome/player/modules/vad/silero_vad_half.onnx 2>/dev/null)" = 'new model' +check 'and the pin moved' contains <(git -C "$FIX/origin.git" show vendored/silero-vad-v6.3.0:tools/verify-vad.mjs) "const TAG = 'v6.3.0';" +check 'and its hash' contains <(git -C "$FIX/origin.git" show vendored/silero-vad-v6.3.0:tools/verify-vad.mjs) "const SHA256 = '$NEW_SHA';" +check 'one commit on main' test "$(git -C "$FIX/origin.git" rev-parse vendored/silero-vad-v6.3.0^)" = "$(git -C "$FIX/work" rev-parse main)" +check 'changing the model and the pin, nothing else' test "$(git -C "$FIX/origin.git" diff --name-only vendored/silero-vad-v6.3.0^ vendored/silero-vad-v6.3.0 | sort | tr '\n' ' ')" = 'chrome/player/modules/vad/silero_vad_half.onnx tools/verify-vad.mjs ' +check 'opens the PR, assigned to the owner' contains "$LOG" 'PRCREATE [--base] [main] [--head] [vendored/silero-vad-v6.3.0] [--title] [Vendored model update: silero-vad v6.3.0] [--assignee] [Nawid3333]' +check 'which mentions the owner' contains "$LOG" '@Nawid3333 silero-vad v6.3.0 is out' +check 'starts CI on the branch' contains "$LOG" 'DISPATCH [ci.yml] [--ref] [vendored/silero-vad-v6.3.0]' +check 'closes the older open PR #40, pointing at the new one' contains "$LOG" 'PRCLOSE [40] [--delete-branch] [--comment] [silero-vad v6.3.0 is out: https://github.com/Nawid3333/FastStream/issues/99 replaces this one.]' +check 'closes #41, whose release the pin has passed' contains "$LOG" 'PRCLOSE [41] [--delete-branch] [--comment] [tools/verify-vad.mjs pins silero-vad v6.2.1 now.]' +check "leaves a person's PR alone" lacks "$LOG" '[42]' +check 'never puts the token in .git/config' lacks "$FIX/work/.git/config" 'extraheader' + +fixtures v6.3.0 '[]' +repo +serve "$(model_url v6.3.0)" 'old model' +run 'm2 a newer release with the same model -> nothing' "$model_step" +check 'succeeds' test "$status" -eq 0 +check 'opens nothing' lacks "$LOG" 'CREATE' +check 'pushes nothing' test -z "$(git -C "$FIX/origin.git" branch --list 'vendored/*')" + +fixtures v6.3.0 '[]' +repo +run 'm3 the model is not at its path at the new tag -> an issue' "$model_step" +check 'succeeds' test "$status" -eq 0 +check 'opens "Silero VAD v6.3.0: the model file moved"' contains "$LOG" 'ISSUECREATE [--title] [Silero VAD v6.3.0: the model file moved] [--assignee] [Nawid3333]' +check 'opens no PR' lacks "$LOG" 'PRCREATE' + +fixtures v6.3.0 "[{\"number\":50,\"state\":\"closed\",\"title\":\"Vendored model update: silero-vad v6.3.0\",\"user\":$bot,\"pull_request\":{}}]" +repo +serve "$(model_url v6.3.0)" 'new model' +run 'm4 a release raised before (its PR closed: skipped) -> nothing, nothing fetched' "$model_step" +check 'succeeds' test "$status" -eq 0 +check 'opens nothing' lacks "$LOG" 'CREATE' +check 'fetches nothing' lacks "$LOG" 'CURL' + +fixtures v6.2.1 "[{\"number\":51,\"state\":\"open\",\"title\":\"Silero VAD v6.2.1: the model file moved\",\"user\":$bot}]" +repo +run 'm5 the pin reached the release -> its open issue closes' "$model_step" +check 'succeeds' test "$status" -eq 0 +check 'closes #51' contains "$LOG" 'ISSUECLOSE [51] [--comment] [tools/verify-vad.mjs pins silero-vad v6.2.1 now.]' + +fixtures 'v6.3.0; rm -rf /' '[]' +repo +run 'm6 a tag that is no version -> refused' "$model_step" +check 'fails' test "$status" -ne 0 +check 'opens nothing' lacks "$LOG" 'CREATE' + +vtt_env +fixtures v5.3.0 "[{\"number\":60,\"state\":\"open\",\"title\":\"vtt.js changed in dash.js v5.2.0\",\"user\":$bot},{\"number\":61,\"state\":\"open\",\"title\":\"vtt.js changed in dash.js v5.0.0\",\"user\":$bot}]" +repo +serve "$(vtt_url v5.1.0)" $'a\nb\nc\n' +serve "$(vtt_url v5.3.0)" $'a\nB\nc\nd\n' +run 'v1 dash.js changed vtt.js -> an issue with the change, older ones closed' "$vtt_step" +check 'succeeds' test "$status" -eq 0 +check 'opens "vtt.js changed in dash.js v5.3.0"' contains "$LOG" 'ISSUECREATE [--title] [vtt.js changed in dash.js v5.3.0] [--assignee] [Nawid3333]' +check 'counts the changed lines and links the compare' contains "$LOG" 'changes 3 lines of it: https://github.com/Dash-Industry-Forum/dash.js/compare/v5.1.0...v5.3.0' +check 'closes the older #60, pointing at the new one' contains "$LOG" "ISSUECLOSE [60] [--reason] [not planned] [--comment] [dash.js v5.3.0 is out: https://github.com/Nawid3333/FastStream/issues/99 replaces this one.]" +check 'closes #61, whose release the pin has passed' contains "$LOG" 'ISSUECLOSE [61] [--comment] [tools/verify-vtt.mjs pins dash.js v5.1.0 now.]' + +fixtures v5.3.0 '[]' +repo +serve "$(vtt_url v5.1.0)" $'a\nb\n' +serve "$(vtt_url v5.3.0)" $'a\nb\n' +run 'v2 the same vtt.js -> nothing' "$vtt_step" +check 'succeeds' test "$status" -eq 0 +check 'opens nothing' lacks "$LOG" 'CREATE' + +fixtures v5.3.0 '[]' +repo +serve "$(vtt_url v5.1.0)" $'a\n' +run 'v3 vtt.js gone from the new release -> an issue saying so' "$vtt_step" +check 'succeeds' test "$status" -eq 0 +check 'says it is gone' contains "$LOG" 'dash.js v5.3.0 is out and no longer has it at contrib/videojs-vtt.js/vtt.js.' + +fixtures v5.3.0 "[{\"number\":62,\"state\":\"closed\",\"title\":\"vtt.js changed in dash.js v5.3.0\",\"user\":$bot}]" +repo +run 'v4 raised before -> nothing, nothing fetched' "$vtt_step" +check 'succeeds' test "$status" -eq 0 +check 'opens nothing' lacks "$LOG" 'CREATE' +check 'fetches nothing' lacks "$LOG" 'CURL' + +finish