Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 64 additions & 11 deletions .github/workflows/pr-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,32 @@ jobs:
{
name: "size:XS",
color: "0e8a16",
description: "0-9 changed lines (additions + deletions).",
description: "0-9 effective changed lines (test files excluded in mixed PRs).",
},
{
name: "size:S",
color: "5ebd3e",
description: "10-29 changed lines (additions + deletions).",
description: "10-29 effective changed lines (test files excluded in mixed PRs).",
},
{
name: "size:M",
color: "fbca04",
description: "30-99 changed lines (additions + deletions).",
description: "30-99 effective changed lines (test files excluded in mixed PRs).",
},
{
name: "size:L",
color: "fe7d37",
description: "100-499 changed lines (additions + deletions).",
description: "100-499 effective changed lines (test files excluded in mixed PRs).",
},
{
name: "size:XL",
color: "d93f0b",
description: "500-999 changed lines (additions + deletions).",
description: "500-999 effective changed lines (test files excluded in mixed PRs).",
},
{
name: "size:XXL",
color: "b60205",
description: "1,000+ changed lines (additions + deletions).",
description: "1,000+ effective changed lines (test files excluded in mixed PRs).",
},
];

Expand Down Expand Up @@ -131,12 +131,18 @@ jobs:
with:
script: |
const issueNumber = context.payload.pull_request.number;
const additions = context.payload.pull_request.additions ?? 0;
const deletions = context.payload.pull_request.deletions ?? 0;
const changedLines = additions + deletions;
const managedLabels = JSON.parse(process.env.PR_SIZE_LABELS_JSON ?? "[]");

const managedLabelNames = new Set(managedLabels.map((label) => label.name));
// Keep this aligned with the repo's test entrypoints and test-only support files.
const testFilePatterns = [
/(^|\/)__tests__(\/|$)/,
/(^|\/)tests?(\/|$)/,
/^apps\/server\/integration\//,
/\.(test|spec|browser|integration)\.[^.\/]+$/,
];

const isTestFile = (filename) =>
testFilePatterns.some((pattern) => pattern.test(filename));

const resolveSizeLabel = (totalChangedLines) => {
if (totalChangedLines < 10) {
Expand All @@ -162,6 +168,42 @@ jobs:
return "size:XXL";
};

const files = await github.paginate(
github.rest.pulls.listFiles,
{
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issueNumber,
per_page: 100,
},
(response) => response.data,
);

if (files.length >= 3000) {
core.warning(
"The GitHub pull request files API may truncate results at 3,000 files; PR size may be undercounted.",
);
}
Comment on lines +182 to +186
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Don't relabel from a truncated file list.

If pulls.listFiles hits GitHub's 3,000-file cap, the workflow still classifies the PR from a partial total. That can attach a smaller size label than the PR actually deserves. Once truncation is detected, this should either force size:XXL or leave the existing size label untouched.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-size.yml around lines 182 - 186, The truncation check
(files.length >= 3000) currently only logs a warning but still allows the
workflow to compute and apply a size label from a partial list; update the logic
that runs after pulls.listFiles to treat truncation as a special case: when
files.length >= 3000 either set the computed size label to "size:XXL" or skip
changing the existing size label entirely instead of applying the normal label
flow, and ensure this change is applied where the code computes/applies labels
(the block that checks files.length and the subsequent label assignment/patching
logic).


let testChangedLines = 0;
let nonTestChangedLines = 0;

for (const file of files) {
const changedLinesForFile = (file.additions ?? 0) + (file.deletions ?? 0);

if (changedLinesForFile === 0) {
continue;
}

if (isTestFile(file.filename)) {
testChangedLines += changedLinesForFile;
continue;
}

nonTestChangedLines += changedLinesForFile;
}

const changedLines = nonTestChangedLines === 0 ? testChangedLines : nonTestChangedLines;
const nextLabelName = resolveSizeLabel(changedLines);

const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
Expand Down Expand Up @@ -199,4 +241,15 @@ jobs:
});
}

core.info(`PR #${issueNumber}: ${changedLines} changed lines -> ${nextLabelName}`);
const classification =
nonTestChangedLines === 0
? testChangedLines > 0
? "test-only PR"
: "no line changes"
: testChangedLines > 0
? "test lines excluded"
: "all non-test changes";

core.info(
`PR #${issueNumber}: ${nonTestChangedLines} non-test lines, ${testChangedLines} test lines, ${changedLines} effective lines -> ${nextLabelName} (${classification})`,
);
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {

import { CheckpointStoreLive } from "../src/checkpointing/Layers/CheckpointStore.ts";
import { CheckpointStore } from "../src/checkpointing/Services/CheckpointStore.ts";
import { GitCoreLive } from "../src/git/Layers/GitCore.ts";
import { GitCore, type GitCoreShape } from "../src/git/Services/GitCore.ts";
import { TextGeneration, type TextGenerationShape } from "../src/git/Services/TextGeneration.ts";
import { OrchestrationCommandReceiptRepositoryLive } from "../src/persistence/Layers/OrchestrationCommandReceipts.ts";
Expand Down Expand Up @@ -284,12 +285,13 @@ export const makeOrchestrationIntegrationHarness = (
Layer.provide(AnalyticsService.layerTest),
);

const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(GitCoreLive));
const runtimeServicesLayer = Layer.mergeAll(
orchestrationLayer,
OrchestrationProjectionSnapshotQueryLive,
ProjectionCheckpointRepositoryLive,
ProjectionPendingApprovalRepositoryLive,
CheckpointStoreLive,
checkpointStoreLayer,
providerLayer,
RuntimeReceiptBusLive,
);
Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "t3",
"version": "0.0.13",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/pingdotgg/t3code",
Expand Down
9 changes: 3 additions & 6 deletions apps/server/src/checkpointing/Layers/CheckpointStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ import { Effect, Layer, FileSystem, Path } from "effect";

import { CheckpointInvariantError } from "../Errors.ts";
import { GitCommandError } from "../../git/Errors.ts";
import { GitServiceLive } from "../../git/Layers/GitService.ts";
import { GitService } from "../../git/Services/GitService.ts";
import { GitCore } from "../../git/Services/GitCore.ts";
import { CheckpointStore, type CheckpointStoreShape } from "../Services/CheckpointStore.ts";
import { CheckpointRef } from "@t3tools/contracts";

const makeCheckpointStore = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const git = yield* GitService;
const git = yield* GitCore;

const resolveHeadCommit = (cwd: string): Effect.Effect<string | null, GitCommandError> =>
git
Expand Down Expand Up @@ -277,6 +276,4 @@ const makeCheckpointStore = Effect.gen(function* () {
} satisfies CheckpointStoreShape;
});

export const CheckpointStoreLive = Layer.effect(CheckpointStore, makeCheckpointStore).pipe(
Layer.provideMerge(GitServiceLive),
);
export const CheckpointStoreLive = Layer.effect(CheckpointStore, makeCheckpointStore);
Loading
Loading