Skip to content

Commit

Permalink
update contributing
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin committed May 11, 2024
1 parent 467aab1 commit ce6abba
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 19 deletions.
89 changes: 88 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,94 @@ As a contributor you can run the following command to trigger the build and crea
/azp run typespec - pr tools
```

# Labels for issues and PRs
# Issue and Pr processes

## Labels

TypeSpec repo use labels to help categorize and manage issues and PRs. The following is a list of labels and their descriptions.

<!-- LABEL GENERATED REF START -->
<!-- DO NOT EDIT: This section is automatically generated by eng/common/scripts/sync-labels.ts, update eng/common/labels.yaml run pnpm sync-labels to update -->

#### issue_kinds

Issue kinds

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

#### area

Area of the codebase

| Name | Color | Description |
| ---------------------------- | ------- | ----------------------------------- |
| `compiler:core` | #453261 | Issues for @typespec/compiler |
| `compiler:emitter-framework` | #453261 | Issues for the emitter framework |
| `ide` | #846da1 | Issues for VS, VSCode, Monaco, etc. |
| `lib:http` | #c7aee6 | |
| `lib:openapi` | #c7aee6 | |
| `lib:rest` | #c7aee6 | |
| `lib:versioning` | #c7aee6 | |
| `meta:blog` | #007dc8 | Blog updates |
| `meta:website` | #007dc8 | TypeSpec.io updates |
| `Service Codegen` | #7C4B1E | |
| `tspd` | #004185 | Issues for the tspd tool |
| `emitter:client:csharp` | #e1b300 | |
| `emitter:json-schema` | #957300 | |
| `emitter:protobuf` | #957300 | The protobuf emitter |
| `emitter:service:csharp` | #967200 | |
| `emitter:service:js` | #967200 | |
| `eng` | #65bfff | |

#### breaking-change

Labels around annotating issues and PR if they contain breaking change or deprecation

| Name | Color | Description |
| ----------------- | ------- | ---------------------------------------------------------------------------------- |
| `breaking-change` | #B60205 | A change that might cause specs or code to break |
| `deprecation` | #760205 | A previously supported feature will now report a warning and eventually be removed |

#### design-issues

Design issue management

| Name | Color | Description |
| ----------------- | ------- | ------------------------------------------------------ |
| `design:accepted` | #1a4421 | Proposal for design has been discussed and accepted. |
| `design:needed` | #96c499 | A design request has been raised that needs a proposal |
| `design:proposed` | #56815a | Proposal has been added and ready for discussion |

#### process

Process labels

| Name | Color | Description |
| -------------- | ------- | --------------------------------------------------------------------------------- |
| `needs-triage` | #ffffff | |
| `needs-info` | #ffffff | Mark an issue that needs reply from the author or it will be closed automatically |
| `triaged:core` | #5319e7 | |

#### misc

Misc labels

| Name | Color | Description |
| -------------------------- | ------- | ------------------ |
| `Client Emitter Migration` | #FD92F0 | |
| `good first issue` | #7057ff | Good for newcomers |

<!-- LABEL GENERATED REF END -->

### Updating labels

Labels are configured in `eng/common/labels.yaml`. To update labels, edit this file and run `pnpm sync-labels`.
**If you create a new label in github UI without updating the `labels.yaml` file, it WILL be automatically removed**

# TypeSpec Emitters

Expand Down
7 changes: 3 additions & 4 deletions eng/common/labels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ issue_kinds:
docs:
color: cccccc
description: Improvements or additions to documentation

epic:
color: cccccc
description: ""
area:
description: "Area of the codebase"
labels:
Expand Down Expand Up @@ -49,9 +51,6 @@ area:
tspd:
color: "004185"
description: Issues for the tspd tool
epic:
color: cccccc
description: ""
emitter:client:csharp:
color: e1b300
description: ""
Expand Down
93 changes: 79 additions & 14 deletions eng/common/scripts/sync-labels.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { Octokit } from "@octokit/rest";
import { readFile } from "fs/promises";
import { readFile, writeFile } from "fs/promises";
import { dirname, resolve } from "path";
import pc from "picocolors";
import { format, resolveConfig } from "prettier";
import { fileURLToPath } from "url";
import { inspect, parseArgs } from "util";
import { parse } from "yaml";

const labelFile = resolve(dirname(fileURLToPath(import.meta.url)), "../labels.yaml");
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
const labelFileRelative = "eng/common/labels.yaml";
const labelFile = resolve(repoRoot, labelFileRelative);
const contributingFile = resolve(repoRoot, "CONTRIBUTING.md");
const magicComment = {
start: "<!-- LABEL GENERATED REF START -->",
end: "<!-- LABEL GENERATED REF END -->",
} as const;

const repo = {
owner: "microsoft",
Expand Down Expand Up @@ -46,6 +53,8 @@ async function main() {
if (options.values["update-github-labels"]) {
await updateGithubLabels(labels.labels, { dryRun: options.values["dry-run"] });
}

updateContributingFile(labels, { dryRun: options.values["dry-run"] });
}

function loadLabels(yamlContent: string): LabelsConfig {
Expand Down Expand Up @@ -97,11 +106,11 @@ function prettyLabel(label: Label, padEnd: number = 0) {
return `${pc.cyan(label.name.padEnd(padEnd))} ${pc.blue(`#${label.color}`)} ${pc.gray(label.description)}`;
}

interface UpdateGithubLabelOptions {
interface ActionOptions {
readonly dryRun?: boolean;
}

async function updateGithubLabels(labels: Label[], options: UpdateGithubLabelOptions = {}) {
async function updateGithubLabels(labels: Label[], options: ActionOptions = {}) {
if (!options.dryRun && !process.env.GITHUB_TOKEN) {
throw new Error(
"GITHUB_TOKEN environment variable is required when not running in dry-run mode"
Expand Down Expand Up @@ -149,22 +158,18 @@ async function fetchAllLabels(octokit: Octokit) {
return result;
}

function logAction(message: string, options: UpdateGithubLabelOptions) {
function logAction(message: string, options: ActionOptions) {
const prefix = options.dryRun ? `${pc.gray("[dry-run]")} ` : "";
console.log(prefix + message);
}

async function doAction(
action: () => Promise<unknown>,
label: string,
options: UpdateGithubLabelOptions
) {
async function doAction(action: () => Promise<unknown>, label: string, options: ActionOptions) {
if (!options.dryRun) {
await action();
}
logAction(label, options);
}
async function createLabels(octokit: Octokit, labels: Label[], options: UpdateGithubLabelOptions) {
async function createLabels(octokit: Octokit, labels: Label[], options: ActionOptions) {
for (const label of labels) {
await doAction(
() => octokit.rest.issues.createLabel({ ...repo, ...label }),
Expand All @@ -173,7 +178,7 @@ async function createLabels(octokit: Octokit, labels: Label[], options: UpdateGi
);
}
}
async function updateLabels(octokit: Octokit, labels: Label[], options: UpdateGithubLabelOptions) {
async function updateLabels(octokit: Octokit, labels: Label[], options: ActionOptions) {
for (const label of labels) {
await doAction(
() => octokit.rest.issues.updateLabel({ ...repo, ...label }),
Expand All @@ -182,7 +187,7 @@ async function updateLabels(octokit: Octokit, labels: Label[], options: UpdateGi
);
}
}
async function deleteLabels(octokit: Octokit, labels: string[], options: UpdateGithubLabelOptions) {
async function deleteLabels(octokit: Octokit, labels: string[], options: ActionOptions) {
for (const name of labels) {
await doAction(
() => octokit.rest.issues.deleteLabel({ ...repo, name }),
Expand All @@ -204,3 +209,63 @@ function validateLabel(label: Label) {
throw new Error(`Label missing description: ${inspect(label)}`);
}
}

async function updateContributingFile(labels: LabelsConfig, options: ActionOptions) {
console.log("Updating contributing file", contributingFile);
const content = await readFile(contributingFile, "utf8");
const startIndex = content.indexOf(magicComment.start);
const endIndex = content.indexOf(magicComment.end);
if (startIndex === -1) {
throw new Error(`Could not find start comment "${magicComment.start}" in ${contributingFile}`);
}
const start = content.slice(0, startIndex + magicComment.start.length);
const end =
endIndex === -1
? magicComment.end + "\n" + content.slice(startIndex + magicComment.start.length)
: content.slice(endIndex);

const warning = `<!-- DO NOT EDIT: This section is automatically generated by eng/common/scripts/sync-labels.ts, update ${labelFileRelative} run pnpm sync-labels to update -->`;
const newContent = `${start}\n${warning}\n${generateLabelsDoc(labels)}\n${end}`;
const prettierOptions = await resolveConfig(contributingFile);
const formatted = await format(newContent, { ...prettierOptions, filepath: contributingFile });
await doAction(
() => writeFile(contributingFile, formatted),
"Updated contributing file",
options
);
}

function generateLabelsDoc(labels: LabelsConfig) {
return [
"### Labels reference",
...labels.categories.map((category) => {
return `#### ${category.name}\n\n${category.description}\n\n${table([
["Name", "Color", "Description"],
...category.labels.map((label) => [
inlinecode(label.name),
`#${label.color}`,
label.description,
]),
])}`;
}),
].join("\n");
}

// #region markdown helpers
export function inlinecode(code: string) {
return "`" + code + "`";
}
function escapeMarkdownTable(text: string) {
return text.replace(/([^\\])(\|)/g, "$1\\$2").replace(/\n/g, "<br />");
}

function table([header, ...rows]: string[][]) {
const renderRow = (row: string[]): string => `| ${row.map(escapeMarkdownTable).join(" | ")} |`;

return [
renderRow(header),
"|" + header.map((x) => "-".repeat(x.length + 2)).join("|") + "|",
...rows.map(renderRow),
].join("\n");
}
// #endregion

0 comments on commit ce6abba

Please sign in to comment.