// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: github.sql package db import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const createGitHubInstallation = `-- name: CreateGitHubInstallation :one INSERT INTO github_installation ( workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id ) VALUES ( $1, $2, $3, $4, $5, $6 ) ON CONFLICT (workspace_id, installation_id) DO UPDATE SET account_login = EXCLUDED.account_login, account_type = EXCLUDED.account_type, account_avatar_url = EXCLUDED.account_avatar_url, connected_by_id = EXCLUDED.connected_by_id, updated_at = now() RETURNING id, workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id, created_at, updated_at ` type CreateGitHubInstallationParams struct { WorkspaceID pgtype.UUID `json:"workspace_id"` InstallationID int64 `json:"installation_id"` AccountLogin string `json:"account_login"` AccountType string `json:"account_type"` AccountAvatarUrl pgtype.Text `json:"account_avatar_url"` ConnectedByID pgtype.UUID `json:"connected_by_id"` } func (q *Queries) CreateGitHubInstallation(ctx context.Context, arg CreateGitHubInstallationParams) (GithubInstallation, error) { row := q.db.QueryRow(ctx, createGitHubInstallation, arg.WorkspaceID, arg.InstallationID, arg.AccountLogin, arg.AccountType, arg.AccountAvatarUrl, arg.ConnectedByID, ) var i GithubInstallation err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ConnectedByID, &i.CreatedAt, &i.UpdatedAt, ) return i, err } const deleteGitHubInstallation = `-- name: DeleteGitHubInstallation :exec DELETE FROM github_installation WHERE id = $1 AND workspace_id = $2 ` type DeleteGitHubInstallationParams struct { ID pgtype.UUID `json:"id"` WorkspaceID pgtype.UUID `json:"workspace_id"` } func (q *Queries) DeleteGitHubInstallation(ctx context.Context, arg DeleteGitHubInstallationParams) error { _, err := q.db.Exec(ctx, deleteGitHubInstallation, arg.ID, arg.WorkspaceID) return err } const deleteGitHubInstallationByInstallationID = `-- name: DeleteGitHubInstallationByInstallationID :many DELETE FROM github_installation WHERE installation_id = $1 RETURNING id, workspace_id ` type DeleteGitHubInstallationByInstallationIDRow struct { ID pgtype.UUID `json:"id"` WorkspaceID pgtype.UUID `json:"workspace_id"` } // GitHub-side uninstall/suspend removes trust in the installation entirely, so // drop every workspace binding. Returns one row per deleted binding so the // handler can broadcast to each affected workspace. func (q *Queries) DeleteGitHubInstallationByInstallationID(ctx context.Context, installationID int64) ([]DeleteGitHubInstallationByInstallationIDRow, error) { rows, err := q.db.Query(ctx, deleteGitHubInstallationByInstallationID, installationID) if err != nil { return nil, err } defer rows.Close() items := []DeleteGitHubInstallationByInstallationIDRow{} for rows.Next() { var i DeleteGitHubInstallationByInstallationIDRow if err := rows.Scan(&i.ID, &i.WorkspaceID); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const deletePendingGitHubInstallation = `-- name: DeletePendingGitHubInstallation :exec DELETE FROM github_pending_installation WHERE installation_id = $1 ` func (q *Queries) DeletePendingGitHubInstallation(ctx context.Context, installationID int64) error { _, err := q.db.Exec(ctx, deletePendingGitHubInstallation, installationID) return err } const findGitHubPullRequestByURL = `-- name: FindGitHubPullRequestByURL :one SELECT id, workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, created_at, updated_at, head_sha, mergeable_state, additions, deletions, changed_files, api_mergeable, api_merge_state_status, checks_rollup_state, snapshot_head_sha, snapshot_fetched_at FROM github_pull_request WHERE workspace_id = $1 AND lower(rtrim(html_url, '/')) = lower($2::text) ORDER BY pr_updated_at DESC LIMIT 1 ` type FindGitHubPullRequestByURLParams struct { WorkspaceID pgtype.UUID `json:"workspace_id"` HtmlUrl string `json:"html_url"` } // Resolves a pasted PR URL to a mirrored PR. The caller normalizes the URL to // scheme://host/owner/repo/pull/N; html_url is stored in that shape. func (q *Queries) FindGitHubPullRequestByURL(ctx context.Context, arg FindGitHubPullRequestByURLParams) (GithubPullRequest, error) { row := q.db.QueryRow(ctx, findGitHubPullRequestByURL, arg.WorkspaceID, arg.HtmlUrl) var i GithubPullRequest err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.CreatedAt, &i.UpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, ) return i, err } const getGitHubInstallationByID = `-- name: GetGitHubInstallationByID :one SELECT id, workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id, created_at, updated_at FROM github_installation WHERE id = $1 ` func (q *Queries) GetGitHubInstallationByID(ctx context.Context, id pgtype.UUID) (GithubInstallation, error) { row := q.db.QueryRow(ctx, getGitHubInstallationByID, id) var i GithubInstallation err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ConnectedByID, &i.CreatedAt, &i.UpdatedAt, ) return i, err } const getGitHubPullRequest = `-- name: GetGitHubPullRequest :one SELECT id, workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, created_at, updated_at, head_sha, mergeable_state, additions, deletions, changed_files, api_mergeable, api_merge_state_status, checks_rollup_state, snapshot_head_sha, snapshot_fetched_at FROM github_pull_request WHERE workspace_id = $1 AND repo_owner = $2 AND repo_name = $3 AND pr_number = $4 ` type GetGitHubPullRequestParams struct { WorkspaceID pgtype.UUID `json:"workspace_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` PrNumber int32 `json:"pr_number"` } func (q *Queries) GetGitHubPullRequest(ctx context.Context, arg GetGitHubPullRequestParams) (GithubPullRequest, error) { row := q.db.QueryRow(ctx, getGitHubPullRequest, arg.WorkspaceID, arg.RepoOwner, arg.RepoName, arg.PrNumber, ) var i GithubPullRequest err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.CreatedAt, &i.UpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, ) return i, err } const getGitHubPullRequestInWorkspace = `-- name: GetGitHubPullRequestInWorkspace :one SELECT id, workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, created_at, updated_at, head_sha, mergeable_state, additions, deletions, changed_files, api_mergeable, api_merge_state_status, checks_rollup_state, snapshot_head_sha, snapshot_fetched_at FROM github_pull_request WHERE id = $1 AND workspace_id = $2 ` type GetGitHubPullRequestInWorkspaceParams struct { ID pgtype.UUID `json:"id"` WorkspaceID pgtype.UUID `json:"workspace_id"` } func (q *Queries) GetGitHubPullRequestInWorkspace(ctx context.Context, arg GetGitHubPullRequestInWorkspaceParams) (GithubPullRequest, error) { row := q.db.QueryRow(ctx, getGitHubPullRequestInWorkspace, arg.ID, arg.WorkspaceID) var i GithubPullRequest err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.CreatedAt, &i.UpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, ) return i, err } const getIssueReviewHeadSha = `-- name: GetIssueReviewHeadSha :one SELECT head_sha FROM ( SELECT pr.head_sha AS head_sha, pr.state AS state, pr.pr_updated_at AS pr_updated_at FROM github_pull_request pr JOIN issue_pull_request ipr ON ipr.pull_request_id = pr.id WHERE ipr.issue_id = $1 AND pr.head_sha <> '' UNION ALL SELECT pr.head_sha AS head_sha, pr.state AS state, pr.pr_updated_at AS pr_updated_at FROM vcs_pull_request pr JOIN issue_vcs_pull_request ipr ON ipr.pull_request_id = pr.id WHERE ipr.issue_id = $1 AND pr.head_sha <> '' ) combined ORDER BY (state IN ('open', 'draft')) DESC, pr_updated_at DESC LIMIT 1 ` // Returns the head SHA of the commit currently "under review" for an issue: // the most-recently-updated linked PR that still has an open/draft state and a // non-empty head_sha. Used by the reviewer-loop dedup (TEN-356) so a pending // review task pinned to an old head does not satisfy a request after HEAD // advanced. Prefers in-flight PRs (open/draft) over merged/closed ones so a // stale merged sibling can't shadow the live review target; falls back to the // newest linked PR with a head_sha when none are open. Returns no rows (empty // string) when the issue has no linked PR — callers treat that as "no SHA key" // and dedup on (issue_id, agent_id) alone, preserving pre-TEN-356 behavior. // // Spans both GitHub and self-hosted VCS PRs: a self-hosted PR pushing a new // commit must move the dedup head SHA the same way a GitHub PR does, otherwise // a fresh review round could be merged away against a stale key. func (q *Queries) GetIssueReviewHeadSha(ctx context.Context, issueID pgtype.UUID) (string, error) { row := q.db.QueryRow(ctx, getIssueReviewHeadSha, issueID) var head_sha string err := row.Scan(&head_sha) return head_sha, err } const getPendingGitHubInstallation = `-- name: GetPendingGitHubInstallation :one SELECT installation_id, account_login, account_type, account_avatar_url, received_at, updated_at FROM github_pending_installation WHERE installation_id = $1 ` func (q *Queries) GetPendingGitHubInstallation(ctx context.Context, installationID int64) (GithubPendingInstallation, error) { row := q.db.QueryRow(ctx, getPendingGitHubInstallation, installationID) var i GithubPendingInstallation err := row.Scan( &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ReceivedAt, &i.UpdatedAt, ) return i, err } const linkIssueToPullRequest = `-- name: LinkIssueToPullRequest :execrows INSERT INTO issue_pull_request ( issue_id, pull_request_id, linked_by_type, linked_by_id ) VALUES ( $1, $2, 'system', NULL ) ON CONFLICT (issue_id, pull_request_id) DO NOTHING ` type LinkIssueToPullRequestParams struct { IssueID pgtype.UUID `json:"issue_id"` PullRequestID pgtype.UUID `json:"pull_request_id"` } // ===================== // Issue ↔ Pull Request link // ===================== // Automatic link from a PR title, branch, or closing keyword. Returns 1 only // when the link is new, so the webhook evaluates the merge automation on the // link event and not on every redelivery. An existing link (automatic or // manual) is left untouched. close_intent is no longer read or written // (MUL-7726). func (q *Queries) LinkIssueToPullRequest(ctx context.Context, arg LinkIssueToPullRequestParams) (int64, error) { result, err := q.db.Exec(ctx, linkIssueToPullRequest, arg.IssueID, arg.PullRequestID) if err != nil { return 0, err } return result.RowsAffected(), nil } const linkIssueToPullRequestManually = `-- name: LinkIssueToPullRequestManually :execrows INSERT INTO issue_pull_request ( issue_id, pull_request_id, linked_by_type, linked_by_id ) VALUES ( $1, $2, 'member', $3 ) ON CONFLICT (issue_id, pull_request_id) DO UPDATE SET linked_by_type = 'member', linked_by_id = EXCLUDED.linked_by_id WHERE issue_pull_request.linked_by_type IS DISTINCT FROM 'member' ` type LinkIssueToPullRequestManuallyParams struct { IssueID pgtype.UUID `json:"issue_id"` PullRequestID pgtype.UUID `json:"pull_request_id"` LinkedByID pgtype.UUID `json:"linked_by_id"` } // A member linked this PR by hand. Marking an existing automatic link as // manual keeps a later title edit from removing it. Returns 1 when the row was // inserted or converted. func (q *Queries) LinkIssueToPullRequestManually(ctx context.Context, arg LinkIssueToPullRequestManuallyParams) (int64, error) { result, err := q.db.Exec(ctx, linkIssueToPullRequestManually, arg.IssueID, arg.PullRequestID, arg.LinkedByID) if err != nil { return 0, err } return result.RowsAffected(), nil } const listAutoLinkedIssueIDsForPullRequest = `-- name: ListAutoLinkedIssueIDsForPullRequest :many SELECT issue_id FROM issue_pull_request WHERE pull_request_id = $1 AND COALESCE(linked_by_type, 'system') <> 'member' ` // Issues this PR is linked to automatically. Manual links are not listed: the // webhook reconciles only what it created itself. func (q *Queries) ListAutoLinkedIssueIDsForPullRequest(ctx context.Context, pullRequestID pgtype.UUID) ([]pgtype.UUID, error) { rows, err := q.db.Query(ctx, listAutoLinkedIssueIDsForPullRequest, pullRequestID) if err != nil { return nil, err } defer rows.Close() items := []pgtype.UUID{} for rows.Next() { var issue_id pgtype.UUID if err := rows.Scan(&issue_id); err != nil { return nil, err } items = append(items, issue_id) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGitHubInstallationsByInstallationID = `-- name: ListGitHubInstallationsByInstallationID :many SELECT id, workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id, created_at, updated_at FROM github_installation WHERE installation_id = $1 ORDER BY created_at ASC, id ASC ` // One installation_id can be bound to several workspaces; webhook routing lists // every binding and fans the event out to each bound workspace. Ordered oldest // first so processing is deterministic and replay-stable. func (q *Queries) ListGitHubInstallationsByInstallationID(ctx context.Context, installationID int64) ([]GithubInstallation, error) { rows, err := q.db.Query(ctx, listGitHubInstallationsByInstallationID, installationID) if err != nil { return nil, err } defer rows.Close() items := []GithubInstallation{} for rows.Next() { var i GithubInstallation if err := rows.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ConnectedByID, &i.CreatedAt, &i.UpdatedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGitHubInstallationsByWorkspace = `-- name: ListGitHubInstallationsByWorkspace :many SELECT id, workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id, created_at, updated_at FROM github_installation WHERE workspace_id = $1 ORDER BY created_at ASC ` // ===================== // GitHub Installation // ===================== func (q *Queries) ListGitHubInstallationsByWorkspace(ctx context.Context, workspaceID pgtype.UUID) ([]GithubInstallation, error) { rows, err := q.db.Query(ctx, listGitHubInstallationsByWorkspace, workspaceID) if err != nil { return nil, err } defer rows.Close() items := []GithubInstallation{} for rows.Next() { var i GithubInstallation if err := rows.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ConnectedByID, &i.CreatedAt, &i.UpdatedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listIssueIDsForPullRequest = `-- name: ListIssueIDsForPullRequest :many SELECT issue_id FROM issue_pull_request WHERE pull_request_id = $1 ` func (q *Queries) ListIssueIDsForPullRequest(ctx context.Context, pullRequestID pgtype.UUID) ([]pgtype.UUID, error) { rows, err := q.db.Query(ctx, listIssueIDsForPullRequest, pullRequestID) if err != nil { return nil, err } defer rows.Close() items := []pgtype.UUID{} for rows.Next() { var issue_id pgtype.UUID if err := rows.Scan(&issue_id); err != nil { return nil, err } items = append(items, issue_id) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listPullRequestsByIssue = `-- name: ListPullRequestsByIssue :many WITH issue_prs AS ( SELECT pr.id, pr.snapshot_head_sha FROM github_pull_request pr JOIN issue_pull_request ipr ON ipr.pull_request_id = pr.id WHERE ipr.issue_id = $1 ), checks AS ( SELECT cr.pr_id, COUNT(*)::bigint AS total, SUM(CASE WHEN cr.status = 'completed' AND cr.conclusion IN ('failure','cancelled','timed_out','action_required','startup_failure','stale','error') THEN 1 ELSE 0 END)::bigint AS failed, SUM(CASE WHEN cr.status = 'completed' AND cr.conclusion IN ('success','neutral','skipped') THEN 1 ELSE 0 END)::bigint AS passed, SUM(CASE WHEN cr.status <> 'completed' OR cr.conclusion IS NULL THEN 1 ELSE 0 END)::bigint AS running, COALESCE( array_agg(cr.name) FILTER (WHERE cr.status = 'completed' AND cr.conclusion IN ('failure','cancelled','timed_out','action_required','startup_failure','stale','error')), '{}' )::text[] AS failed_names FROM github_pull_request_check_run cr JOIN issue_prs ip ON ip.id = cr.pr_id WHERE cr.head_sha = ip.snapshot_head_sha AND ip.snapshot_head_sha <> '' GROUP BY cr.pr_id ) SELECT pr.id, pr.workspace_id, pr.installation_id, pr.repo_owner, pr.repo_name, pr.pr_number, pr.title, pr.state, pr.html_url, pr.branch, pr.author_login, pr.author_avatar_url, pr.merged_at, pr.closed_at, pr.pr_created_at, pr.pr_updated_at, pr.head_sha, pr.mergeable_state, pr.additions, pr.deletions, pr.changed_files, pr.api_mergeable, pr.api_merge_state_status, pr.checks_rollup_state, pr.snapshot_head_sha, pr.snapshot_fetched_at, pr.created_at, pr.updated_at, COALESCE(ipr.linked_by_type, 'system')::text AS linked_by_type, COALESCE(c.total, 0)::bigint AS checks_total, COALESCE(c.passed, 0)::bigint AS checks_passed, COALESCE(c.failed, 0)::bigint AS checks_failed, COALESCE(c.running, 0)::bigint AS checks_running, COALESCE(c.failed_names, '{}')::text[] AS failed_check_names FROM github_pull_request pr JOIN issue_pull_request ipr ON ipr.pull_request_id = pr.id LEFT JOIN checks c ON c.pr_id = pr.id WHERE ipr.issue_id = $1 ORDER BY pr.pr_created_at DESC ` type ListPullRequestsByIssueRow struct { ID pgtype.UUID `json:"id"` WorkspaceID pgtype.UUID `json:"workspace_id"` InstallationID int64 `json:"installation_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` PrNumber int32 `json:"pr_number"` Title string `json:"title"` State string `json:"state"` HtmlUrl string `json:"html_url"` Branch pgtype.Text `json:"branch"` AuthorLogin pgtype.Text `json:"author_login"` AuthorAvatarUrl pgtype.Text `json:"author_avatar_url"` MergedAt pgtype.Timestamptz `json:"merged_at"` ClosedAt pgtype.Timestamptz `json:"closed_at"` PrCreatedAt pgtype.Timestamptz `json:"pr_created_at"` PrUpdatedAt pgtype.Timestamptz `json:"pr_updated_at"` HeadSha string `json:"head_sha"` MergeableState pgtype.Text `json:"mergeable_state"` Additions int32 `json:"additions"` Deletions int32 `json:"deletions"` ChangedFiles int32 `json:"changed_files"` ApiMergeable pgtype.Text `json:"api_mergeable"` ApiMergeStateStatus pgtype.Text `json:"api_merge_state_status"` ChecksRollupState pgtype.Text `json:"checks_rollup_state"` SnapshotHeadSha string `json:"snapshot_head_sha"` SnapshotFetchedAt pgtype.Timestamptz `json:"snapshot_fetched_at"` CreatedAt pgtype.Timestamptz `json:"created_at"` UpdatedAt pgtype.Timestamptz `json:"updated_at"` LinkedByType string `json:"linked_by_type"` ChecksTotal int64 `json:"checks_total"` ChecksPassed int64 `json:"checks_passed"` ChecksFailed int64 `json:"checks_failed"` ChecksRunning int64 `json:"checks_running"` FailedCheckNames []string `json:"failed_check_names"` } // Returns the issue's linked PRs with the GitHub API snapshot (MUL-5265): the // mergeability verdict, the CI rollup, and per-check counts for the PR's // CURRENT snapshot head SHA. Checks are aggregated from // github_pull_request_check_run — the run-level snapshot written by the API // refresh pipeline — NOT the legacy suite-level webhook aggregation, which is // removed. The `issue_prs` CTE narrows to this issue's PR ids first so the // aggregation only touches check rows for those PRs. Rows for an OLD head are // excluded by the snapshot_head_sha filter. Every link row is a delivery PR: // the webhook links an identifier it read from the PR title or branch name, and // a member can link one by hand (linked_by_type = 'member'). MUL-7429. func (q *Queries) ListPullRequestsByIssue(ctx context.Context, issueID pgtype.UUID) ([]ListPullRequestsByIssueRow, error) { rows, err := q.db.Query(ctx, listPullRequestsByIssue, issueID) if err != nil { return nil, err } defer rows.Close() items := []ListPullRequestsByIssueRow{} for rows.Next() { var i ListPullRequestsByIssueRow if err := rows.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, &i.CreatedAt, &i.UpdatedAt, &i.LinkedByType, &i.ChecksTotal, &i.ChecksPassed, &i.ChecksFailed, &i.ChecksRunning, &i.FailedCheckNames, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const unlinkIssueFromPullRequest = `-- name: UnlinkIssueFromPullRequest :execrows DELETE FROM issue_pull_request WHERE issue_id = $1 AND pull_request_id = $2 ` type UnlinkIssueFromPullRequestParams struct { IssueID pgtype.UUID `json:"issue_id"` PullRequestID pgtype.UUID `json:"pull_request_id"` } func (q *Queries) UnlinkIssueFromPullRequest(ctx context.Context, arg UnlinkIssueFromPullRequestParams) (int64, error) { result, err := q.db.Exec(ctx, unlinkIssueFromPullRequest, arg.IssueID, arg.PullRequestID) if err != nil { return 0, err } return result.RowsAffected(), nil } const updateGitHubInstallationAccountByInstallationID = `-- name: UpdateGitHubInstallationAccountByInstallationID :many UPDATE github_installation SET account_login = $2, account_type = $3, account_avatar_url = $4, updated_at = now() WHERE installation_id = $1 RETURNING id, workspace_id, installation_id, account_login, account_type, account_avatar_url, connected_by_id, created_at, updated_at ` type UpdateGitHubInstallationAccountByInstallationIDParams struct { InstallationID int64 `json:"installation_id"` AccountLogin string `json:"account_login"` AccountType string `json:"account_type"` AccountAvatarUrl pgtype.Text `json:"account_avatar_url"` } // Refresh the GitHub account display metadata across every workspace binding of // an installation (fired by installation.created/new_permissions_accepted/ // unsuspend). Leaves workspace_id and connected_by_id untouched. func (q *Queries) UpdateGitHubInstallationAccountByInstallationID(ctx context.Context, arg UpdateGitHubInstallationAccountByInstallationIDParams) ([]GithubInstallation, error) { rows, err := q.db.Query(ctx, updateGitHubInstallationAccountByInstallationID, arg.InstallationID, arg.AccountLogin, arg.AccountType, arg.AccountAvatarUrl, ) if err != nil { return nil, err } defer rows.Close() items := []GithubInstallation{} for rows.Next() { var i GithubInstallation if err := rows.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ConnectedByID, &i.CreatedAt, &i.UpdatedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const upsertGitHubPullRequest = `-- name: UpsertGitHubPullRequest :one INSERT INTO github_pull_request ( workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, head_sha, mergeable_state, additions, deletions, changed_files ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $15, $16, $17, $18, $19, $9, $10, $11, $20, $12, $13, $14 ) ON CONFLICT (workspace_id, repo_owner, repo_name, pr_number) DO UPDATE SET installation_id = EXCLUDED.installation_id, title = EXCLUDED.title, state = EXCLUDED.state, html_url = EXCLUDED.html_url, branch = EXCLUDED.branch, author_login = EXCLUDED.author_login, author_avatar_url = EXCLUDED.author_avatar_url, merged_at = EXCLUDED.merged_at, closed_at = EXCLUDED.closed_at, pr_updated_at = EXCLUDED.pr_updated_at, head_sha = EXCLUDED.head_sha, mergeable_state = CASE WHEN COALESCE($21::boolean, FALSE) THEN NULL WHEN EXCLUDED.mergeable_state IS NOT NULL THEN EXCLUDED.mergeable_state ELSE github_pull_request.mergeable_state END, additions = EXCLUDED.additions, deletions = EXCLUDED.deletions, changed_files = EXCLUDED.changed_files, updated_at = now() WHERE EXCLUDED.pr_updated_at >= github_pull_request.pr_updated_at RETURNING id, workspace_id, installation_id, repo_owner, repo_name, pr_number, title, state, html_url, branch, author_login, author_avatar_url, merged_at, closed_at, pr_created_at, pr_updated_at, created_at, updated_at, head_sha, mergeable_state, additions, deletions, changed_files, api_mergeable, api_merge_state_status, checks_rollup_state, snapshot_head_sha, snapshot_fetched_at ` type UpsertGitHubPullRequestParams struct { WorkspaceID pgtype.UUID `json:"workspace_id"` InstallationID int64 `json:"installation_id"` RepoOwner string `json:"repo_owner"` RepoName string `json:"repo_name"` PrNumber int32 `json:"pr_number"` Title string `json:"title"` State string `json:"state"` HtmlUrl string `json:"html_url"` PrCreatedAt pgtype.Timestamptz `json:"pr_created_at"` PrUpdatedAt pgtype.Timestamptz `json:"pr_updated_at"` HeadSha string `json:"head_sha"` Additions int32 `json:"additions"` Deletions int32 `json:"deletions"` ChangedFiles int32 `json:"changed_files"` Branch pgtype.Text `json:"branch"` AuthorLogin pgtype.Text `json:"author_login"` AuthorAvatarUrl pgtype.Text `json:"author_avatar_url"` MergedAt pgtype.Timestamptz `json:"merged_at"` ClosedAt pgtype.Timestamptz `json:"closed_at"` MergeableState pgtype.Text `json:"mergeable_state"` ClearMergeableState pgtype.Bool `json:"clear_mergeable_state"` } // ===================== // GitHub Pull Request // ===================== // mergeable_state has three-state semantics on UPDATE: // 1. clear_mergeable_state=true → write NULL (state-changing actions like // opened/synchronize/reopened/edited(base) invalidate the prior verdict). // 2. clear_mergeable_state=false, mergeable_state non-null → write the value. // 3. clear_mergeable_state=false, mergeable_state null → preserve existing // column. Metadata events (labeled/assigned/etc.) ship payloads without // mergeability, and silently clobbering a known clean/dirty would lose // information that GitHub only re-computes lazily. // // INSERT path always writes the incoming value (NULL acceptable for a new row). // // GitHub may deliver events out of order. An event older than the stored row // (pr_updated_at) updates nothing and returns no row, so a late "opened" can't // roll a merged PR back to open — the same guard UpsertVCSPullRequest has. func (q *Queries) UpsertGitHubPullRequest(ctx context.Context, arg UpsertGitHubPullRequestParams) (GithubPullRequest, error) { row := q.db.QueryRow(ctx, upsertGitHubPullRequest, arg.WorkspaceID, arg.InstallationID, arg.RepoOwner, arg.RepoName, arg.PrNumber, arg.Title, arg.State, arg.HtmlUrl, arg.PrCreatedAt, arg.PrUpdatedAt, arg.HeadSha, arg.Additions, arg.Deletions, arg.ChangedFiles, arg.Branch, arg.AuthorLogin, arg.AuthorAvatarUrl, arg.MergedAt, arg.ClosedAt, arg.MergeableState, arg.ClearMergeableState, ) var i GithubPullRequest err := row.Scan( &i.ID, &i.WorkspaceID, &i.InstallationID, &i.RepoOwner, &i.RepoName, &i.PrNumber, &i.Title, &i.State, &i.HtmlUrl, &i.Branch, &i.AuthorLogin, &i.AuthorAvatarUrl, &i.MergedAt, &i.ClosedAt, &i.PrCreatedAt, &i.PrUpdatedAt, &i.CreatedAt, &i.UpdatedAt, &i.HeadSha, &i.MergeableState, &i.Additions, &i.Deletions, &i.ChangedFiles, &i.ApiMergeable, &i.ApiMergeStateStatus, &i.ChecksRollupState, &i.SnapshotHeadSha, &i.SnapshotFetchedAt, ) return i, err } const upsertPendingGitHubInstallation = `-- name: UpsertPendingGitHubInstallation :one INSERT INTO github_pending_installation ( installation_id, account_login, account_type, account_avatar_url ) VALUES ( $1, $2, $3, $4 ) ON CONFLICT (installation_id) DO UPDATE SET account_login = EXCLUDED.account_login, account_type = EXCLUDED.account_type, account_avatar_url = EXCLUDED.account_avatar_url, updated_at = now() RETURNING installation_id, account_login, account_type, account_avatar_url, received_at, updated_at ` type UpsertPendingGitHubInstallationParams struct { InstallationID int64 `json:"installation_id"` AccountLogin string `json:"account_login"` AccountType string `json:"account_type"` AccountAvatarUrl pgtype.Text `json:"account_avatar_url"` } func (q *Queries) UpsertPendingGitHubInstallation(ctx context.Context, arg UpsertPendingGitHubInstallationParams) (GithubPendingInstallation, error) { row := q.db.QueryRow(ctx, upsertPendingGitHubInstallation, arg.InstallationID, arg.AccountLogin, arg.AccountType, arg.AccountAvatarUrl, ) var i GithubPendingInstallation err := row.Scan( &i.InstallationID, &i.AccountLogin, &i.AccountType, &i.AccountAvatarUrl, &i.ReceivedAt, &i.UpdatedAt, ) return i, err }