forked from Azure/azure-rest-api-specs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SDK Suppressions labels] Add new action to update suppressions labels (
Azure#31878) * initial version * use variables to be used in next steps * removed unused code and test branch * added function description * updated dependencies * removed test branch * add comment to to explain this behavior * Add trailing newline --------- Co-authored-by: Mike Harder <mharder@microsoft.com> Co-authored-by: Ray Chen <raychen@microsoft.com>
- Loading branch information
Showing
14 changed files
with
952 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
name: SDK Suppressions | ||
|
||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
- RPSaaSMaster | ||
- release* | ||
|
||
jobs: | ||
process-sdk-suppressions-labels: | ||
name: Sdk Suppressions | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
# Required since "HEAD^" is passed to Get-ChangedFiles | ||
fetch-depth: 2 | ||
|
||
- name: Setup Node and run `npm ci` | ||
uses: ./.github/actions/setup-node-npm-ci | ||
|
||
- name: Get GitHub PullRequest Changed Files | ||
shell: pwsh | ||
id: get-changedFiles | ||
run: | | ||
. eng/scripts/ChangedFiles-Functions.ps1 | ||
$changedFiles = @(Get-ChangedFiles) | ||
echo "PR Changed files: $changedFiles" | ||
Add-Content -Path $env:GITHUB_OUTPUT -Value "changedFiles=$changedFiles" | ||
- name: Get GitHub PullRequest Context | ||
uses: actions/github-script@v7 | ||
id: fetch-pullRequest-context | ||
with: | ||
script: | | ||
const pr = context.payload.pull_request; | ||
if (!pr) { | ||
throw new Error("This workflow must run in the context of a pull request."); | ||
} | ||
console.log("This action trigger by ", context.eventName); | ||
core.setOutput("prLabels", pr.labels.map(label => label.name)); | ||
result-encoding: string | ||
|
||
- name: Run Get suppressions label script | ||
id: run-suppressions-script | ||
env: | ||
OUTPUT_FILE: "output.json" | ||
GITHUB_PULL_REQUEST_CHANGE_FILES: ${{ steps.get-changedFiles.outputs.changedFiles }} | ||
GITHUB_PULL_REQUEST_LABELS: ${{ steps.fetch-pullRequest-context.outputs.prLabels }} | ||
run: | | ||
node eng/tools/sdk-suppressions/cmd/sdk-suppressions-label.js HEAD^ HEAD "$GITHUB_PULL_REQUEST_CHANGE_FILES" "$GITHUB_PULL_REQUEST_LABELS" | ||
OUTPUT=$(cat $OUTPUT_FILE) | ||
echo "Script output labels: $OUTPUT" | ||
labelsToAdd=$(echo "$OUTPUT" | sed -n 's/.*"labelsToAdd":\[\([^]]*\)\].*/\1/p' | tr -d '" ') | ||
labelsToRemove=$(echo "$OUTPUT" | sed -n 's/.*"labelsToRemove":\[\([^]]*\)\].*/\1/p' | tr -d '" ') | ||
for label in $(echo $labelsToAdd | tr ',' '\n'); do | ||
echo "Label to add: $label" | ||
echo "$label=true" >> $GITHUB_OUTPUT | ||
done | ||
for label in $(echo $labelsToRemove | tr ',' '\n'); do | ||
echo "Label to remove: $label" | ||
echo "$label=false" >> $GITHUB_OUTPUT | ||
done | ||
# No Action or Add/Remove label according to step run-suppressions-script output | ||
# e.g. | ||
# If the output of the step does not include the BreakingChange-Go-Sdk-Suppression, no action will be taken. | ||
# If the step's output is "BreakingChange-Go-Sdk-Suppression='true'", the label "BreakingChange-Go-Sdk-Suppression" will be applied to the PR. | ||
# If the step's output is "BreakingChange-Go-Sdk-Suppression='false'", the label "BreakingChange-Go-Sdk-Suppression" will be removed from the PR. | ||
- uses: ./.github/actions/add-label-artifact | ||
name: Upload artifact with results-go | ||
if: ${{ steps.run-suppressions-script.outputs.BreakingChange-Go-Sdk-Suppression }} | ||
with: | ||
name: "BreakingChange-Go-Sdk-Suppression" | ||
value: "${{ steps.run-suppressions-script.outputs.BreakingChange-Go-Sdk-Suppression == 'true' }}" | ||
|
||
- uses: ./.github/actions/add-label-artifact | ||
name: Upload artifact with results java | ||
if: ${{ steps.run-suppressions-script.outputs.BreakingChange-Java-Sdk-Suppression }} | ||
with: | ||
name: "BreakingChange-Java-Sdk-Suppression" | ||
value: "${{ steps.run-suppressions-script.outputs.BreakingChange-Java-Sdk-Suppression == 'true' }}" | ||
|
||
- uses: ./.github/actions/add-label-artifact | ||
name: Upload artifact with results js | ||
if: ${{ steps.run-suppressions-script.outputs.BreakingChange-JavaScript-Sdk-Suppression }} | ||
with: | ||
name: "BreakingChange-JavaScript-Sdk-Suppression" | ||
value: "${{ steps.run-suppressions-script.outputs.BreakingChange-JavaScript-Sdk-Suppression == 'true' }}" | ||
|
||
- uses: ./.github/actions/add-label-artifact | ||
name: Upload artifact with results python | ||
if: ${{ steps.run-suppressions-script.outputs.BreakingChange-Python-Sdk-Suppression }} | ||
with: | ||
name: "BreakingChange-Python-Sdk-Suppression" | ||
value: "${{ steps.run-suppressions-script.outputs.BreakingChange-Python-Sdk-Suppression == 'true' }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/usr/bin/env node | ||
|
||
import { main } from "../dist/src/index.js"; | ||
|
||
await main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "@azure-tools/sdk-suppressions", | ||
"private": true, | ||
"type": "module", | ||
"main": "dist/src/index.js", | ||
"version": "1.0.0", | ||
"bin": { | ||
"get-sdk-suppressions-label": "cmd/sdk-suppressions-label.js" | ||
}, | ||
"scripts": { | ||
"build": "tsc --build", | ||
"test": "vitest", | ||
"test:ci": "vitest run --coverage --reporter=verbose" | ||
}, | ||
"engines": { | ||
"node": ">= 18.0.0" | ||
}, | ||
"dependencies": { | ||
"ajv": "^8.17.1", | ||
"lodash": "^4.17.20", | ||
"yaml": "^2.4.2" | ||
}, | ||
"devDependencies": { | ||
"@types/lodash": "^4.14.161", | ||
"@types/node": "^18.19.31", | ||
"@vitest/coverage-v8": "^2.0.4", | ||
"typescript": "~5.6.2", | ||
"vitest": "^2.0.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { parse as yamlParse } from "yaml"; | ||
|
||
import { exec } from "child_process"; | ||
import { promisify } from "util"; | ||
|
||
/** | ||
* @param yamlContent | ||
* @returns {result: string | object | undefined | null, message: string} | ||
* special return | ||
* if the content is empty, return {result: null, message: string | ||
* if the file parse error, return {result: undefined, message: string | ||
*/ | ||
export function parseYamlContent(yamlContent: string, path: string): { | ||
result: string | object | undefined | null; | ||
message: string; | ||
}{ | ||
let content = undefined; | ||
// if yaml file is not a valid yaml, catch error and return undefined | ||
try { | ||
content = yamlParse(yamlContent); | ||
} catch (error) { | ||
console.error(`The file parsing failed in the ${path}. Details: ${error}`); | ||
return { | ||
result: content, | ||
message: `The file parsing failed in the ${path}. Details: ${error}` | ||
};; | ||
} | ||
|
||
// if yaml file is empty, run yaml.safeload success but get undefined | ||
// to identify whether it is empty return null to distinguish. | ||
if (!content) { | ||
console.info(`The file in the ${path} has been successfully parsed, but it is an empty file.`) | ||
return { | ||
result: null, | ||
message: `The file in the ${path} has been successfully parsed, but it is an empty file.` | ||
};; | ||
} | ||
|
||
return { | ||
result: content, | ||
message: 'The file has been successfully parsed.' | ||
}; | ||
|
||
} | ||
|
||
// Promisify the exec function | ||
const execAsync = promisify(exec); | ||
|
||
export async function runGitCommand(command: string): Promise<string> { | ||
try { | ||
const { stdout, stderr } = await execAsync(command); | ||
|
||
if (stderr) { | ||
console.error("Error Output:", stderr); | ||
// throw new Error(stderr); | ||
} | ||
|
||
return stdout.trim(); | ||
} catch (error:any) { | ||
console.error("Error details:", error.stderr || error); | ||
throw error; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
import { exit } from "process"; | ||
import { updateSdkSuppressionsLabels } from "./updateSdkSuppressionsLabel.js"; | ||
|
||
function getArgsError(args: string[]): string { | ||
return ( | ||
"Get args lengths: " + args.length + "\n" + | ||
"Details: " + args.join(', ') + "\n" + | ||
"Usage: node eng/tools/sdk-suppressions/cmd/sdk-suppressions-label.js baseCommitHash headCommitHash changeFiles prLabels\n" + | ||
"Returns: {labelsToAdd: [label1, label2],labelsToRemove: [lable3, label4]}\n" + | ||
"Parameters:\n" + | ||
" baseCommitHash: The base commit hash. Example: HEAD^ \n" + | ||
" headCommitHash: The head commit hash. Example: HEAD \n" + | ||
" changeFiles: The changed files. Example: 'specification/workloads/Workloads.Operations.Management/sdk-suppressions.yaml specification/workloads/Workloads.Operations.Management/main.tsp'\n" + | ||
" prLabels: The PR has added labels. Example: '['BreakingChange-Go-Sdk-Suppression', 'BreakingChange-Python-Sdk-Suppression']'\n" | ||
); | ||
} | ||
|
||
export async function main() { | ||
const args: string[] = process.argv.slice(2); | ||
if (args.length === 4) { | ||
const baseCommitHash: string = args[0]; | ||
const headCommitHash: string = args[1]; | ||
const changeFiles: string = args[2]; | ||
const lables: string = args[3]; | ||
const outputFile = process.env.OUTPUT_FILE as string; | ||
const changedLabels: {labelsToAdd: String[], labelsToRemove: String[]} = await updateSdkSuppressionsLabels(lables, changeFiles, baseCommitHash, headCommitHash, outputFile); | ||
console.log(JSON.stringify(changedLabels)); | ||
exit(0); | ||
} else { | ||
console.error(getArgsError(args)); | ||
exit(1); | ||
} | ||
|
||
} | ||
|
||
export { updateSdkSuppressionsLabels }; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* This file is the single source of truth for the labels used by the SDK generation tooling | ||
* in the Azure/azure-rest-api-specs and Azure/azure-rest-api-specs-pr repositories. | ||
* | ||
* For additional context, see: | ||
* - https://gist.github.com/raych1/353949d19371b69fb82a10dd70032a51 | ||
* - https://github.com/Azure/azure-sdk-tools/issues/6327 | ||
* - https://microsoftapc-my.sharepoint.com/:w:/g/personal/raychen_microsoft_com/EbOAA9SkhQhGlgxtf7mc0kUB-25bFue0EFbXKXS3TFLTQA | ||
*/ | ||
export type SdkName = | ||
| "azure-sdk-for-go" | ||
| "azure-sdk-for-java" | ||
| "azure-sdk-for-js" | ||
| "azure-sdk-for-net" | ||
| "azure-sdk-for-python" | ||
|
||
export const sdkLabels: { | ||
[sdkName in SdkName]: { | ||
breakingChange: string | undefined; | ||
breakingChangeApproved: string | undefined; | ||
breakingChangeSuppression: string | undefined; | ||
breakingChangeSuppressionApproved: string | undefined; | ||
}; | ||
} = { | ||
"azure-sdk-for-go": { | ||
breakingChange: "BreakingChange-Go-Sdk", | ||
breakingChangeApproved: "BreakingChange-Go-Sdk-Approved", | ||
breakingChangeSuppression: "BreakingChange-Go-Sdk-Suppression", | ||
breakingChangeSuppressionApproved: | ||
"BreakingChange-Go-Sdk-Suppression-Approved", | ||
}, | ||
"azure-sdk-for-java": { | ||
breakingChange: "BreakingChange-Java-Sdk", | ||
breakingChangeApproved: "BreakingChange-Java-Sdk-Approved", | ||
breakingChangeSuppression: "BreakingChange-Java-Sdk-Suppression", | ||
breakingChangeSuppressionApproved: | ||
"BreakingChange-Java-Sdk-Suppression-Approved" | ||
}, | ||
"azure-sdk-for-js": { | ||
breakingChange: "BreakingChange-JavaScript-Sdk", | ||
breakingChangeApproved: "BreakingChange-JavaScript-Sdk-Approved", | ||
breakingChangeSuppression: "BreakingChange-JavaScript-Sdk-Suppression", | ||
breakingChangeSuppressionApproved: | ||
"BreakingChange-JavaScript-Sdk-Suppression-Approved" | ||
}, | ||
"azure-sdk-for-net": { | ||
breakingChange: undefined, | ||
breakingChangeApproved: undefined, | ||
breakingChangeSuppression: undefined, | ||
breakingChangeSuppressionApproved: undefined | ||
}, | ||
"azure-sdk-for-python": { | ||
breakingChange: "BreakingChange-Python-Sdk", | ||
breakingChangeApproved: "BreakingChange-Python-Sdk-Approved", | ||
breakingChangeSuppression: "BreakingChange-Python-Sdk-Suppression", | ||
breakingChangeSuppressionApproved: | ||
"BreakingChange-Python-Sdk-Suppression-Approved" | ||
} | ||
}; |
Oops, something went wrong.