Skip to content

Commit 3de9820

Browse files
authored
Add copilot-requests permission, gated by feature flag (#335)
* Add copilot-requests permission gated by feature flag This add a new 'copilot-requests' permission to the workflow schema, gated behind the 'allowCopilotRequestsPermission' experimental feature flag. When the flag is disabled (default), `copilot-requests` is filtered out of autocomplete suggestions. When enabled, it appears alongside other permissions like actions, contents, pull-requests, etc. * Update workflow-parser/src/workflow-v1.0.json * Add additional unit test coverage * Fix formatting
1 parent a7f581b commit 3de9820

File tree

5 files changed

+98
-2
lines changed

5 files changed

+98
-2
lines changed

expressions/src/features.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ describe("FeatureFlags", () => {
5555
"missingInputsQuickfix",
5656
"blockScalarChompingWarning",
5757
"allowCaseFunction",
58-
"allowCronTimezone"
58+
"allowCronTimezone",
59+
"allowCopilotRequestsPermission"
5960
]);
6061
});
6162
});

expressions/src/features.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ export interface ExperimentalFeatures {
4040
* @default false
4141
*/
4242
allowCronTimezone?: boolean;
43+
44+
/**
45+
* Enable the copilot-requests permission in workflow permissions.
46+
* @default false
47+
*/
48+
allowCopilotRequestsPermission?: boolean;
4349
}
4450

4551
/**
@@ -55,7 +61,8 @@ const allFeatureKeys: ExperimentalFeatureKey[] = [
5561
"missingInputsQuickfix",
5662
"blockScalarChompingWarning",
5763
"allowCaseFunction",
58-
"allowCronTimezone"
64+
"allowCronTimezone",
65+
"allowCopilotRequestsPermission"
5966
];
6067

6168
export class FeatureFlags {

languageservice/src/complete.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,3 +967,79 @@ describe("schedule timezone completion", () => {
967967
expect(labels).not.toContain("timezone");
968968
});
969969
});
970+
971+
describe("permissions copilot-requests completion", () => {
972+
it("includes copilot-requests when allowCopilotRequestsPermission is enabled", async () => {
973+
const input = `on: push
974+
permissions:
975+
|`;
976+
const result = await complete(...getPositionFromCursor(input), {
977+
featureFlags: new FeatureFlags({allowCopilotRequestsPermission: true})
978+
});
979+
980+
expect(result).not.toBeUndefined();
981+
const labels = result.map(x => x.label);
982+
expect(labels).toContain("actions");
983+
expect(labels).toContain("copilot-requests");
984+
});
985+
986+
it("excludes copilot-requests when allowCopilotRequestsPermission is disabled", async () => {
987+
const input = `on: push
988+
permissions:
989+
|`;
990+
const result = await complete(...getPositionFromCursor(input), {
991+
featureFlags: new FeatureFlags({allowCopilotRequestsPermission: false})
992+
});
993+
994+
expect(result).not.toBeUndefined();
995+
const labels = result.map(x => x.label);
996+
expect(labels).toContain("actions");
997+
expect(labels).not.toContain("copilot-requests");
998+
});
999+
1000+
it("excludes copilot-requests when no feature flags are provided", async () => {
1001+
const input = `on: push
1002+
permissions:
1003+
|`;
1004+
const result = await complete(...getPositionFromCursor(input));
1005+
1006+
expect(result).not.toBeUndefined();
1007+
const labels = result.map(x => x.label);
1008+
expect(labels).toContain("actions");
1009+
expect(labels).not.toContain("copilot-requests");
1010+
});
1011+
1012+
it("includes copilot-requests in job-level permissions when allowCopilotRequestsPermission is enabled", async () => {
1013+
const input = `on: push
1014+
jobs:
1015+
build:
1016+
runs-on: ubuntu-latest
1017+
permissions:
1018+
|`;
1019+
const result = await complete(...getPositionFromCursor(input), {
1020+
featureFlags: new FeatureFlags({allowCopilotRequestsPermission: true})
1021+
});
1022+
1023+
expect(result).not.toBeUndefined();
1024+
const labels = result.map(x => x.label);
1025+
expect(labels).toContain("actions");
1026+
expect(labels).toContain("copilot-requests");
1027+
});
1028+
1029+
it("excludes copilot-requests from job-level permissions when allowCopilotRequestsPermission is disabled", async () => {
1030+
const input = `on: push
1031+
jobs:
1032+
build:
1033+
runs-on: ubuntu-latest
1034+
permissions:
1035+
|`;
1036+
const result = await complete(...getPositionFromCursor(input), {
1037+
featureFlags: new FeatureFlags({allowCopilotRequestsPermission: false})
1038+
});
1039+
1040+
expect(result).not.toBeUndefined();
1041+
const labels = result.map(x => x.label);
1042+
expect(labels).toContain("actions");
1043+
expect(labels).not.toContain("copilot-requests");
1044+
});
1045+
});

languageservice/src/complete.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ export async function complete(
168168
values = values.filter(v => v.label !== "timezone");
169169
}
170170

171+
// Filter `copilot-requests` from permissions completions when the feature flag is disabled
172+
if (
173+
!config?.featureFlags?.isEnabled("allowCopilotRequestsPermission") &&
174+
parent?.definition?.key === "permissions-mapping"
175+
) {
176+
values = values.filter(v => v.label !== "copilot-requests");
177+
}
178+
171179
// Offer "(switch to list)" / "(switch to mapping)" when the schema allows alternative forms
172180
const escapeHatches = getEscapeHatchCompletions(token, keyToken, indentString, newPos, schema);
173181
values.push(...escapeHatches);

workflow-parser/src/workflow-v1.0.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,10 @@
16021602
"type": "permission-level-any",
16031603
"description": "Repository contents, commits, branches, downloads, releases, and merges."
16041604
},
1605+
"copilot-requests": {
1606+
"type": "permission-level-write-or-no-access",
1607+
"description": "GitHub Copilot requests."
1608+
},
16051609
"deployments": {
16061610
"type": "permission-level-any",
16071611
"description": "Deployments and deployment statuses."

0 commit comments

Comments
 (0)