Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
e9dc816
Add logic to auto-signoff open-api-specs with trivial changes
Nov 12, 2025
b9618b0
Updates based on comments, Refactor trivial check
Dec 4, 2025
71db523
Merge origin/main
Dec 4, 2025
be72bbb
Fix references with file move
Dec 4, 2025
056a31b
Fix invalid chars in upload artifact step
Dec 4, 2025
177dab9
Fix tests
Dec 5, 2025
422cd6a
Address comments, Add more tests
Dec 9, 2025
495559e
whitespace
mikeharder Dec 9, 2025
cf58b5d
Merge with main, Resolve conflicts
Dec 10, 2025
1a584be
Resolve merge conflict
Dec 10, 2025
189eaa8
minor changes based on comments
Dec 10, 2025
99b3e9c
rename step
mikeharder Dec 11, 2025
b55614c
Revert workflow title
mikeharder Dec 11, 2025
0cd5fdd
Revert workflow title
mikeharder Dec 11, 2025
6f96b9a
revert step title
mikeharder Dec 11, 2025
dfc2e2b
Refcatoring based on comments
Dec 11, 2025
d3f0d6a
Pull remote
Dec 11, 2025
40ae297
Merge branch 'main' into ailla/auto_signoff_trivial_changes
mikeharder Dec 11, 2025
7a97f5d
fix missing token error
Dec 11, 2025
46dbf3d
Merge branch 'ailla/auto_signoff_trivial_changes' of https://github.c…
Dec 11, 2025
ac95780
Merge branch 'main' into ailla/auto_signoff_trivial_changes
mikeharder Dec 11, 2025
9e903c0
Merge branch 'ailla/auto_signoff_trivial_changes' of https://github.c…
Dec 11, 2025
072d824
resolve merge conflict
mikeharder Dec 11, 2025
c653cde
Delete documentation/trivial-changes-auto-signoff.md
mikeharder Dec 11, 2025
ace0e72
Merge branch 'ailla/auto_signoff_trivial_changes' of https://github.c…
Dec 11, 2025
8370e9e
Merge branch 'main' into ailla/auto_signoff_trivial_changes
mikeharder Dec 11, 2025
9c07141
remove unhelpful comment
mikeharder Dec 11, 2025
55e2999
revert names
mikeharder Dec 11, 2025
8562b2a
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Dec 11, 2025
839b12e
whitespace
mikeharder Dec 11, 2025
f1daaf8
ARM auto-signoff: trivial changes + managed label actions
Dec 16, 2025
6e7211a
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Dec 16, 2025
52c85df
formatting
mikeharder Dec 16, 2025
9c77e73
yaml: "if" before "name"
mikeharder Dec 16, 2025
1146025
Refactor dryrun mode and just add trivial-test label, Update PRChange…
Dec 17, 2025
ef4eea1
Pull remote changes
Dec 17, 2025
710184e
Refactor, updates based on PR comments
Dec 19, 2025
0028fc2
Merge branch 'main' into ailla/auto_signoff_trivial_changes
mikeharder Jan 6, 2026
55ac6a5
Refactor pr-changes from struct to class, update the use cases, tests
Jan 6, 2026
d24335b
Merge branch 'ailla/auto_signoff_trivial_changes' of https://github.c…
Jan 6, 2026
827dffd
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 6, 2026
8b5b83a
Refactor naming, Fix lint errors
Jan 7, 2026
bef163e
Fix prettier errors
Jan 7, 2026
57cca4b
Fix prettier errors, Refactor trivial changes, minor updates
Jan 10, 2026
afa86d0
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 13, 2026
c9a2907
Fix prettier failures
Jan 13, 2026
902d29d
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 14, 2026
1816f7b
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 14, 2026
d8d3b38
Update log statements, Fix auto sign off label list
Jan 14, 2026
539cc10
Update trivial changes logic to evaluate functional changes
Jan 20, 2026
c5e62f8
Remove updated timeouts in test
Jan 20, 2026
f1bb347
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 21, 2026
41e4df1
Updates made to address feedback
Jan 22, 2026
e349a36
Fix prettier issue
Jan 22, 2026
8219f65
Merge branch 'main' of https://github.com/Azure/azure-rest-api-specs …
Jan 22, 2026
cccd378
fix space
Jan 22, 2026
b46058a
fix prettier issue
Jan 22, 2026
4977cd3
Merge branch 'main' into ailla/auto_signoff_trivial_changes
AkhilaIlla Jan 23, 2026
f940d86
Merge branch 'main' into ailla/auto_signoff_trivial_changes
AkhilaIlla Jan 26, 2026
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
9 changes: 9 additions & 0 deletions .github/shared/src/changed-files.js
Comment thread
mikeharder marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import debug from "debug";
import { simpleGit } from "simple-git";
import { includesSegment } from "./path.js";
Expand Down Expand Up @@ -179,6 +179,15 @@
return typeof file === "string" && file.toLowerCase().endsWith("readme.md");
}

/**
* @param {string} [file]
* @returns {boolean}
*/
export function markdown(file) {
// Extension ".md" with any case is a valid markdown file
return typeof file === "string" && file.toLowerCase().endsWith(".md");
}

