feat(observability): add a local operations log for agent and schedul… #816
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Benchmark image — build + push to ECR (any adapter) | |
| # Adapter-agnostic image build. The bench image carries the full | |
| # ``tests/benchmarks/`` tree, so every registered adapter ships in the | |
| # same image. ``benchmark-run.yml`` selects which adapter actually runs | |
| # via its ``config`` input. See ``tests/benchmarks/_framework/registry.py`` | |
| # for the registration contract. | |
| # Builds tests/benchmarks/cloudopsbench/infra/Dockerfile.bench and pushes the resulting image to the | |
| # opensre-bench ECR repository. The bench container is what | |
| # `Benchmark run (manual)` invokes on AWS Fargate, so this workflow's | |
| # output is the input to that one. | |
| # | |
| # Triggered automatically on changes to the bench code (or the Dockerfile | |
| # itself) and manually via workflow_dispatch. | |
| # | |
| # After the image is pushed, update the task definition by re-applying the | |
| # Terraform with the new tag: | |
| # | |
| # cd tests/benchmarks/cloudopsbench/infra | |
| # terraform apply -var="image_tag=<TAG>" | |
| # | |
| # (Or wire a follow-up step into this workflow to update task definition | |
| # automatically — out of scope for v1.) | |
| # | |
| # Tag format: short git SHA (`git rev-parse --short HEAD`). Stable, unique | |
| # per commit, recognizable in `aws ecr describe-images` output. ECR is | |
| # IMMUTABLE — a tag pushed once cannot be overwritten, so re-running the | |
| # workflow on the same commit just re-tags (no-op layer push). | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: Image tag to push (default = short git SHA) | |
| required: false | |
| type: string | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - "tests/benchmarks/cloudopsbench/infra/Dockerfile.bench" | |
| - "tests/benchmarks/cloudopsbench/infra/Dockerfile.bench.dockerignore" | |
| - "pyproject.toml" | |
| - "uv.lock" | |
| - "surfaces/**" | |
| - "config/**" | |
| - "core/**" | |
| - "integrations/**" | |
| - "platform/**" | |
| - "tools/**" | |
| - "tests/benchmarks/**" | |
| - ".github/workflows/benchmark-image.yml" | |
| permissions: | |
| contents: read | |
| id-token: write # required for AWS OIDC role assumption | |
| concurrency: | |
| # Allow one in-flight build per ref so two pushes in quick succession | |
| # don't race ECR. The newer push cancels the older. | |
| group: bench-image-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| AWS_REGION: us-east-1 | |
| # Account ID is repo-level configuration, not a secret. Set as a GitHub | |
| # repository Variable (Settings > Secrets and variables > Actions > | |
| # Variables) so it doesn't need to be edited in every workflow file | |
| # when the bench moves accounts. | |
| ACCOUNT_ID: ${{ vars.AWS_ACCOUNT_ID }} | |
| ECR_REPOSITORY: opensre-bench | |
| jobs: | |
| build-and-push: | |
| if: github.repository == 'Tracer-Cloud/opensre' | |
| name: build + push | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| # Fetch enough history that `git rev-parse --short HEAD` is stable | |
| fetch-depth: 1 | |
| - name: Resolve image tag | |
| id: tag | |
| env: | |
| # Route `inputs.tag` through env so the shell treats it as DATA, | |
| # not code. Without this, a workflow_dispatch caller could inject | |
| # shell commands via a crafted `tag` value containing $() or | |
| # backticks. See: | |
| # https://securitylab.github.com/research/github-actions-untrusted-input/ | |
| INPUT_TAG: ${{ inputs.tag }} | |
| run: | | |
| if [ -n "$INPUT_TAG" ]; then | |
| TAG="$INPUT_TAG" | |
| else | |
| TAG="$(git rev-parse --short HEAD)" | |
| fi | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "Will push: $ECR_REPOSITORY:$TAG" | |
| - name: Configure AWS credentials (OIDC role assumption) | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/opensre-bench-github-actions | |
| role-session-name: github-actions-bench-image-${{ github.run_id }} | |
| aws-region: us-east-1 | |
| - name: Login to Amazon ECR | |
| id: ecr-login | |
| uses: aws-actions/amazon-ecr-login@v2 | |
| - name: Set up Docker Buildx | |
| # Buildx adds multi-platform support + better cache control. Even | |
| # for single-platform builds, it's the modern default. | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build and push | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: tests/benchmarks/cloudopsbench/infra/Dockerfile.bench | |
| platforms: linux/amd64 | |
| push: true | |
| tags: | | |
| ${{ steps.ecr-login.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ steps.tag.outputs.tag }} | |
| # Stamp the COMMIT SHA into the image so the runtime can read it | |
| # via the OPENSRE_SHA env var. We use github.sha (the full 40-char | |
| # commit being built), NOT steps.tag.outputs.tag (which resolves | |
| # to the user-supplied inputs.tag like ``hotfix-june`` on | |
| # workflow_dispatch and would stamp an unverifiable string as if | |
| # it were a SHA). The image tag (for ECR naming) and OPENSRE_SHA | |
| # (for provenance) are intentionally decoupled — the tag is for | |
| # humans/operators; the SHA is for reproducibility. The runtime | |
| # gate also validates SHA shape (7-40 lowercase hex chars), so | |
| # even a manually-built image with a bad OPENSRE_SHA fails loudly. | |
| build-args: | | |
| OPENSRE_SHA=${{ github.sha }} | |
| # GitHub Actions cache for Docker layers - speeds up rebuilds | |
| # when only the source changes (deps stay in the cached layer). | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: false # smaller manifest; matches ECR's tolerance for OCI | |
| - name: Summarise | |
| # Route step outputs through env so the shell sees them as DATA, | |
| # not code. `steps.tag.outputs.tag` is derived verbatim from the | |
| # `inputs.tag` user input — without env scoping, a workflow_dispatch | |
| # caller could inject shell commands here even though the | |
| # "Resolve image tag" step is hardened. Same risk applies to any | |
| # tag-derived chain. | |
| env: | |
| REGISTRY: ${{ steps.ecr-login.outputs.registry }} | |
| TAG: ${{ steps.tag.outputs.tag }} | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| run: | | |
| echo "## Image pushed" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| field | value |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| --- | --- |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| Registry | \`$REGISTRY\` |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| Repository | \`$ECR_REPOSITORY\` |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| Tag | \`$TAG\` |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "| Digest | \`$DIGEST\` |" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "To deploy this image:" >> "$GITHUB_STEP_SUMMARY" | |
| echo "" >> "$GITHUB_STEP_SUMMARY" | |
| echo "\`\`\`bash" >> "$GITHUB_STEP_SUMMARY" | |
| echo "cd tests/benchmarks/cloudopsbench/infra" >> "$GITHUB_STEP_SUMMARY" | |
| echo "terraform apply -var=\"image_tag=$TAG\"" >> "$GITHUB_STEP_SUMMARY" | |
| echo "\`\`\`" >> "$GITHUB_STEP_SUMMARY" |