Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
mayankagg9722 authored Dec 16, 2024
2 parents 5ffbfcc + 5874020 commit 509f582
Show file tree
Hide file tree
Showing 1,608 changed files with 185,736 additions and 14,676 deletions.
4 changes: 3 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
/specification/domainservices/ @jihochang

# PRLabel: %Event Grid
/specification/eventgrid/ @Kishp01 @ahamad-MS
/specification/eventgrid/ @lmazuel @jsquire @JoshLove-msft @l0lawrence

# PRLabel: %Event Hubs
/specification/eventhub/ @v-ajnava @dsouzaarun @damodaravadhani
Expand Down Expand Up @@ -273,6 +273,8 @@
/specification/**/resource-manager/**/readme.go.md @tadelesh
/specification/**/resource-manager/**/readme.python.md @msyyc

/specification/contosowidgetmanager/ @mikeharder @raych1 @maririos

###########
# Eng Sys
###########
Expand Down
2 changes: 2 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ Switch to "Preview" on this description then select one of the choices below.
<a href="?expand=1&template=data_plane_template.md">Click here</a> to open a PR for a Data Plane API.

<a href="?expand=1&template=control_plane_template.md">Click here</a> to open a PR for a Control Plane (ARM) API.

<a href="?expand=1&template=sdk_configuration_template.md">Click here</a> to open a PR for only SDK configuration.
25 changes: 25 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/sdk_configuration_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# SDK configuration pull request

## Purpose of this PR

- [ ] Make changes to the SDK configuration only when there are no modifications to the API specification, eliminating the need for an ARM or Stewardship Board API review.

## Due diligence checklist

To merge this PR, you **must** go through the following checklist and confirm you understood
and followed the instructions by checking all the boxes:

- [ ] I confirm this PR is modifying only SDK configurations, and not API related specifications.
- [ ] I have reviewed and used the respective `tspconfig.yaml` templates:
- [ARM tspconfig template](https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.Management/tspconfig.yaml)
- [Data plane tspconfig template](https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml)

## Getting help

- First, carefully read through this PR description, from top to bottom. Fill out the `Purpose of this PR` and `Due diligence checklist`.
- If you don't have permissions to remove or add labels to the PR, request `write access` per [aka.ms/azsdk/access#request-access-to-rest-api-or-sdk-repositories](https://aka.ms/azsdk/access#request-access-to-rest-api-or-sdk-repositories)
- To understand what you must do next to merge this PR, see the `Next Steps to Merge` comment. It will appear within few minutes of submitting this PR and will continue to be up-to-date with current PR state.
- For guidance on fixing this PR CI check failures, see the hyperlinks provided in given failure and https://aka.ms/ci-fix.
- If the PR CI checks appear to be stuck in `queued` state, please add a comment with contents `/azp run`.
This should result in a new comment denoting a `PR validation pipeline` has started and the checks should be updated after few minutes.
- If the help provided by the previous points is not enough, post to https://aka.ms/azsdk/support/specreview-channel and link to this PR.
27 changes: 27 additions & 0 deletions .github/actions/add-label-artifact/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Add Label Artifact
description: Uploads an empty artifact named `label-${name}=${value}`, that's consumed by action "update-labels"

inputs:
name:
description: Name
required: true
value:
description: Value ("true" or "false")
required: true

runs:
using: composite

steps:
- name: Create empty file to upload artifact
run: "> $RUNNER_TEMP/empty.txt"
shell: bash

# The maximum length is reported to be 260 characters. A full list of invalid artifact name characters is documented here:
# https://github.com/actions/toolkit/blob/main/packages/artifact/src/internal/upload/path-and-artifact-name-validation.ts
- uses: actions/upload-artifact@v4
with:
name: label-${{ inputs.name }}=${{ inputs.value }}
path: ${{ runner.temp }}/empty.txt
if-no-files-found: error
overwrite: true
95 changes: 95 additions & 0 deletions .github/actions/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// @ts-check

