Skip to content

Commit

Permalink
Make the sync label logic reusable for typespec-azure repo (#3425)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored May 23, 2024
1 parent 4107059 commit 5698be1
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 190 deletions.
2 changes: 0 additions & 2 deletions .github/policies/issues.needs-info.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ configuration:
filters:
- isIssue
- isOpen
- hasLabel:
label: No-Recent-Activity
- hasLabel:
label: needs-info
- noActivitySince:
Expand Down
2 changes: 0 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
**/obj/
**/.vs/
**/.docusaurus/
common/temp/
common/scripts/
.chronus/changes/

# Pnpm lock file
Expand Down
22 changes: 11 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,17 +297,6 @@ TypeSpec repo use labels to help categorize and manage issues and PRs. The follo

### Labels reference

#### issue_kinds

Issue kinds

| Name | Color | Description |
| --------- | ------- | ------------------------------------------ |
| `bug` | #d93f0b | Something isn't working |
| `feature` | #cccccc | New feature or request |
| `docs` | #cccccc | Improvements or additions to documentation |
| `epic` | #cccccc | |

#### area

Area of the codebase
Expand All @@ -332,6 +321,17 @@ Area of the codebase
| `emitter:service:js` | #967200 | |
| `eng` | #65bfff | |

#### issue_kinds

Issue kinds

| Name | Color | Description |
| --------- | ------- | ------------------------------------------ |
| `bug` | #d93f0b | Something isn't working |
| `feature` | #cccccc | New feature or request |
| `docs` | #cccccc | Improvements or additions to documentation |
| `epic` | #cccccc | |

#### breaking-change

Labels around annotating issues and PR if they contain breaking change or deprecation
Expand Down
24 changes: 0 additions & 24 deletions eng/common/config/areas.ts

This file was deleted.

75 changes: 51 additions & 24 deletions eng/common/config/labels.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// cspell:ignore bfff
import { repo } from "../scripts/common.js";
import { defineConfig, defineLabels } from "../scripts/labels/config.js";

/**
* Labels that are used to categorize issue for which area they belong to.
Expand Down Expand Up @@ -74,10 +76,10 @@ export const AreaLabels = defineLabels({
},
});

export default {
export const CommonLabels = {
issue_kinds: {
description: "Issue kinds",
labels: {
labels: defineLabels({
bug: {
color: "d93f0b",
description: "Something isn't working",
Expand All @@ -94,11 +96,7 @@ export default {
color: "cccccc",
description: "",
},
},
},
area: {
description: "Area of the codebase",
labels: AreaLabels,
}),
},
"breaking-change": {
description:
Expand Down Expand Up @@ -150,23 +148,52 @@ export default {
},
},
},
misc: {
description: "Misc labels",
labels: {
"Client Emitter Migration": {
color: "FD92F0",
description: "",
},
"good first issue": {
color: "7057ff",
description: "Good for newcomers",
};

/**
* Set the paths that each area applies to.
*/
export const AreaPaths: Record<keyof typeof AreaLabels, string[]> = {
"compiler:core": ["packages/compiler/"],
"compiler:emitter-framework": [],
ide: ["packages/typespec-vscode/", "packages/typespec-vs/"],
"lib:http": ["packages/http/"],
"lib:openapi": ["packages/openapi/"],
"lib:rest": ["packages/rest/"],
"lib:versioning": ["packages/versioning/"],
"meta:blog": ["blog/"],
"meta:website": ["website/"],
tspd: ["packages/tspd/"],
"emitter:client:csharp": ["packages/http-client-csharp/"],
"emitter:json-schema": ["packages/json-schema/"],
"emitter:protobuf": ["packages/protobuf/"],
"emitter:openapi3": ["packages/openapi3/"],
"emitter:service:csharp": [],
"emitter:service:js": [],
eng: ["eng/", ".github/"],
};

export default defineConfig({
repo,
labels: {
area: {
description: "Area of the codebase",
labels: AreaLabels,
},
...CommonLabels,
misc: {
description: "Misc labels",
labels: {
"Client Emitter Migration": {
color: "FD92F0",
description: "",
},
"good first issue": {
color: "7057ff",
description: "Good for newcomers",
},
},
},
},
} as const;

function defineLabels<const T extends string>(
labels: Record<T, { color: string; description: string }>
) {
return labels;
}
areaPaths: AreaPaths,
});
189 changes: 96 additions & 93 deletions eng/common/scripts/labels/automation.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { resolve } from "path";
import { stringify } from "yaml";
import { AreaPaths } from "../../config/areas.js";
import { AreaLabels } from "../../config/labels.js";
import { CheckOptions, repoRoot, syncFile } from "../common.js";
import { CheckOptions, syncFile } from "../common.js";
import {
PolicyServiceConfig,
and,
Expand All @@ -16,14 +14,15 @@ import {
or,
payloadType,
} from "./policy.js";
import type { RepoConfig } from "./types.js";

const policyFolder = resolve(repoRoot, ".github", "policies");
const policyFolder = resolve(process.cwd(), ".github", "policies");

export interface SyncLabelAutomationOptions extends CheckOptions {}

export async function syncLabelAutomation(options: SyncLabelAutomationOptions) {
await syncPolicyFile(issueTriageConfig, options);
await syncPolicyFile(prTriageConfig, options);
export async function syncLabelAutomation(config: RepoConfig, options: SyncLabelAutomationOptions) {
await syncPolicyFile(createIssueTriageConfig(config), options);
await syncPolicyFile(createPrTriageConfig(config), options);
}

async function syncPolicyFile(policy: PolicyServiceConfig, options: CheckOptions) {
Expand All @@ -33,96 +32,100 @@ async function syncPolicyFile(policy: PolicyServiceConfig, options: CheckOptions
await syncFile(filename, content, options);
}

const issueTriageConfig: PolicyServiceConfig = {
id: "issues.triage",
name: "New Issue Assign labels",
description: "Assign labels to new issues",
resource: "repository",
disabled: false,
configuration: {
resourceManagementConfiguration: {
eventResponderTasks: [
eventResponderTask({
description: "Adds `needs-area` label for new unassigned issues",
if: [
payloadType("Issues"),
isAction("Opened"),
not(and(["isAssignedToSomeone"])),
not(or(Object.keys(AreaLabels).map((area) => hasLabel(area)))),
],
then: [
{
addLabel: {
label: "needs-area",
function createIssueTriageConfig(config: RepoConfig): PolicyServiceConfig {
const areaLabels = config.labels.area.labels;
return {
id: "issues.triage",
name: "New Issue Assign labels",
description: "Assign labels to new issues",
resource: "repository",
disabled: false,
configuration: {
resourceManagementConfiguration: {
eventResponderTasks: [
eventResponderTask({
description: "Adds `needs-area` label for new unassigned issues",
if: [
payloadType("Issues"),
isAction("Opened"),
not(and(["isAssignedToSomeone"])),
not(or(Object.keys(areaLabels).map((area) => hasLabel(area)))),
],
then: [
{
addLabel: {
label: "needs-area",
},
},
},
],
}),
eventResponderTask({
description: "Remove `needs-area` label when an area label is added",
if: [
payloadType("Issues"),
hasLabel("needs-area"),
"isOpen",
or(Object.keys(AreaLabels).map((area) => labelAdded(area))),
],
then: [
{
removeLabel: {
label: "needs-area",
],
}),
eventResponderTask({
description: "Remove `needs-area` label when an area label is added",
if: [
payloadType("Issues"),
hasLabel("needs-area"),
"isOpen",
or(Object.keys(areaLabels).map((area) => labelAdded(area))),
],
then: [
{
removeLabel: {
label: "needs-area",
},
},
},
],
}),
eventResponderTask({
description: "Add `needs-area` back when all area labels are removed",
if: [
payloadType("Issues"),
not(hasLabel("needs-area")),
"isOpen",
or(Object.keys(AreaLabels).map((area) => labelRemoved(area))),
not(or(Object.keys(AreaLabels).map((area) => hasLabel(area)))),
],
then: [
{
addLabel: {
label: "needs-area",
],
}),
eventResponderTask({
description: "Add `needs-area` back when all area labels are removed",
if: [
payloadType("Issues"),
not(hasLabel("needs-area")),
"isOpen",
or(Object.keys(areaLabels).map((area) => labelRemoved(area))),
not(or(Object.keys(areaLabels).map((area) => hasLabel(area)))),
],
then: [
{
addLabel: {
label: "needs-area",
},
},
},
],
}),
],
],
}),
],
},
},
},
};

const prTriageConfig: PolicyServiceConfig = {
id: "prs.triage",
name: "Assign area labels to PRs",
description: "Assign area labels to PR depending on path modified.",
resource: "repository",
disabled: false,
configuration: {
resourceManagementConfiguration: {
eventResponderTasks: [
eventResponderTask({
if: [payloadType("Pull_Request")],
then: Object.entries(AreaPaths).flatMap(([label, files]) => {
return files.map((file) => {
return {
if: [filesMatchPattern(`${file}.*`)],
then: [
{
addLabel: {
label,
};
}
function createPrTriageConfig(config: RepoConfig): PolicyServiceConfig {
return {
id: "prs.triage",
name: "Assign area labels to PRs",
description: "Assign area labels to PR depending on path modified.",
resource: "repository",
disabled: false,
configuration: {
resourceManagementConfiguration: {
eventResponderTasks: [
eventResponderTask({
if: [payloadType("Pull_Request")],
then: Object.entries(config.areaPaths).flatMap(([label, files]) => {
return files.map((file) => {
return {
if: [filesMatchPattern(`${file}.*`)],
then: [
{
addLabel: {
label,
},
},
},
],
};
});
],
};
});
}),
}),
}),
],
],
},
},
},
};
};
}
Loading

0 comments on commit 5698be1

Please sign in to comment.