Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TypeSpecRequirement] Add upgrade notice to brownfield specs #31814

Merged
merged 74 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
0b1568d
Log notice, set output var
mikeharder Oct 1, 2024
f870b43
Upload artifact named "key--value"
mikeharder Oct 1, 2024
97e076e
Only upload artifact if output set
mikeharder Oct 1, 2024
d928d02
Improve comment
mikeharder Oct 1, 2024
6df9cd3
Add completed workflow
mikeharder Oct 1, 2024
98612e2
Fix artifact name
mikeharder Oct 1, 2024
5626021
Typo
mikeharder Oct 1, 2024
6ccbd2c
pretty-print
mikeharder Oct 1, 2024
b8458c7
Sparse checkout
mikeharder Oct 1, 2024
267f3fa
Remove unnecessary aritfact download
mikeharder Oct 2, 2024
c6ea8f0
WIP: Fix scripts
mikeharder Oct 2, 2024
8b9d815
Yaml parameter destructuring
mikeharder Oct 2, 2024
3434be6
Fix script args
mikeharder Oct 2, 2024
b7aaf09
Use "=" in artifact name
mikeharder Oct 25, 2024
e9121d6
Add trailing newline
mikeharder Oct 25, 2024
6aea1ef
Use composite actions
mikeharder Oct 25, 2024
77a05cc
Fix upload
mikeharder Oct 25, 2024
10e5b53
WIP: get keyvalue artifacts
mikeharder Oct 25, 2024
b5437ea
Update scripts path
mikeharder Oct 26, 2024
bb15740
empty commit
mikeharder Oct 31, 2024
e24152e
Add script file
mikeharder Oct 31, 2024
d25046e
Pass arguments correctly
mikeharder Oct 31, 2024
b8fecea
WIP: Implement get-keyvaule-artifacts action
mikeharder Oct 31, 2024
ddbb051
Flow inputs
mikeharder Oct 31, 2024
7d69904
Pass owner, repo, and run_id via env vars
mikeharder Oct 31, 2024
0b7c899
Print env after setting
mikeharder Oct 31, 2024
1f393ca
Use env var
mikeharder Oct 31, 2024
c51e806
Re-organize .github folder
mikeharder Nov 1, 2024
1a2d217
Add .github to root package.json
mikeharder Nov 1, 2024
616a59a
Revert "Add .github to root package.json"
mikeharder Nov 4, 2024
c5eee69
Prevent warning in VS Code
mikeharder Nov 4, 2024
4b7729f
Restore package-lock.json
mikeharder Nov 4, 2024
f93bfbb
Improve comment
mikeharder Nov 4, 2024
bb5c325
Make workflow_dispatch parameters required
mikeharder Nov 5, 2024
b8376dd
Fix bug checking event action
mikeharder Nov 5, 2024
fb0363f
Remove old comment
mikeharder Nov 5, 2024
cdd603d
Only update vars not already set
mikeharder Nov 5, 2024
fc11f44
Fix context check
mikeharder Nov 5, 2024
c5f43ae
Use payload.action
mikeharder Nov 5, 2024
49d1573
Add action "set-label"
mikeharder Nov 13, 2024
1b1b82b
Add LogNotice
mikeharder Nov 13, 2024
8ba1b21
Remove extra whitespace
mikeharder Nov 13, 2024
3677ba9
Extract owner and repo from head_repository
mikeharder Nov 13, 2024
7ce0d1b
Use target owner and repo to set label
mikeharder Nov 13, 2024
80704da
Improve comment
mikeharder Nov 13, 2024
7b15c4e
Shared function to extract inputs from context
mikeharder Nov 13, 2024
881ab99
Ignore errors removing label
mikeharder Nov 13, 2024
ac86643
Remove context logging
mikeharder Nov 13, 2024
9efc5cb
Add run_id to inputs
mikeharder Nov 13, 2024
df03c45
Restore package-lock.json
mikeharder Nov 13, 2024
6aacb70
Cleanup
mikeharder Nov 13, 2024
8cb91e5
Add logging
mikeharder Nov 14, 2024
32d230c
Support "pull_request" event type
mikeharder Nov 15, 2024
623d011
Remove commit_sha input
mikeharder Nov 15, 2024
79f0d2f
Rename workflow to "Update Labels" and run on label triggers
mikeharder Nov 15, 2024
da8e5ee
WIP: Add support for getting artifacts from an issue_number
mikeharder Nov 15, 2024
7defa4b
Rename to add-label-artifact
mikeharder Nov 15, 2024
34fb0be
Fix job name
mikeharder Nov 15, 2024
0eacd2c
Remove matrix from TypeSpec Requirement
mikeharder Nov 15, 2024
b6e7b87
Fix input name
mikeharder Nov 15, 2024
ba82cdb
Simplify output
mikeharder Nov 15, 2024
2585c0a
[set-label] Default value to "true"
mikeharder Nov 15, 2024
bba99f6
Refactor to create update-labels composite action
mikeharder Nov 15, 2024
072171f
Add comment
mikeharder Nov 15, 2024
c833eb9
WIP: Get workflows from head_sha
mikeharder Nov 27, 2024
ec34ded
Remove labeled and unlabeled triggers
mikeharder Dec 9, 2024
5a9cf1f
Add head_sha to workflow_run inputs
mikeharder Dec 9, 2024
f0806c1
Improve comments
mikeharder Dec 9, 2024
2df306a
Improve description
mikeharder Dec 9, 2024
b4c1d74
Use "for of" instead of "for in"
mikeharder Dec 9, 2024
290545b
grammar
mikeharder Dec 9, 2024
16de04c
Revert accidental change
mikeharder Dec 9, 2024
8791aee
Improve description
mikeharder Dec 9, 2024
a15deba
Merge branch 'main' into brownfield-notice-workflow-run
mikeharder Dec 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
mikeharder marked this conversation as resolved.
Show resolved Hide resolved
required: true

runs:
using: composite

steps:
- name: Create empty file to upload artifact
run: "> $RUNNER_TEMP/empty.txt"
mikeharder marked this conversation as resolved.
Show resolved Hide resolved
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
mikeharder marked this conversation as resolved.
Show resolved Hide resolved

// 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) {
mikeharder marked this conversation as resolved.
Show resolved Hide resolved
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
Loading