Comment thread
mikeharder marked this conversation as resolved.
Outdated
/**
* @param {string} [file]
* @returns {boolean}
Expand Down
86 changes: 86 additions & 0 deletions .github/shared/src/pr-changes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* Represents the types of changes present in a pull request.
*
* All properties are boolean flags that indicate presence of a change type.
* An empty PR would have all properties set to false.
*
* @typedef {Object} PullRequestChanges
* @property {boolean} documentation - True if PR contains documentation (.md) file changes
* @property {boolean} examples - True if PR contains example file changes (/examples/*.json)
* @property {boolean} functional - True if PR contains functional spec changes (API-impacting)
* @property {boolean} nonFunctional - True if PR contains non-functional spec changes (metadata only)
Comment thread
AkhilaIlla marked this conversation as resolved.
Outdated
* @property {boolean} other - True if PR contains other file types (config, scripts, etc.)
*/

/**
* Creates a PullRequestChanges object with all flags set to false
* @returns {PullRequestChanges}
*/
export function createEmptyPullRequestChanges() {
return {
documentation: false,
examples: false,
functional: false,
nonFunctional: false,
other: false,
};
}

/**
* Checks if a PR qualifies as trivial based on its changes
* A PR is trivial if it contains only:
* - Documentation changes
* - Example changes
* - Non-functional spec changes
* And does NOT contain:
* - Functional spec changes
* - Other file types
*
* @param {PullRequestChanges} changes - The PR changes object
* @returns {boolean} - True if PR is trivial
*/
export function isTrivialPullRequest(changes) {
// Trivial if no functional changes and no other files
// Must have at least one of: documentation, examples, or nonFunctional
const hasNoBlockingChanges = !changes.functional && !changes.other;
const hasTrivialChanges = changes.documentation || changes.examples || changes.nonFunctional;

return hasNoBlockingChanges && hasTrivialChanges;
}

/**
* Checks if a PR contains only documentation changes
* @param {PullRequestChanges} changes - The PR changes object
* @returns {boolean} - True if only documentation changed
*/
export function isDocumentationOnly(changes) {
return changes.documentation &&
!changes.examples &&
!changes.functional &&
!changes.nonFunctional &&
!changes.other;
}

/**
* Checks if a PR contains only example changes
* @param {PullRequestChanges} changes - The PR changes object
* @returns {boolean} - True if only examples changed
*/
export function isExamplesOnly(changes) {
return !changes.documentation &&
changes.examples &&
!changes.functional &&
!changes.nonFunctional &&
!changes.other;
}

