Skip to content

refactor(data): consolidate dataviewer API transport (#1568) #703

refactor(data): consolidate dataviewer API transport (#1568)

refactor(data): consolidate dataviewer API transport (#1568) #703

Workflow file for this run

name: CI
on:
push:
branches:
- main
permissions:
contents: read
defaults:
run:
shell: pwsh
jobs:
# Spell checking using cspell
spell-check:
name: Spell Check
uses: ./.github/workflows/spell-check.yml
permissions:
contents: read
# Markdown linting using markdownlint-cli2
markdown-lint:
name: Markdown Lint
uses: ./.github/workflows/markdown-lint.yml
permissions:
contents: read
# TOML formatting using Taplo
toml-format:
name: TOML Format
uses: ./.github/workflows/toml-format.yml
permissions:
contents: read
# Markdown table formatting check
table-format:
name: Table Format
uses: ./.github/workflows/table-format.yml
permissions:
contents: read
# Frontmatter validation for markdown files
frontmatter-validation:
name: Frontmatter Validation
uses: ./.github/workflows/frontmatter-validation.yml
with:
changed-files-only: false
permissions:
contents: read
# PowerShell script analysis
psscriptanalyzer:
name: PSScriptAnalyzer
uses: ./.github/workflows/ps-script-analyzer.yml
with:
changed-files-only: false
permissions:
contents: read
# YAML/actionlint workflow linting
yaml-lint:
name: YAML Lint
uses: ./.github/workflows/yaml-lint.yml
with:
changed-files-only: false
permissions:
contents: read
# Link language locale check
link-lang-check:
name: Link Language Check
uses: ./.github/workflows/link-lang-check.yml
permissions:
contents: read
# Markdown link validation
markdown-link-check:
name: Markdown Link Check
uses: ./.github/workflows/markdown-link-check.yml
permissions:
contents: read
# SHA pinning compliance for GitHub Actions and dependencies
dependency-pinning:
name: Dependency Pinning
uses: ./.github/workflows/dependency-pinning-scan.yml
permissions:
contents: read
security-events: write # Required for SARIF upload to Security tab
with:
upload-sarif: true
exclude-paths: 'scripts/tests/Fixtures/**,shared/ci/tests/Fixtures/**'
# PowerShell Pester test execution
pester-tests:
name: Pester Tests
uses: ./.github/workflows/pester-tests.yml
with:
changed-files-only: false
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: training component
pytest-training:
name: Pytest Training
uses: ./.github/workflows/pytest-training.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: data-management/tools component
pytest-dm-tools:
name: Pytest DM Tools
uses: ./.github/workflows/pytest-dm-tools.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: data-pipeline component
pytest-data-pipeline:
name: Pytest Data Pipeline
uses: ./.github/workflows/pytest-data-pipeline.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: inference component
pytest-inference:
name: Pytest Inference
uses: ./.github/workflows/pytest-inference.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Pytest: gpu-offload controller and runtime components
pytest-gpu-offload:
name: Pytest GPU Offload
uses: ./.github/workflows/pytest-gpu-offload.yml
permissions:
contents: read
# Pytest: shared CI scripts component
pytest-shared-ci:
name: Pytest Shared CI
uses: ./.github/workflows/pytest-shared-ci.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Dataviewer frontend lint, type-check, and build
dataviewer-frontend-tests:
name: Dataviewer Frontend Tests
uses: ./.github/workflows/dataviewer-frontend-tests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Dataviewer backend pytest execution
dataviewer-backend-pytests:
name: Dataviewer Backend Pytest
uses: ./.github/workflows/dataviewer-backend-pytests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Evaluation domain pytest execution
evaluation-pytests:
name: Evaluation Pytest
uses: ./.github/workflows/evaluation-pytests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Fuzz regression via deterministic corpus-based tests
fuzz-regression-tests:
name: Fuzz Regression Tests
uses: ./.github/workflows/fuzz-regression-tests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write
# Python linting using ruff
python-lint:
name: Python Lint
uses: ./.github/workflows/python-lint.yml
permissions:
contents: read
# Terraform linting using TFLint
terraform-lint:
name: Terraform Lint
uses: ./.github/workflows/terraform-lint.yml
with:
soft-fail: false
permissions:
contents: read
# Terraform format and validate checks
terraform-validation:
name: Terraform Validation
uses: ./.github/workflows/terraform-validation.yml
with:
soft-fail: false
permissions:
contents: read
# Terraform test execution with Codecov Test Analytics
terraform-tests:
name: Terraform Tests
uses: ./.github/workflows/terraform-tests.yml
with:
soft-fail: true
code-coverage: true
permissions:
contents: read
id-token: write
# Go linting using golangci-lint
go-lint:
name: Go Lint
uses: ./.github/workflows/go-lint.yml
with:
soft-fail: false
permissions:
contents: read
# Go tests
go-tests:
name: Go Tests
uses: ./.github/workflows/go-tests.yml
with:
soft-fail: false
code-coverage: true
permissions:
contents: read
id-token: write
# ShellCheck linting for shell scripts
shellcheck:
name: ShellCheck
uses: ./.github/workflows/shellcheck.yml
with:
soft-fail: false
permissions:
contents: read
# Terraform documentation freshness check
terraform-docs-check:
name: Terraform Docs Check
uses: ./.github/workflows/terraform-docs-check.yml
with:
soft-fail: true
permissions:
contents: read
# CodeQL security analysis
codeql-analysis:
name: CodeQL Analysis
uses: ./.github/workflows/codeql-analysis.yml
permissions:
contents: read
security-events: write
actions: read
# GPU-free import smoke gate. No path filter on main: run every domain depth.
smoke:
name: Smoke
uses: ./.github/workflows/smoke-cpu.yml
with:
rl: true
il: true
evaluation: true
osmo_replay: true
dataviewer: true
permissions:
contents: read
# Automated release PR management via release-please
release-please:
needs:
- spell-check
- markdown-lint
- toml-format
- table-format
- frontmatter-validation
- psscriptanalyzer
- yaml-lint
- link-lang-check
- markdown-link-check
- dependency-pinning
- pester-tests
- pytest-training
- pytest-dm-tools
- pytest-data-pipeline
- pytest-inference
- pytest-gpu-offload
- pytest-shared-ci
- dataviewer-frontend-tests
- dataviewer-backend-pytests
- evaluation-pytests
- python-lint
- terraform-lint
- terraform-validation
- terraform-tests
- go-lint
- go-tests
- shellcheck
- terraform-docs-check
- codeql-analysis
name: Release Please
runs-on: ubuntu-latest
concurrency:
group: release-please-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
id-token: write
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
version: ${{ steps.release.outputs.version }}
major: ${{ steps.release.outputs.major }}
minor: ${{ steps.release.outputs.minor }}
patch: ${{ steps.release.outputs.patch }}
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Run release-please
id: release
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
with:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
manifest-file: release-please-manifest.json
# On release commits, skip PR creation to prevent bogus PRs
# from draft release lazy tag timing. Release commits have zero
# unreleased changes so skipping loses nothing. The tag is
# created in the next step, ensuring subsequent runs find it.
skip-github-pull-request: ${{ github.event_name == 'push' && startsWith(github.event.head_commit.message, 'chore(main)') }}
- name: Checkout release PR branch
if: ${{ steps.release.outputs.prs_created == 'true' }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
token: ${{ steps.app-token.outputs.token }}
persist-credentials: false
- name: Setup uv
if: ${{ steps.release.outputs.prs_created == 'true' }}
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
- name: Regenerate uv.lock
if: ${{ steps.release.outputs.prs_created == 'true' }}
shell: bash
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
uv lock
if git diff --quiet -- uv.lock; then
echo "uv.lock is already up to date"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git add uv.lock
git commit -m "chore: regenerate uv.lock"
git push
- name: Stamp ms.date in CHANGELOG.md
if: ${{ steps.release.outputs.prs_created == 'true' }}
shell: pwsh
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: ./scripts/ci/Update-ChangelogMsDate.ps1
- name: Checkout default branch for tag signing
if: ${{ steps.release.outputs.release_created == 'true' }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
token: ${{ steps.app-token.outputs.token }}
fetch-depth: 0
- name: Install gitsign
if: ${{ steps.release.outputs.release_created == 'true' }}
run: ./scripts/ci/Install-Gitsign.ps1
# Workaround: release-please with "draft": true uses lazy tag
# creation. The git tag is not materialized until the release is
# published. Without the tag, release-please cannot find the draft
# on subsequent runs, breaking version anchoring and causing bogus
# changelog entries. The skip-github-pull-request conditional above
# prevents PR creation on release commits (zero unreleased changes),
# and this step creates a signed tag so subsequent runs find the release.
# Replace both workarounds with "force-tag-creation": true in
# release-please-config.json once release-please-action ships a
# version that includes googleapis/release-please#2627.
- name: Create signed git tag for draft release
if: ${{ steps.release.outputs.release_created == 'true' }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
TAG_NAME: ${{ steps.release.outputs.tag_name }}
run: ./scripts/ci/New-SignedReleaseTag.ps1
- name: Verify signed git tag
if: ${{ steps.release.outputs.release_created == 'true' }}
shell: bash
env:
TAG_NAME: ${{ steps.release.outputs.tag_name }}
run: |
tag_type="$(git cat-file -t "refs/tags/${TAG_NAME}")"
if [ "${tag_type}" != "tag" ]; then
echo "Expected annotated tag object for ${TAG_NAME}, found ${tag_type}"
exit 1
fi
gitsign verify-tag \
--certificate-identity 'https://github.com/microsoft/physical-ai-toolchain/.github/workflows/main.yml@refs/heads/main' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"${TAG_NAME}"
# Generate dependency SBOM from all package manifests
generate-dependency-sbom:
if: ${{ needs.release-please.outputs.release_created == 'true' }}
needs: [release-please]
name: Generate Dependency SBOM
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout dependency manifests
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: |
.syft.yaml
package.json
package-lock.json
pyproject.toml
uv.lock
data-pipeline/pyproject.toml
data-pipeline/uv.lock
evaluation/pyproject.toml
evaluation/uv.lock
training/rl/pyproject.toml
training/rl/uv.lock
training/il/lerobot/pyproject.toml
training/il/lerobot/uv.lock
workflows/osmo/pyproject.toml
workflows/osmo/uv.lock
data-management/viewer/pyproject.toml
data-management/viewer/uv.lock
data-management/viewer/package.json
data-management/viewer/backend/pyproject.toml
data-management/viewer/backend/uv.lock
data-management/viewer/frontend/package.json
data-management/viewer/frontend/package-lock.json
docs/docusaurus/package.json
docs/docusaurus/package-lock.json
infrastructure/terraform/e2e/go.mod
- name: Generate dependency SBOM
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
path: .
format: spdx-json
config: .syft.yaml
output-file: dependencies.spdx.json
artifact-name: ''
dependency-snapshot: true
syft-version: v1.20.0
- name: Generate dependency SBOM (CycloneDX)
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
path: .
format: cyclonedx-json
config: .syft.yaml
output-file: dependencies.cdx.json
artifact-name: ''
dependency-snapshot: true
upload-artifact: false
syft-version: v1.20.0
- name: Upload dependency SBOM artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-dependencies
path: dependencies.spdx.json
- name: Upload dependency SBOM (CycloneDX) artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom-dependencies-cdx
path: dependencies.cdx.json
- name: Upload dependency SBOM to release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
gh release upload "${TAG}" \
dependencies.spdx.json \
dependencies.cdx.json \
--clobber
shell: bash
# Sign release artifacts and generate SBOM attestation
attest-release:
if: ${{ needs.release-please.outputs.release_created == 'true' }}
needs: [release-please, generate-dependency-sbom]
name: Attest Release
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Download dependency SBOM
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sbom-dependencies
- name: Create source archive
env:
TAG: ${{ needs.release-please.outputs.tag_name }}
run: git archive --format=tar.gz --prefix="${TAG}/" HEAD -o "source-${TAG}.tar.gz"
shell: bash
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.12'
- name: Set up uv
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
- name: Build release wheel
run: uv build --wheel --out-dir dist
shell: bash
- name: Sign release wheel (keyless Sigstore)
run: |
python -m pip install sigstore==4.3.0
sigstore sign dist/*.whl
shell: bash
- name: Generate SBOM
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
path: .
format: spdx-json
output-file: sbom.spdx.json
artifact-name: ''
syft-version: v1.20.0
- name: Generate SBOM (CycloneDX)
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
path: .
format: cyclonedx-json
output-file: sbom.cdx.json
artifact-name: ''
upload-artifact: false
syft-version: v1.20.0
- name: Attest build provenance
id: attest
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: "source-${{ needs.release-please.outputs.tag_name }}.tar.gz"
- name: Attest wheel build provenance
id: attest-wheel
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: dist/*.whl
- name: Attest SBOM
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: "source-${{ needs.release-please.outputs.tag_name }}.tar.gz"
sbom-path: sbom.spdx.json
- name: Attest dependency SBOM
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: "source-${{ needs.release-please.outputs.tag_name }}.tar.gz"
sbom-path: dependencies.spdx.json
- name: Attest SBOM (CycloneDX)
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: "source-${{ needs.release-please.outputs.tag_name }}.tar.gz"
sbom-path: sbom.cdx.json
- name: Create signing artifacts for Scorecard detection
env:
BUNDLE_PATH: ${{ steps.attest.outputs.bundle-path }}
WHEEL_BUNDLE_PATH: ${{ steps.attest-wheel.outputs.bundle-path }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: ./scripts/ci/New-SigningArtifacts.ps1
- name: Upload release assets
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
gh release upload "${TAG}" \
"source-${TAG}.tar.gz" \
sbom.spdx.json \
sbom.cdx.json \
"source-${TAG}.sigstore.json" \
"source-${TAG}.intoto.jsonl" \
"wheels-${TAG}.sigstore.json" \
"wheels-${TAG}.intoto.jsonl" \
dist/*.whl \
dist/*.sigstore.json \
--clobber
shell: bash
# Compare dependency SBOM against previous release
sbom-diff:
if: ${{ needs.release-please.outputs.release_created == 'true' }}
needs: [release-please, generate-dependency-sbom]
name: SBOM Diff
runs-on: ubuntu-latest
continue-on-error: true
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Download current dependency SBOM
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sbom-dependencies
- name: Download previous release SBOM
id: prev-sbom
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
prev_tag=$(gh release list --repo "$GITHUB_REPOSITORY" --limit 10 --json tagName,isDraft --jq '[.[] | select(.tagName != env.TAG and .isDraft == false)] | first | .tagName // empty')
if [ -z "$prev_tag" ]; then
echo "No previous release found"
echo "found=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Previous release: $prev_tag"
gh release download "$prev_tag" --repo "$GITHUB_REPOSITORY" --pattern "dependencies.spdx.json" --dir previous || {
echo "No dependency SBOM in previous release $prev_tag"
echo "found=false" >> "$GITHUB_OUTPUT"
exit 0
}
echo "found=true" >> "$GITHUB_OUTPUT"
shell: bash
- name: Generate dependency diff
if: steps.prev-sbom.outputs.found == 'true'
run: python3 shared/ci/generate-dependency-diff.py dependencies.spdx.json previous/dependencies.spdx.json dependency-diff.md
- name: Upload dependency diff to release
if: steps.prev-sbom.outputs.found == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
gh release upload "${TAG}" \
dependency-diff.md \
--clobber
shell: bash
# Append attestation verification instructions to release notes
append-verification-notes:
if: ${{ needs.release-please.outputs.release_created == 'true' }}
needs: [release-please, attest-release]
name: Append Verification Notes
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Append verification instructions
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.release-please.outputs.tag_name }}
run: ./scripts/ci/Add-ReleaseVerificationNotes.ps1
# Promote draft release to published
publish-release:
if: ${{ needs.release-please.outputs.release_created == 'true' }}
needs: [release-please, attest-release, sbom-diff, append-verification-notes]
name: Publish Release
runs-on: ubuntu-latest
concurrency:
group: release-please-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Publish draft release
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
run: gh release edit $env:TAG_NAME --draft=false --repo $env:GITHUB_REPOSITORY
- name: Close released milestone
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
run: ./scripts/ci/Close-ReleaseMilestone.ps1