From 49914110e40f394b2ae90086b463e5817491a1a0 Mon Sep 17 00:00:00 2001 From: yanziz-nv Date: Fri, 22 May 2026 13:09:59 -0700 Subject: [PATCH 1/2] CI: publish per-tag web client and seed /client/stable/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a tag trigger to docs.yaml so v* pushes deploy the web client to /client//, and (re)point /client/stable/ at the highest v* tag. A new promote-stable-client.yaml workflow re-resolves /client/stable/ on tag deletion (rollback path) and manual dispatch. The root /client/ redirect is intentionally left at ./main/ — flipping it to ./stable/ is a one-line follow-up once 1.2.x is tagged, so users hitting /client/ don't regress to a 1.1.x build that's missing fixes. Release-branch deploys no longer rewrite the root redirect; only main owns it. The redirect is self-healed on the next main push, and the new promote workflow keeps /client/stable/ in sync independently. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/docs.yaml | 80 ++++++++++++++++---- .github/workflows/promote-stable-client.yaml | 71 +++++++++++++++++ 2 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/promote-stable-client.yaml diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 7d2e312bb..0208155e8 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -2,7 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 # # Build docs and Teleop web app, then deploy to GitHub Pages. -# - Push to main/release (canonical repo): deploy docs at site root, web app at /client//. +# - Push to main/release/v* tag (canonical repo): deploy docs at site root, web app at /client//. +# Tag pushes also promote /client/stable/ to the highest v* tag. # - Same-repo PR: auto-deploy preview to preview/pr-/. # - Fork PR: build only; a maintainer can deploy via `/preview-docs` (see # docs-preview-on-demand.yaml). @@ -21,6 +22,8 @@ on: branches: - main - 'release/**' + tags: + - 'v[1-9]*.[0-9]*.[0-9]*' pull_request: types: [opened, synchronize, reopened] paths: @@ -48,7 +51,10 @@ jobs: if: github.repository == 'NVIDIA/IsaacTeleop' run: echo "defined=true" >> "$GITHUB_OUTPUT" - id: is-deploy-branch - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') + if: >- + github.ref == 'refs/heads/main' + || startsWith(github.ref, 'refs/heads/release/') + || startsWith(github.ref, 'refs/tags/v') run: echo "defined=true" >> "$GITHUB_OUTPUT" - id: ngc-allowlist run: | @@ -180,6 +186,12 @@ jobs: permissions: contents: write # push to gh-pages steps: + - name: Checkout (for tag lookup) + if: github.event_name == 'push' && github.ref_type == 'tag' + uses: actions/checkout@v6 + with: + fetch-depth: 1 + - name: Download docs artifact if: needs.build-docs.result == 'success' uses: actions/download-artifact@v7 @@ -194,24 +206,32 @@ jobs: name: webapp path: ./webapp - # Each push lands at client// so a release-branch deploy can no - # longer trample the canonical /client/, which is just a redirect to - # ./main/. + # Web client lands at client//: tag → v1.2.3, main → main, release branch → release-1.3.x. + # Tag pushes also (re)point client/stable/ at the highest v* tag. + # The root client/ redirect (currently → ./main/) is owned by the main branch deploy; + # flip it to ./stable/ in a follow-up once 1.2.x ships. - name: Place web app under versioned subpath if: needs.build-app.result == 'success' run: | set -euo pipefail + CLIENT_BASE=./docs/build/client + if [ "${{ github.event_name }}" = 'pull_request' ]; then - # PR previews live under preview/pr-/ and are pinned to the PR, - # so they don't need the multi-version layout. - CLIENT_DIR=./docs/build/current/client - mkdir -p "$CLIENT_DIR" - cp -r ./webapp/. "$CLIENT_DIR/" + mkdir -p ./docs/build/current/client + cp -r ./webapp/. ./docs/build/current/client/ + exit 0 + fi + + if [ "$GITHUB_REF_TYPE" = 'tag' ]; then + target="$GITHUB_REF_NAME" else - slug="${GITHUB_REF_NAME//\//-}" - CLIENT_BASE=./docs/build/client - mkdir -p "$CLIENT_BASE/$slug" - cp -r ./webapp/. "$CLIENT_BASE/$slug/" + target="${GITHUB_REF_NAME//\//-}" + fi + mkdir -p "$CLIENT_BASE/$target" + cp -r ./webapp/. "$CLIENT_BASE/$target/" + echo "Deployed web client to /client/$target/" + + if [ "$GITHUB_REF" = 'refs/heads/main' ]; then cat > "$CLIENT_BASE/index.html" <<'HTML' @@ -227,10 +247,38 @@ jobs: HTML - echo "Deployed web client to /client/$slug/" fi - - name: Deploy to gh-pages (main branch) + if [ "$GITHUB_REF_TYPE" = 'tag' ]; then + stable_slug="$(git ls-remote --tags origin 'v[1-9]*' \ + | awk -F'refs/tags/' '{print $2}' \ + | sed 's/\^{}$//' | sort -uV | tail -n1)" + if [ -z "$stable_slug" ]; then + echo "::warning::No v* tags resolved; leaving client/stable/ untouched." + exit 0 + fi + mkdir -p "$CLIENT_BASE/stable" + cat > "$CLIENT_BASE/stable/index.html" < + + + + + Redirecting to the stable Isaac Teleop web client (${stable_slug}) + + + + + +

