From 06ba99231ba224e5a0f1d0b2e767d49b63ad2c64 Mon Sep 17 00:00:00 2001 From: "@daniel-lxs" <57051444+daniel-lxs@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:10:47 +0000 Subject: [PATCH 1/2] fix: let Fast mode inspect GitHub Actions failures --- apps/docs/providers/source-control/github.mdx | 17 ++++++ .../settings/SourceControl.test.tsx | 29 ++++++++++- .../src/components/settings/SourceControl.tsx | 52 ++++++++++++++++--- .../trpc/commands/github/mutations.test.ts | 25 ++++++++- .../web/src/trpc/commands/github/mutations.ts | 45 ++++++++++++++++ .../fast-agent-integration-broker.test.ts | 8 +++ .../fast-agent-integration-broker.ts | 5 +- .../router/__tests__/router-helpers.test.ts | 11 ++++ .../src/server/router/mcp-policy.ts | 5 +- 9 files changed, 186 insertions(+), 11 deletions(-) diff --git a/apps/docs/providers/source-control/github.mdx b/apps/docs/providers/source-control/github.mdx index 990832c6c..afab63af4 100644 --- a/apps/docs/providers/source-control/github.mdx +++ b/apps/docs/providers/source-control/github.mdx @@ -85,6 +85,23 @@ Grant these repository permissions: - **Pull requests**: Read and write - **Workflows**: Read and write +Fast mode needs at least **Actions: Read-only** to inspect workflow runs, jobs, +step conclusions, and available failure logs. The Roomote manifest requests +**Read and write** because other Roomote workflows can also manage Actions; Fast +mode still accesses GitHub through a read-only tool policy. + +If the GitHub App or installation predates the Actions permission, an app owner +must add **Actions: Read-only** or **Read and write** under **Permissions & +events**. GitHub then requires an installation owner to approve the updated +permission. In Roomote, open **Settings > Source control** and select **Approve +GitHub access**, then **Refresh GitHub**. A full reinstall is normally not +required, but uninstall and reinstall the app if GitHub does not offer the +permission approval for the existing installation. + +GitHub may remove logs after the repository's retention period or deny them for +an installation that lacks access. In those cases Roomote can report run, job, +and step metadata, but it will not claim to have inspected unavailable logs. + Subscribe to these events: - **Check run** diff --git a/apps/web/src/components/settings/SourceControl.test.tsx b/apps/web/src/components/settings/SourceControl.test.tsx index 17413f8f4..2ceabd966 100644 --- a/apps/web/src/components/settings/SourceControl.test.tsx +++ b/apps/web/src/components/settings/SourceControl.test.tsx @@ -8,7 +8,9 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { toast } from 'sonner'; const state = vi.hoisted(() => ({ - gitHubInstallations: [{ id: 'gh-1' }], + gitHubInstallations: [ + { id: 'gh-1', permissions: { actions: 'write' } }, + ] as Array<{ id: string; permissions: Record }>, gitHubRepositories: [ { id: 'repo-1', @@ -354,7 +356,9 @@ describe('SourceControl settings', () => { beforeEach(() => { vi.clearAllMocks(); state.searchParams = ''; - state.gitHubInstallations = [{ id: 'gh-1' }]; + state.gitHubInstallations = [ + { id: 'gh-1', permissions: { actions: 'write' } }, + ]; state.gitHubRepositories = [ { id: 'repo-1', @@ -562,6 +566,27 @@ describe('SourceControl settings', () => { ); }); + it('guides older GitHub installations through Actions permission approval', () => { + state.gitHubInstallations = [ + { id: 'gh-1', permissions: { contents: 'write' } }, + ]; + + render(); + + expect( + screen.getByText(/This installation cannot read GitHub Actions runs/), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'Approve GitHub access' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('link', { name: 'Review the setup steps' }), + ).toHaveAttribute( + 'href', + 'https://docs.roomote.dev/providers/source-control/github#permissions-and-events', + ); + }); + it('syncs GitLab repositories from the source control section', () => { render(); diff --git a/apps/web/src/components/settings/SourceControl.tsx b/apps/web/src/components/settings/SourceControl.tsx index 938403ca4..8a4e7fc29 100644 --- a/apps/web/src/components/settings/SourceControl.tsx +++ b/apps/web/src/components/settings/SourceControl.tsx @@ -58,6 +58,15 @@ import { SourceControlConfigForm } from './SourceControlConfigForm'; const INITIAL_REPO_COUNT = 100; +function hasGitHubActionsReadPermission(permissions: unknown): boolean { + if (!permissions || typeof permissions !== 'object') { + return false; + } + + const actions = (permissions as Record).actions; + return actions === 'read' || actions === 'write'; +} + type Repository = { id: string; fullName: string; @@ -243,6 +252,13 @@ export function SourceControl() { gitHubRepositories.isPending || sourceControlConfigStatus.isPending; const gitHubIsConnected = (gitHubInstallations.data?.length ?? 0) > 0; + const gitHubNeedsActionsPermission = + gitHubIsConnected && + (gitHubInstallations.data?.some( + (installation) => + !hasGitHubActionsReadPermission(installation.permissions), + ) ?? + false); const gitHubIsConfigured = isProviderConfigured( sourceControlConfigStatus.data, 'github', @@ -367,7 +383,11 @@ export function SourceControl() { disabled={enableGitHubApp.isPending} > {gitHubIsConnected ? : } - {gitHubIsConnected ? 'Update GitHub' : 'Connect GitHub'} + {gitHubNeedsActionsPermission + ? 'Approve GitHub access' + : gitHubIsConnected + ? 'Update GitHub' + : 'Connect GitHub'} {gitHubIsConnected ? ( {gitHubIsConnected ? (