/**
* Extracts inputs from context based on event name and properties.
* run_id is only defined for "workflow_run:completed" events.
*
* @param {import('github-script').AsyncFunctionArguments['github']} github
* @param {import('github-script').AsyncFunctionArguments['context']} context
* @param {import('github-script').AsyncFunctionArguments['core']} core
* @returns {Promise<{owner: string, repo: string, head_sha: string, issue_number: number, run_id: number }>}
*/
async function extractInputs(github, context, core) {
core.info(`extractInputs(${context.eventName}, ${context.payload.action})`);

// Add support for more event types as needed
if (context.eventName === "pull_request") {
const payload =
/** @type {import("@octokit/webhooks-types").PullRequestEvent} */ (
context.payload
);

const inputs = {
owner: payload.repository.owner.login,
repo: payload.repository.name,
head_sha: payload.pull_request.head.sha,
issue_number: payload.number,
run_id: NaN
};

core.info(`inputs: ${JSON.stringify(inputs)}`);

return inputs;
} else if (
context.eventName === "workflow_run" &&
context.payload.action === "completed"
) {
const payload =
/** @type {import("@octokit/webhooks-types").WorkflowRunCompletedEvent} */ (
context.payload
);

let issue_number;

const pull_requests = payload.workflow_run.pull_requests;
if (pull_requests && pull_requests.length > 0) {
// For non-fork PRs, we should be able to extract the PR number from the payload, which avoids an
// unnecessary API call. The listPullRequestsAssociatedWithCommit() API also seems to return
// empty for non-fork PRs.
issue_number = pull_requests[0].number;
} else {
// For fork PRs, we must call an API in the head repository to get the PR number in the target repository

// Owner and repo for the PR head (may differ from target for fork PRs)
const head_owner = payload.workflow_run.head_repository.owner.login;
const head_repo = payload.workflow_run.head_repository.name;
const head_sha = payload.workflow_run.head_sha;

core.info(
`listPullRequestsAssociatedWithCommit(${head_owner}, ${head_repo}, ${head_sha})`,
);
const { data: pullRequests } =
await github.rest.repos.listPullRequestsAssociatedWithCommit({
owner: head_owner,
repo: head_repo,
commit_sha: head_sha,
});

if (pullRequests.length === 1) {
issue_number = pullRequests[0].number;
} else {
throw new Error(
`Unexpected number of pull requests associated with commit '${head_sha}'. Expected: '1'. Actual '${pullRequests.length}'.`,
);
}
}

const inputs = {
owner: payload.workflow_run.repository.owner.login,
repo: payload.workflow_run.repository.name,
head_sha: payload.workflow_run.head_sha,
issue_number: issue_number,
run_id: payload.workflow_run.id,
};

core.info(`inputs: ${JSON.stringify(inputs)}`);

return inputs;
} else {
throw new Error(
`Invalid context: '${context.eventName}:${context.payload.action}'. Expected 'workflow_run:completed'.`,
);
}
}

module.exports = { extractInputs };
103 changes: 103 additions & 0 deletions .github/actions/update-labels/action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// @ts-check

const { extractInputs } = require("../context");

/**
* @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments
*/
module.exports = async ({ github, context, core }) => {
let owner = process.env.OWNER;
let repo = process.env.REPO;
let issue_number = parseInt(process.env.ISSUE_NUMBER || "");
let run_id = parseInt(process.env.RUN_ID || "");

if (!owner || !repo || !(issue_number || run_id)) {
let inputs = await extractInputs(github, context, core);
owner = owner || inputs.owner;
repo = repo || inputs.repo;
issue_number = issue_number || inputs.issue_number;
run_id = run_id || inputs.run_id;
}

/** @type {string[]} */
let artifactNames = [];

if (run_id) {
// List artifacts from a single run_id
core.info(`listWorkflowRunArtifacts(${owner}, ${repo}, ${run_id})`);
const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: owner,
repo: repo,
run_id: run_id,
});

artifactNames = artifacts.data.artifacts.map((a) => a.name);
} else {
// TODO: List all artifacts of all workflows associated with issue_number
throw new Error("Required input 'run_id' not found in env or context");
}

core.info(`artifactNames: ${JSON.stringify(artifactNames)}`);

/** @type {string[]} */
const labelsToAdd = [];

/** @type {string[]} */
const labelsToRemove = [];

for (const artifactName of artifactNames) {
// If artifactName has format "label-name=true|false", add or remove the label
// Else, if artifactName has format "label-name=other-string", throw an error
// Else, if artifactName does not start with "label-", ignore it
const firstEquals = artifactName.indexOf("=");
if (firstEquals !== -1) {
const key = artifactName.substring(0, firstEquals);
const value = artifactName.substring(firstEquals + 1);

if (key.startsWith("label-")) {
const name = key.substring("label-".length);
if (value === "true") {
labelsToAdd.push(name);
} else if (value === "false") {
labelsToRemove.push(name);
} else {
throw new Error(
`Invalid value for label '${name}': ${value}. Expected "true" or "false".`,
);
}
}
}
}

core.info(`labelsToAdd: ${JSON.stringify(labelsToAdd)}`);
core.info(`labelsToRemove: ${JSON.stringify(labelsToRemove)}`);

if (labelsToAdd.length > 0) {
await github.rest.issues.addLabels({
owner: owner,
repo: repo,
issue_number: issue_number,
labels: labelsToAdd,
});
}

if (labelsToRemove.length > 0) {
// Must loop over labelsToRemove ourselves, since GitHub doesn't expose a REST API to remove in bulk.
for (const name of labelsToRemove) {
try {
await github.rest.issues.removeLabel({
owner: owner,
repo: repo,
issue_number: issue_number,
name: name,
});
} catch (error) {
if (error.status === 404) {
core.info(`Ignoring error: ${error.status} - ${error.message}`);
} else {
throw error;
}
}
}
}
};
33 changes: 33 additions & 0 deletions .github/actions/update-labels/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Update Labels
description: Adds or removes labels to set state matching artifact names

# If any inputs are not set, we will attempt to extract them from the event context
inputs:
owner:
description: The account owner of the repository. The name is not case sensitive.
required: false
repo:
description: The name of the repository without the .git extension. The name is not case sensitive.
required: false
issue_number:
description: The issue that should have its labels updated.
required: false
run_id:
description: Updates labels from a single completed workflow.
required: false

runs:
using: composite

steps:
- name: Set Label
uses: actions/github-script@v7
env:
OWNER: ${{ inputs.owner }}
REPO: ${{ inputs.repo }}
ISSUE_NUMBER: ${{ inputs.issue_number }}
RUN_ID: ${{ inputs.run_id }}
with:
script: |
const action = require('./.github/actions/update-labels/action.js')
await action({ github, context, core });
Loading

0 comments on commit 509f582

Please sign in to comment.