Redirecting to the stable Isaac Teleop web client.

+ + + + HTML + echo "Stable now points to /client/${stable_slug}/" + fi + + - name: Deploy to gh-pages if: github.event_name == 'push' && needs.check-repo.outputs.is-deploy-branch == 'true' uses: peaceiris/actions-gh-pages@v4 with: diff --git a/.github/workflows/promote-stable-client.yaml b/.github/workflows/promote-stable-client.yaml new file mode 100644 index 000000000..0a95d4ccf --- /dev/null +++ b/.github/workflows/promote-stable-client.yaml @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Re-resolve /client/stable/ to the highest existing v* tag. +# Fires on tag deletion (rollback) and manual dispatch. Tag creation is handled +# by docs.yaml as part of the per-tag deploy. + +name: Promote stable web client + +on: + delete: + workflow_dispatch: + +concurrency: + group: promote-stable-client + cancel-in-progress: false + +permissions: + contents: write + +jobs: + promote: + if: >- + github.repository == 'NVIDIA/IsaacTeleop' + && ( + github.event_name == 'workflow_dispatch' + || (github.event.ref_type == 'tag' && startsWith(github.event.ref, 'v')) + ) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - id: build + run: | + set -euo pipefail + slug="$(git ls-remote --tags origin 'v[1-9]*' \ + | awk -F'refs/tags/' '{print $2}' \ + | sed 's/\^{}$//' | sort -uV | tail -n1)" + if [ -z "$slug" ]; then + echo "::warning::No v* tags remain; leaving client/stable/ untouched." + exit 0 + fi + mkdir -p out/client/stable + cat > out/client/stable/index.html < + + + + + Redirecting to the stable Isaac Teleop web client (${slug}) + + + + + +

Redirecting to the stable Isaac Teleop web client.

+ + + + HTML + echo "slug=$slug" >> "$GITHUB_OUTPUT" + echo "Stable resolved to /client/${slug}/" + + - if: steps.build.outputs.slug != '' + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./out + keep_files: true From 00bb46588e21c9fe46791e1366aa94ba8b381021 Mon Sep 17 00:00:00 2001 From: yanziz-nv Date: Fri, 22 May 2026 13:30:34 -0700 Subject: [PATCH 2/2] CI: tighten stable_slug glob to match tag trigger pattern The trigger filters 'v[1-9]*.[0-9]*.[0-9]*' but the ls-remote lookup used 'v[1-9]*', which would match non-semver tags (e.g. v2-dev) that weren't actually deployed and could rank above real releases under sort -V. Tighten both lookups to the trigger's glob so stable only points at tags the workflow publishes. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/docs.yaml | 2 +- .github/workflows/promote-stable-client.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 0208155e8..4c47498dd 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -250,7 +250,7 @@ jobs: fi if [ "$GITHUB_REF_TYPE" = 'tag' ]; then - stable_slug="$(git ls-remote --tags origin 'v[1-9]*' \ + stable_slug="$(git ls-remote --tags origin 'v[1-9]*.[0-9]*.[0-9]*' \ | awk -F'refs/tags/' '{print $2}' \ | sed 's/\^{}$//' | sort -uV | tail -n1)" if [ -z "$stable_slug" ]; then diff --git a/.github/workflows/promote-stable-client.yaml b/.github/workflows/promote-stable-client.yaml index 0a95d4ccf..4debc714b 100644 --- a/.github/workflows/promote-stable-client.yaml +++ b/.github/workflows/promote-stable-client.yaml @@ -35,7 +35,7 @@ jobs: - id: build run: | set -euo pipefail - slug="$(git ls-remote --tags origin 'v[1-9]*' \ + slug="$(git ls-remote --tags origin 'v[1-9]*.[0-9]*.[0-9]*' \ | awk -F'refs/tags/' '{print $2}' \ | sed 's/\^{}$//' | sort -uV | tail -n1)" if [ -z "$slug" ]; then