-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[OPIK-7793] [FE] ci: run the frontend checks with the private ai-spend plugin staged #7891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
andriidudar
wants to merge
5
commits into
main
Choose a base branch
from
andriid/OPIK-7793-ci-plugin-typecheck
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
6dc84ba
[OPIK-7793] [FE] ci: run the frontend checks with the private ai-spen…
andriidudar 825c40d
ci(frontend): give the exact reproduction commands in the failure ann…
andriidudar d498baa
ci(frontend): address Liya's review — trigger types, staging order, r…
andriidudar e947b8e
ci(frontend): strip CR before parsing ai-spend-plugin-ref
andriidudar 3d4c601
ci(frontend): distinguish the two 'staging produced nothing' error ti…
andriidudar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| name: Frontend Private Plugin Checks | ||
| run-name: "Frontend Private Plugin Checks ${{ github.ref_name }} by @${{ github.actor }}" | ||
|
|
||
| # The comet frontend image compiles comet-ml/opik-plugin-ai-spend, checked out at | ||
| # build time into src/plugins/ai-spend. Nothing else here compiles it, so a | ||
| # breaking change to a shared surface it imports passes every check on the PR | ||
| # that makes it and only fails later, in the image build. This runs the frontend | ||
| # checks with the plugin staged the same way the image stages it. | ||
| # | ||
| # For a change that intentionally breaks the plugin, name the plugin branch that | ||
| # adapts to it in the PR body, then merge the plugin PR first: | ||
| # | ||
| # ai-spend-plugin-ref: someone/my-branch | ||
| # | ||
| # Same-repo PRs get the token; that is the standard model this repo already | ||
| # uses for other secrets (e.g. typescript_sdk_e2e_tests.yml), and this repo | ||
| # additionally requires maintainer approval before any workflow runs for a | ||
| # first-time/outside contributor. Fork PRs get no token at all, from GitHub | ||
| # itself, regardless of what any workflow file says. | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - "apps/opik-frontend/**" | ||
| # A change to this check, or to the workflow that controls how the real | ||
| # image stages this same plugin, should re-run it. | ||
| - ".github/workflows/frontend_private_plugin_checks.yml" | ||
|
andriidudar marked this conversation as resolved.
|
||
| - ".github/workflows/build_and_push_docker.yaml" | ||
| workflow_dispatch: | ||
| inputs: | ||
| ai_spend_plugin_ref: | ||
| type: string | ||
| required: false | ||
| description: ai-spend plugin ref | ||
| default: "main" | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | ||
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
|
|
||
| jobs: | ||
| checks: | ||
| name: Checks with ai-spend plugin | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| fetch-depth: 1 | ||
| persist-credentials: false | ||
|
|
||
|
andriidudar marked this conversation as resolved.
|
||
| # Token availability checked first: without one, the job exits green with | ||
| # a notice, before ref parsing -- a malformed ai-spend-plugin-ref must | ||
| # never fail a fork event, since nothing downstream would use it anyway. | ||
| - name: Resolve plugin ref and token availability | ||
| id: resolve | ||
| env: | ||
| HAS_TOKEN: ${{ secrets.OPIK_PLUGIN_AI_SPEND_TOKEN != '' }} | ||
| DISPATCH_REF: ${{ inputs.ai_spend_plugin_ref }} | ||
| PR_BODY: ${{ github.event.pull_request.body }} | ||
| run: | | ||
| set -euo pipefail | ||
| echo "has_token=${HAS_TOKEN}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| if [ "${HAS_TOKEN}" != "true" ]; then | ||
| echo "::notice title=ai-spend plugin not checked::No access to the private plugin repository from this event. The plugin was not checked." | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Fenced blocks are skipped: a PR that documents this syntax in an | ||
| # example must not be taken as using it. | ||
| ref="${DISPATCH_REF:-}" | ||
| if [ -z "${ref}" ]; then | ||
| ref="$(printf '%s' "${PR_BODY:-}" \ | ||
| | awk '/^[[:space:]]*```/ { fenced = !fenced; next } !fenced' \ | ||
| | grep -iEm1 '^[[:space:]]*ai-spend-plugin-ref:[[:space:]]*[^[:space:]]+' \ | ||
| | sed -E 's/^[^:]*:[[:space:]]*//' \ | ||
| | tr -d '[:space:]' || true)" | ||
| fi | ||
| ref="${ref:-main}" | ||
|
andriidudar marked this conversation as resolved.
|
||
|
|
||
| if ! printf '%s' "${ref}" | grep -qE '^[A-Za-z0-9._/-]+$'; then | ||
| echo "::error title=Invalid ai-spend-plugin-ref::'${ref}' is not a valid git ref." | ||
| exit 1 | ||
|
andriidudar marked this conversation as resolved.
|
||
| fi | ||
|
|
||
| echo "ref=${ref}" >> "$GITHUB_OUTPUT" | ||
| echo "Plugin ref: ${ref}" | ||
|
|
||
| - name: Checkout ai-spend plugin (private) | ||
| if: steps.resolve.outputs.has_token == 'true' | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| repository: comet-ml/opik-plugin-ai-spend | ||
| ref: ${{ steps.resolve.outputs.ref }} | ||
| token: ${{ secrets.OPIK_PLUGIN_AI_SPEND_TOKEN }} | ||
| path: .ai-spend-plugin | ||
| fetch-depth: 1 | ||
| persist-credentials: false | ||
|
andriidudar marked this conversation as resolved.
|
||
|
|
||
| # Same staging as the image build. Asserted non-empty, and specifically | ||
| # checked for the manifest PluginsStore actually loads by name -- a layout | ||
| # change that drops or misnames manifest.ts would otherwise leave | ||
| # production silently without the plugin's routes while this still passed | ||
| # on an unrelated .ts file count. | ||
| - name: Stage ai-spend plugin into frontend src | ||
| if: steps.resolve.outputs.has_token == 'true' | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p apps/opik-frontend/src/plugins/ai-spend | ||
| cp -R .ai-spend-plugin/src/. apps/opik-frontend/src/plugins/ai-spend/ | ||
|
andriidudar marked this conversation as resolved.
|
||
| rm -rf .ai-spend-plugin | ||
|
|
||
| count="$(find apps/opik-frontend/src/plugins/ai-spend -type f \( -name '*.ts' -o -name '*.tsx' \) | wc -l | tr -d ' ')" | ||
| if [ "${count}" -eq 0 ]; then | ||
| echo "::error title=Plugin staging produced nothing::Copied 0 TypeScript files. The plugin's src layout likely changed." | ||
| exit 1 | ||
| fi | ||
|
|
||
| manifest=apps/opik-frontend/src/plugins/ai-spend/manifest.ts | ||
| if [ ! -f "${manifest}" ] || ! grep -qE 'name:[[:space:]]*"ai-spend"' "${manifest}"; then | ||
| echo "::error title=Plugin manifest missing or misnamed::PluginsStore loads plugins by the name declared in plugins/*/manifest.ts. ${manifest} is missing, or no longer declares name: \"ai-spend\" -- production would silently drop the plugin's routes." | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Staged ${count} TypeScript files from the plugin; manifest present and named correctly." | ||
|
|
||
| - name: Set up Node.js | ||
| if: steps.resolve.outputs.has_token == 'true' | ||
| uses: actions/setup-node@v7 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Install dependencies | ||
| if: steps.resolve.outputs.has_token == 'true' | ||
| run: npm ci | ||
| working-directory: apps/opik-frontend | ||
|
|
||
| # All three run even if an earlier one fails, so a PR sees every problem in | ||
| # one go. eslint is scoped to the plugin: core files are already linted by | ||
| # the code quality workflow. | ||
| - name: Typecheck, lint and validate dependencies | ||
| if: steps.resolve.outputs.has_token == 'true' | ||
| working-directory: apps/opik-frontend | ||
| run: | | ||
| set -uo pipefail | ||
| failed=0 | ||
|
|
||
| echo "::group::typecheck" | ||
| npm run typecheck || failed=1 | ||
| echo "::endgroup::" | ||
|
|
||
| echo "::group::eslint (plugin sources)" | ||
| npx eslint src/plugins/ai-spend --max-warnings=0 || failed=1 | ||
|
andriidudar marked this conversation as resolved.
|
||
| echo "::endgroup::" | ||
|
|
||
| echo "::group::dependency-cruiser" | ||
| npm run deps:validate || failed=1 | ||
| echo "::endgroup::" | ||
|
|
||
| if [ "${failed}" -ne 0 ]; then | ||
| echo "::error title=Frontend checks fail with the ai-spend plugin staged::Reproduce locally: symlink or copy a sibling opik-plugin-ai-spend checkout's src/ into apps/opik-frontend/src/plugins/ai-spend, then from apps/opik-frontend run: npm run typecheck && npx eslint src/plugins/ai-spend --max-warnings=0 && npm run deps:validate. (bash scripts/dev-runner.sh --lint-fe is close but not equivalent -- it lints the whole src tree with --fix, plus stylelint, none of which this check runs.) Keep the shared surface backward compatible, or land the matching plugin change first and add 'ai-spend-plugin-ref: <branch>' to this PR body." | ||
| exit 1 | ||
|
andriidudar marked this conversation as resolved.
|
||
| fi | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.