/**
* Checks if a PR contains only non-functional spec changes (with optional docs/examples)
* @param {PullRequestChanges} changes - The PR changes object
* @returns {boolean} - True if only non-functional changes (+ optional docs/examples)
*/
export function isNonFunctionalOnly(changes) {
return changes.nonFunctional &&
!changes.functional &&
!changes.other;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ARM Incremental TypeSpec
name: ARM Auto-SignOff - Analyze Code
Comment thread
mikeharder marked this conversation as resolved.
Outdated

on:
pull_request:
Expand All @@ -20,16 +20,18 @@
contents: read

jobs:
arm-incremental-typespec:
name: ARM Incremental TypeSpec
arm-auto-signoff-code:
name: ARM Auto-SignOff - Analyze Code
Comment thread
mikeharder marked this conversation as resolved.
Outdated

runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v4
with:
# Required to detect changed files in PR
fetch-depth: 2
# Fetch full PR history including base branch for proper diff comparison
Comment thread
AkhilaIlla marked this conversation as resolved.
Outdated
fetch-depth: 0
# Fetch base branch to compare against
ref: ${{ github.event.pull_request.head.sha }}
Comment thread
mikeharder marked this conversation as resolved.
Outdated
# Check only needs to view contents of changed files as a string, so can use
# "git show" on specific files instead of cloning whole repo
sparse-checkout: |
Expand All @@ -45,19 +47,20 @@
install-command: "npm ci --no-audit --omit dev"
working-directory: ./.github

# Output is "true" if PR contains only incremental changes to an existing TypeSpec RP
- id: incremental-typespec
name: ARM Incremental TypeSpec
# Run ARM Auto-SignOff Code analysis
- id: arm-auto-signoff-code
name: ARM Auto-SignOff Code
uses: actions/github-script@v7
with:
result-encoding: string
Comment thread
AkhilaIlla marked this conversation as resolved.
Outdated
script: |
const { default: incrementalTypeSpec } =
await import('${{ github.workspace }}/.github/workflows/src/arm-incremental-typespec.js');
return await incrementalTypeSpec({ github, context, core });
const { default: armAutoSignOffCode } =
await import('${{ github.workspace }}/.github/workflows/src/arm-auto-signoff/arm-auto-signoff-code.js');
return await armAutoSignOffCode({ github, context, core });

- name: Upload artifact with results
# Upload artifact with all results
- name: Upload artifact - ARM Auto-SignOff Code Results
uses: ./.github/actions/add-empty-artifact
with:
name: "incremental-typespec"
value: ${{ steps.incremental-typespec.outputs.result }}
name: "arm-auto-signoff-code-results"
value: ${{ steps.arm-auto-signoff-code.outputs.result }}
Comment thread
mikeharder marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ARM Auto SignOff
name: ARM Auto SignOff - Set Status

on:
# Must run on pull_request_target instead of pull_request, since the latter cannot trigger on
Expand All @@ -12,7 +12,7 @@
- unlabeled
workflow_run:
workflows:
["ARM Incremental TypeSpec", "Swagger Avocado - Set Status", "Swagger LintDiff - Set Status"]
["ARM Auto-SignOff - Analyze Code", "Swagger Avocado - Set Status", "Swagger LintDiff - Set Status"]
types: [completed]

permissions:
Expand All @@ -30,7 +30,7 @@

jobs:
arm-auto-signoff:
name: ARM Auto SignOff
name: ARM Auto SignOff - Set Status

# workflow_run - already filtered by triggers above
# pull_request_target:labeled - filter to only the input and output labels
Expand All @@ -40,7 +40,8 @@
(github.event.action == 'labeled' ||
github.event.action == 'unlabeled') &&
(github.event.label.name == 'Approved-Suppression' ||
github.event.label.name == 'ARMAutoSignedOff' ||
github.event.label.name == 'ARMAutoSignedOff-IncrementalTSP' ||
Comment thread
AkhilaIlla marked this conversation as resolved.
Comment thread
mikeharder marked this conversation as resolved.
github.event.label.name == 'ARMAutoSignedOff-Trivial' ||
github.event.label.name == 'ARMReview' ||
github.event.label.name == 'ARMSignedOff' ||
github.event.label.name == 'NotReadyForARMReview' ||
Expand Down Expand Up @@ -69,33 +70,36 @@
# issueNumber: number
# }
- id: get-label-action
name: ARM Auto SignOff
name: ARM Auto SignOff
Comment thread
mikeharder marked this conversation as resolved.
Outdated
uses: actions/github-script@v7
with:
script: |
const { default: getLabelAction } =
await import('${{ github.workspace }}/.github/workflows/src/arm-auto-signoff.js');
await import('${{ github.workspace }}/.github/workflows/src/arm-auto-signoff/arm-auto-signoff-status.js');
return await getLabelAction({ github, context, core });

- if: |
fromJson(steps.get-label-action.outputs.result).labelAction == 'add' ||
fromJson(steps.get-label-action.outputs.result).labelAction == 'remove'
name: Upload artifact with results
# Add/remove specific auto sign-off labels based on analysis results
# Only upload label artifacts if we have autoSignOffLabels defined (not undefined)
- if: fromJson(steps.get-label-action.outputs.result).autoSignOffLabels != null
name: Upload artifact for ARMSignedOff label
uses: ./.github/actions/add-label-artifact
with:
name: "ARMAutoSignedOff"
# Convert "add/remove" to "true/false"
value: "${{ fromJson(steps.get-label-action.outputs.result).labelAction == 'add' }}"
name: "ARMSignedOff"
value: "${{ fromJson(steps.get-label-action.outputs.result).autoSignOffLabels && (contains(fromJson(steps.get-label-action.outputs.result).autoSignOffLabels, 'ARMAutoSignedOff-IncrementalTSP') || contains(fromJson(steps.get-label-action.outputs.result).autoSignOffLabels, 'ARMAutoSignedOff-Trivial')) }}"

- if: |
fromJson(steps.get-label-action.outputs.result).labelAction == 'add' ||
fromJson(steps.get-label-action.outputs.result).labelAction == 'remove'
name: Upload artifact with results
- if: fromJson(steps.get-label-action.outputs.result).autoSignOffLabels != null
name: Upload artifact for ARMAutoSignedOff-IncrementalTSP label
uses: ./.github/actions/add-label-artifact
with:
name: "ARMSignedOff"
# Convert "add/remove" to "true/false"
value: "${{ fromJson(steps.get-label-action.outputs.result).labelAction == 'add' }}"
name: "ARMAutoSignedOff-IncrementalTSP"
value: "${{ fromJson(steps.get-label-action.outputs.result).autoSignOffLabels && contains(fromJson(steps.get-label-action.outputs.result).autoSignOffLabels, 'ARMAutoSignedOff-IncrementalTSP') }}"

- if: fromJson(steps.get-label-action.outputs.result).autoSignOffLabels != null
name: Upload artifact for ARMAutoSignedOff-Trivial label
uses: ./.github/actions/add-label-artifact
with:
name: "ARMAutoSignedOff-Trivial"
value: "${{ fromJson(steps.get-label-action.outputs.result).autoSignOffLabels && contains(fromJson(steps.get-label-action.outputs.result).autoSignOffLabels, 'ARMAutoSignedOff-Trivial') }}"

# Required for consumers to identify the head SHA associated with this workflow run.
# Output can be trusted, because it was uploaded from a workflow that is trusted,
Expand Down
Loading
Loading