Conversation
There was a problem hiding this comment.
Pull request overview
Adds Playwright E2E coverage for core “video manager” user flows in video-manager-frontend, introducing new spec files plus Page Object Model abstractions and a helper to ensure items exist before running item-dependent tests.
Changes:
- Added E2E specs for navigation, items browsing/filtering, tagging mode, tags management, and collections lifecycle.
- Introduced new Page Object Model classes for the above areas to centralize locators and actions.
- Added a sync helper to trigger provider sync when the items list is empty.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| video-manager-frontend/tests/tags.spec.ts | E2E flow for creating, renaming, and deleting tags. |
| video-manager-frontend/tests/tagging.spec.ts | E2E flow for tagging mode navigation and tag add/remove behavior. |
| video-manager-frontend/tests/navigation.spec.ts | Verifies drawer navigation across major routes. |
| video-manager-frontend/tests/items.spec.ts | Verifies items list loads, filtering works, and tagging-mode navigation. |
| video-manager-frontend/tests/collections.spec.ts | E2E flow for collection create → detail → collection mode → delete. |
| video-manager-frontend/tests/helpers/sync.helper.ts | Helper to trigger sync when items are not present. |
| video-manager-frontend/tests/pages/tags.page.ts | Tags page object (create/rename/delete + assertions). |
| video-manager-frontend/tests/pages/tagging.page.ts | Tagging mode page object (overlay interactions + navigation). |
| video-manager-frontend/tests/pages/navigation.page.ts | Navigation drawer page object (drawer open + link navigation). |
| video-manager-frontend/tests/pages/items.page.ts | Items page object (load assertions, filtering, navigation). |
| video-manager-frontend/tests/pages/collections.page.ts | Collections list page object (create/open/delete + assertions). |
| video-manager-frontend/tests/pages/collection-detail.page.ts | Collection detail page object (visibility/empty state + mode entry). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…n permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async renameTag(currentName: string, newName: string) { | ||
| const heading = this.page.getByRole('heading', { name: currentName, exact: true }); | ||
| // Edit button is the first button in the card header's button group | ||
| await heading.locator('xpath=../..//button[1]').click(); | ||
|
|
||
| await this.page.locator('#editTagName').fill(newName); | ||
| await this.page.getByRole('button', { name: 'Rename' }).click(); | ||
| await expect(this.page.getByRole('dialog')).not.toBeVisible({ timeout: 5000 }); | ||
| } | ||
|
|
||
| async deleteTag(name: string) { | ||
| const heading = this.page.getByRole('heading', { name, exact: true }); | ||
| // Delete button is the second button in the card header's button group | ||
| await heading.locator('xpath=../..//button[2]').click(); | ||
|
|
There was a problem hiding this comment.
The edit/delete interactions rely on XPath with positional button indices (//button[1], //button[2]). This is brittle if the card header structure changes (or if additional buttons are added). Prefer locating the specific buttons via accessible names (adding aria-labels in the UI if needed) or scoping to the card container and using role-based locators with stable selectors.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
|
@copilot please solve comments and ensure PR Checks goes green. |
- Add aria-labels to edit/delete buttons in tags UI - Replace brittle XPath selectors with stable aria-label selectors - Scope tagging overlay locators to .relative.aspect-video container - Use exact string match for tag buttons instead of RegExp - Increase sync timeout to 10s and verify items after sync - Scope media type filter to correct section - Add try/finally cleanup to tags and collections tests - Add dotnet tool restore step to CI workflow Co-authored-by: inur93 <5747088+inur93@users.noreply.github.com>
fix: improve E2E test stability and CI reliability
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sonar-project.properties
Outdated
| sonar.sources=VideoManager/VManBackend,video-manager-frontend/src | ||
| sonar.tests=video-manager-frontend/tests |
There was a problem hiding this comment.
sonar.sources includes the .NET backend, but the workflow runs the generic SonarSource/sonarcloud-github-action, which uses the CLI scanner and will not perform C# analysis without the SonarScanner for .NET (MSBuild) integration. Either switch to the .NET scanner flow (begin/build/test/end) for VideoManager/VManBackend, or limit sonar.sources to the frontend so the analysis results are accurate.
.github/workflows/verify.yml
Outdated
| - name: SonarCloud Scan | ||
| uses: SonarSource/sonarqube-scan-action@v5 | ||
| env: |
There was a problem hiding this comment.
The SonarCloud job uses the generic SonarSource/sonarcloud-github-action without a build step. With sonar.sources pointing at VideoManager/VManBackend (C#), this setup typically won’t analyze C# correctly unless you run the SonarScanner for .NET (MSBuild) workflow (begin/build/test/end) and pass the appropriate parameters. Consider updating this job accordingly (or splitting frontend vs backend analysis) to avoid misleading SonarCloud results.
Replace brittle XPath selectors with aria-label in tags e2e tests
test: critical e2e test for all features
| name: SonarQube | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| - name: SonarQube Scan | ||
| uses: SonarSource/sonarqube-scan-action@v6 | ||
| with: | ||
| projectBaseDir: video-manager-frontend | ||
| env: | ||
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} No newline at end of file |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 16 days ago
In general, the fix is to explicitly declare permissions for the workflow or for the specific job, restricting the GITHUB_TOKEN to the least privileges needed. Since this job only checks out the repository and runs an external SonarQube scan using SONAR_TOKEN, it only needs read access to repository contents.
The best minimal fix, without changing existing functionality, is to add a permissions block at the workflow root (so it applies to all jobs) specifying contents: read. This will ensure the GITHUB_TOKEN cannot perform write operations while still allowing actions/checkout@v4 to function. Concretely, in .github/workflows/frontend-build.yml, insert:
permissions:
contents: readbetween the on: block and the jobs: block (i.e., after line 7 and before line 8). No new imports or methods are needed, since this is purely a YAML configuration change.
| @@ -5,6 +5,8 @@ | ||
| - master | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| sonarqube: | ||
| name: SonarQube |
|
This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation. |
.github/workflows/backend-build.yml
Outdated
| name: Build and analyze | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Set up JDK 17 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| java-version: 17 | ||
| distribution: 'zulu' # Alternative distribution options are available. | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| - name: Cache SonarQube Cloud packages | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ~\sonar\cache | ||
| key: ${{ runner.os }}-sonar | ||
| restore-keys: ${{ runner.os }}-sonar | ||
| - name: Cache SonarQube Cloud scanner | ||
| id: cache-sonar-scanner | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ${{ runner.temp }}\scanner | ||
| key: ${{ runner.os }}-sonar-scanner | ||
| restore-keys: ${{ runner.os }}-sonar-scanner | ||
| - name: Install SonarQube Cloud scanner | ||
| if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' | ||
| shell: pwsh | ||
| run: | | ||
| New-Item -Path ${{ runner.temp }}\scanner -ItemType Directory | ||
| dotnet tool update dotnet-sonarscanner --tool-path ${{ runner.temp }}\scanner | ||
| - name: Build and analyze | ||
| env: | ||
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | ||
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: | | ||
| ${{ runner.temp }}\scanner\dotnet-sonarscanner begin /k:"vormadal_vman_backend" /o:"vormadal" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" | ||
| dotnet build | ||
| ${{ runner.temp }}\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" No newline at end of file |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 16 days ago
In general, the fix is to explicitly define a permissions block in the workflow (at the root or per job) so that the GITHUB_TOKEN is limited to the least privileges required. For this workflow, the job only needs to read repository contents (for actions/checkout) and does not perform any write operations to the repo or GitHub resources, so contents: read is sufficient as a minimal baseline.
The single best fix without changing existing functionality is to add a permissions section under the build job in .github/workflows/backend-build.yml. This will scope the permissions to that job only and will not affect other workflows. Insert:
permissions:
contents: readdirectly under runs-on: ubuntu-latest (line 8), keeping indentation consistent (two extra spaces under the job). No imports or additional methods are needed; this is a pure YAML configuration change.
| @@ -6,6 +6,8 @@ | ||
| build: | ||
| name: Build and analyze | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
|
|
||
| steps: | ||
| - name: Set up JDK 17 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 25 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dotnet-version: "10.0.101" | ||
| - name: Build backend | ||
| shell: pwsh | ||
| working-directory: VideoManager |
There was a problem hiding this comment.
dotnet run is executed with working-directory: VideoManager, but that directory doesn’t contain a project file (only a solution). This is likely to fail or run an unintended project. Use dotnet run --project <path-to-csproj> (or build/run the intended backend/AppHost explicitly).
| working-directory: VideoManager | |
| working-directory: ./VideoManager/VManBackend |
.github/workflows/playwright.yml
Outdated
| - uses: actions/setup-dotnet@v5 | ||
| with: | ||
| dotnet-version: "10.0.101" | ||
| - name: Build backend | ||
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: dotnet run & echo $! > backend.pid | ||
|
|
||
| - name: Install Playwright Browsers | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright install --with-deps | ||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npm run test:e2e | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" | ||
|
|
There was a problem hiding this comment.
The workflow no longer provisions Postgres or applies EF migrations / config used by the backend. VManBackend is configured to use Npgsql (see appsettings) and the E2E tests trigger sync/tag/collection flows that depend on a working DB and a reachable Immich endpoint (previously stubbed). Reintroduce the Postgres service + migration step and the backend env vars (e.g., stub Immich/base URL, connection string) so CI matches the expected test environment.
.github/workflows/playwright.yml
Outdated
| - name: Build backend | ||
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: dotnet run & echo $! > backend.pid | ||
|
|
||
| - name: Install Playwright Browsers | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright install --with-deps | ||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npm run test:e2e | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" | ||
|
|
||
|
|
||
| - name: Stop backend | ||
| if: always() | ||
| working-directory: ./VideoManager/VManBackend | ||
| run: | | ||
| if [ -f backend.pid ]; then | ||
| kill $(cat backend.pid) || true | ||
| rm backend.pid | ||
| fi |
There was a problem hiding this comment.
The backend PID handling is inconsistent: the PID file is written in the VideoManager working directory (and uses $!, which is a bash variable, not PowerShell), but the stop step looks for backend.pid in ./VideoManager/VManBackend using a bash shell. Use a single shell consistently and write/read the PID file from the same directory, or use a built-in job/service mechanism.
| name: SonarQube | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| - name: SonarQube Scan | ||
| uses: SonarSource/sonarqube-scan-action@v6 | ||
| with: | ||
| projectBaseDir: video-manager-frontend | ||
| env: |
There was a problem hiding this comment.
video-manager-frontend/sonar-project.properties is configured for SonarCloud (sonar.organization and the comment references the SonarCloud UI), but this workflow uses SonarSource/sonarqube-scan-action@v6 (intended for SonarQube) without setting SONAR_HOST_URL. If the target is SonarCloud, switch to the SonarCloud action (or explicitly configure the host URL) so the scan runs against the correct service.
| name: SonarQube | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | |
| - name: SonarQube Scan | |
| uses: SonarSource/sonarqube-scan-action@v6 | |
| with: | |
| projectBaseDir: video-manager-frontend | |
| env: | |
| name: SonarCloud | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | |
| - name: SonarCloud Scan | |
| uses: SonarSource/sonarcloud-github-action@v2 | |
| with: | |
| projectBaseDir: video-manager-frontend | |
| env: | |
| SONAR_HOST_URL: https://sonarcloud.io |
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| - uses: actions/setup-dotnet@v5 | ||
| with: | ||
| dotnet-version: "10.0.101" | ||
| - name: Build backend | ||
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: dotnet run & echo $! > backend.pid | ||
|
|
||
| - name: Install Playwright Browsers | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright install --with-deps | ||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npm run test:e2e | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" |
There was a problem hiding this comment.
The Playwright CI workflow no longer installs Node dependencies or sets up Node (no npm ci / actions/setup-node), but it runs npx playwright install and npm run test:e2e. This will fail on a clean runner because npm dependencies (including Playwright) won’t be present. Add a Node setup step and install dependencies in video-manager-frontend before running Playwright.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dotnet-version: "10.0.101" | ||
|
|
||
| - name: Run Aspire | ||
| shell: pwsh |
There was a problem hiding this comment.
The “Run Aspire” step is using PowerShell (shell: pwsh) but bash-style backgrounding (&) and PID capture ($!). In PowerShell this won’t background the process and $! isn’t the child PID, so the job will hang on dotnet run and/or write an invalid PID file. Use a proper PowerShell background process (e.g., Start-Process -PassThru / Start-Job) or switch this step to shell: bash if you want to use &/$! semantics.
| shell: pwsh | |
| shell: bash |
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright test | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" | ||
| PLAYWRIGHT_BASE_URL: "http://localhost:3000" | ||
| TEST_USER_EMAIL: test.user@example.com | ||
| TEST_USER_PASSWORD: TestPassword123! | ||
|
|
There was a problem hiding this comment.
npx playwright test will start the dev server defined in video-manager-frontend/playwright.config.ts (webServer: { command: 'npm run dev', url: 'http://localhost:3000', reuseExistingServer: false on CI }). At the same time this workflow starts Aspire, which also starts the Next.js dev server on port 3000. This will lead to a port conflict / flaky startup in CI. Either disable Playwright’s webServer when running under Aspire (via env flag/conditional config) or don’t start the frontend via Aspire and let Playwright manage it.
.github/workflows/playwright.yml
Outdated
| - name: Stop backend | ||
| if: always() | ||
| working-directory: ./VideoManager/VManBackend | ||
| run: | | ||
| if [ -f backend.pid ]; then | ||
| kill $(cat backend.pid) || true | ||
| rm backend.pid | ||
| fi |
There was a problem hiding this comment.
The PID file is written in the “Run Aspire” step under working-directory: VideoManager, but the “Stop backend” step runs in ./VideoManager/VManBackend. As a result, backend.pid won’t be found and the Aspire process won’t be stopped. Write/read the PID file from a consistent location (or stop the distributed app via a more reliable mechanism).
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 27 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| this.newTagButton = page.getByRole('button', { name: /new tag/i }); | ||
| this.itemCountText = page.getByText(/showing \d+ of \d+/i); | ||
| } | ||
|
|
||
| async goto() { | ||
| await super.goto('/items'); | ||
| } | ||
|
|
||
| async expectToBeVisible() { | ||
| await expect(this.heading).toBeVisible(); | ||
| } | ||
|
|
||
| async expectItemsLoaded() { | ||
| await expect(this.itemCountText).toBeVisible({ timeout: 10000 }); | ||
| } |
There was a problem hiding this comment.
ItemsPage waits for /showing \d+ of \d+/ to indicate items loaded, but the actual Items page UI doesn't render any "showing X of Y" text. This will cause expectItemsLoaded() (and any helper that relies on it) to time out consistently. Update the locator/assertion to wait on a real, stable element from the Items page (e.g., the item grid/cards/thumbnail elements, or the disappearance of the loading state).
| // Re-navigate to items page and verify items are now available | ||
| await page.goto('/items'); | ||
| await page.waitForLoadState('domcontentloaded'); | ||
| await page.getByText(/showing \d+ of \d+/i).waitFor({ timeout: 10000 }); |
There was a problem hiding this comment.
Same issue as above: this final wait also depends on /showing \d+ of \d+/, which doesn't exist on the current Items page UI, so the helper will time out even after a successful sync. Update to wait for a real Items page signal.
| // Re-navigate to items page and verify items are now available | |
| await page.goto('/items'); | |
| await page.waitForLoadState('domcontentloaded'); | |
| await page.getByText(/showing \d+ of \d+/i).waitFor({ timeout: 10000 }); | |
| // Re-navigate to items page and verify the Items page has loaded | |
| await page.goto('/items'); | |
| await page.waitForLoadState('domcontentloaded'); | |
| await page.getByRole('heading', { name: /items/i }).waitFor({ timeout: 10000 }); |
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright test | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" | ||
| PLAYWRIGHT_BASE_URL: "http://localhost:3000" | ||
| TEST_USER_EMAIL: test.user@example.com | ||
| TEST_USER_PASSWORD: TestPassword123! | ||
|
|
There was a problem hiding this comment.
Playwright is configured to start a dev server via webServer: { command: 'npm run dev', url: 'http://localhost:3000' }. This workflow also starts Aspire, which already starts the Next.js frontend on port 3000. On CI (reuseExistingServer is false), Playwright will try to start another server on the same port and fail. Either don't start the frontend in Aspire for this job, or configure Playwright to reuse the existing server / disable webServer when Aspire is used, or run one of them on a different port.
| push: | ||
| branches: | ||
| - master | ||
| pull_request: |
There was a problem hiding this comment.
This workflow only runs on push to master, but other workflows and prior configuration in this repo target main/develop. If the default branch isn't master, this workflow will never run on pushes. Align the branch filter with the repository's actual default/release branches (or remove the push branch filter if not needed).
| const itemsPage = new ItemsPage(page); | ||
| await itemsPage.goto(); | ||
| await itemsPage.expectToBeVisible(); | ||
| await itemsPage.expectItemsLoaded(); | ||
|
|
There was a problem hiding this comment.
This test relies on ItemsPage.expectItemsLoaded() which currently waits for "showing X of Y" text that doesn't exist in the Items page UI. The test will fail even when items load correctly; update the Items page object / assertions to match the actual UI.
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: dotnet run --project VideoManager.AppHost & echo $! > backend.pid |
There was a problem hiding this comment.
The "Run Aspire" step is executed with shell: pwsh but uses Bash job control (&) and $! to capture the PID. In PowerShell, $! is not the background PID, so backend.pid will not contain the correct process id (and may be empty/incorrect), breaking the later stop step. Use PowerShell-native process launching (e.g., Start-Process / Start-Job) and capture the PID properly, or run this step in bash explicitly.
| shell: pwsh | |
| working-directory: VideoManager | |
| run: dotnet run --project VideoManager.AppHost & echo $! > backend.pid | |
| shell: bash | |
| working-directory: VideoManager | |
| run: dotnet run --project VideoManager.AppHost & echo $! > VManBackend/backend.pid |
.github/workflows/playwright.yml
Outdated
| - name: Stop backend | ||
| if: always() | ||
| working-directory: ./VideoManager/VManBackend | ||
| run: | | ||
| if [ -f backend.pid ]; then | ||
| kill $(cat backend.pid) || true | ||
| rm backend.pid | ||
| fi |
There was a problem hiding this comment.
The stop step looks for backend.pid under ./VideoManager/VManBackend, but the PID file is written by the Aspire step under the VideoManager working directory. As a result the backend process likely won't be stopped on CI. Write/read the PID file from a consistent path (or use pkill on the specific command), and ensure you're stopping the AppHost process you actually started.
| // Create and add a tag to current item | ||
| const tagName = `E2E Tagging ${Date.now()}`; | ||
| await taggingPage.createAndAddTag(tagName); | ||
|
|
||
| // Verify tag appears on the item overlay | ||
| await taggingPage.expectTagInOverlay(tagName); | ||
|
|
||
| // Remove the tag from overlay | ||
| await taggingPage.removeTagFromOverlay(tagName); | ||
|
|
||
| // Verify tag moved to available tags list | ||
| await taggingPage.expectTagInAvailableList(tagName); | ||
|
|
There was a problem hiding this comment.
This test creates a new tag via tagging mode but never removes it. Even with unique names, this can pollute state for later tests in the same run (longer tag lists, slower UI, unexpected matches). Consider deleting the created tag at the end (either via tagging mode UI or via the Tags page) or using a cleanup finally similar to tags.spec.ts.
| name: Build and analyze | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis | ||
| - uses: actions/setup-dotnet@v5 | ||
| with: | ||
| dotnet-version: "10.0.101" | ||
|
|
||
| - name: Run Aspire | ||
| shell: pwsh | ||
| working-directory: VideoManager | ||
| run: dotnet run --project VideoManager.AppHost & echo $! > backend.pid | ||
|
|
||
| - name: Install dependencies | ||
| working-directory: video-manager-frontend | ||
| run: npm ci | ||
|
|
||
| - name: Install Playwright Browsers | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright install --with-deps | ||
|
|
||
| - name: Wait for backend to be ready | ||
| run: | | ||
| for i in {1..30}; do | ||
| curl -s http://localhost:5001/health | ||
| if curl -s http://localhost:5001/health; then | ||
| echo "Backend is ready!" | ||
| exit 0 | ||
| fi | ||
| echo "Waiting for backend to be ready..." | ||
| sleep 2 | ||
| done | ||
| echo "Backend did not become ready in time." | ||
| exit 1 | ||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: video-manager-frontend | ||
| run: npx playwright test | ||
| env: | ||
| NEXT_PUBLIC_API_URL: "http://localhost:5001" | ||
| PLAYWRIGHT_BASE_URL: "http://localhost:3000" | ||
| TEST_USER_EMAIL: test.user@example.com | ||
| TEST_USER_PASSWORD: TestPassword123! | ||
|
|
||
| - name: Stop backend | ||
| if: always() | ||
| working-directory: ./VideoManager/VManBackend | ||
| run: | | ||
| if [ -f backend.pid ]; then | ||
| kill $(cat backend.pid) || true | ||
| rm backend.pid | ||
| fi | ||
|
|
||
| - uses: actions/upload-artifact@v4 | ||
| if: ${{ !cancelled() }} | ||
| with: | ||
| name: playwright-report | ||
| path: video-manager-frontend/playwright-report/ | ||
| retention-days: 30 |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 16 days ago
In general, the fix is to add an explicit permissions block limiting the GITHUB_TOKEN to the minimal scopes required. For this workflow, the steps only need to read the code and upload artifacts; they do not need to push commits, modify issues, or update pull requests. Therefore, setting permissions: contents: read at the job level (or workflow root) is sufficient and aligns with CodeQL’s suggestion.
The best fix with minimal functional change is to add a permissions block under the build job in .github/workflows/playwright.yml. This keeps the scope local to the job that actually runs, avoids assumptions about other jobs (none are shown), and documents that the job only requires read access to repository contents. Concretely, insert:
permissions:
contents: readbetween runs-on: ubuntu-latest (line 11) and steps: (line 13). No imports or additional methods are needed because this is a YAML workflow configuration change only.
| @@ -9,6 +9,8 @@ | ||
| build: | ||
| name: Build and analyze | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 |
|
|





No description provided.