Skip to content

Commit 3203b8b

Browse files
committed
Add initial workflow checks and sync v1.0
Signed-off-by: Aaron Chan <aaron.chun.yew.chan@intel.com>
1 parent b4e1893 commit 3203b8b

File tree

4 files changed

+417
-0
lines changed

4 files changed

+417
-0
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
#
4+
# GitHub Actions workflow to run yamllint on specific YAML files in a pull request.
5+
---
6+
name: Run YAML Lint
7+
on:
8+
pull_request:
9+
types:
10+
- opened
11+
- synchronize
12+
- reopened
13+
branches:
14+
- next-devel
15+
jobs:
16+
check:
17+
name: YAML Lint Check
18+
runs-on: bdba
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Setup Python
25+
uses: actions/setup-python@v4
26+
with:
27+
python-version: '3.x'
28+
29+
- name: Install PYPI packages
30+
run: pip install yamllint pyyaml
31+
32+
- name: Display YAML Lint version
33+
run: yamllint --version
34+
35+
- name: Bot Auto Assignee
36+
uses: actions/github-script@v7
37+
with:
38+
script: |
39+
github.rest.issues.addAssignees({
40+
owner: context.repo.owner,
41+
repo: context.repo.repo,
42+
issue_number: context.payload.pull_request.number,
43+
assignees: [context.actor],
44+
});
45+
46+
- name: Bot Auto Reviewer
47+
uses: actions/github-script@v7
48+
with:
49+
script: |
50+
try {
51+
await github.rest.pulls.requestReviewers({
52+
owner: context.repo.owner,
53+
repo: context.repo.repo,
54+
pull_number: context.payload.pull_request.number,
55+
reviewers: ['jinghuitham', 'JiayongT', 'Copilot'],
56+
});
57+
console.log('Reviewers added successfully');
58+
} catch (error) {
59+
core.setFailed(`Failed to add reviewers: ${error.message}`);
60+
}
61+
62+
- name: Bot Auto Labels
63+
uses: actions/github-script@v7
64+
with:
65+
script: |
66+
github.rest.issues.addLabels({
67+
owner: context.repo.owner,
68+
repo: context.repo.repo,
69+
issue_number: context.payload.pull_request.number,
70+
labels: ['needs-review'],
71+
});
72+
73+
- name: Bot assign PR title
74+
uses: actions/github-script@v7
75+
with:
76+
script: |
77+
78+
const { data: files } = await github.rest.pulls.listFiles({
79+
owner: context.repo.owner,
80+
repo: context.repo.repo,
81+
pull_number: context.payload.pull_request.number,
82+
});
83+
84+
const args = files.map(file => file.filename.split('/')[1]).filter(spec => spec !== undefined);
85+
86+
87+
const MAX_TITLE_LENGTH = 256;
88+
const title = context.payload.pull_request.title;
89+
let newTitle = title;
90+
91+
if (args.length > 0) {
92+
const prefix = 'Review Analysis Configuration File - ';
93+
const remainingForContent = Math.max(0, MAX_TITLE_LENGTH - prefix.length);
94+
95+
let displayedFiles = [];
96+
97+
for (let i = 0; i < args.length; i++) {
98+
const file = args[i];
99+
const nextFiles = displayedFiles.concat(file);
100+
const remainingCount = args.length - (i + 1);
101+
const moreText = remainingCount > 0 ? ` (+${remainingCount} more)` : '';
102+
const candidateContent = nextFiles.join(', ');
103+
const candidateTitle = prefix + candidateContent + moreText;
104+
105+
if (candidateTitle.length <= MAX_TITLE_LENGTH) {
106+
displayedFiles = nextFiles;
107+
} else {
108+
break;
109+
}
110+
}
111+
112+
let content = displayedFiles.join(', ');
113+
const remainingCountFinal = args.length - displayedFiles.length;
114+
if (remainingCountFinal > 0) {
115+
content += ` (+${remainingCountFinal} more)`;
116+
}
117+
118+
newTitle = prefix + content;
119+
}
120+
121+
try {
122+
await github.rest.pulls.update({
123+
owner: context.repo.owner,
124+
repo: context.repo.repo,
125+
pull_number: context.payload.pull_request.number,
126+
title: newTitle,
127+
});
128+
}
129+
catch (error) {
130+
core.setFailed(`Failed to update PR title: ${error.message}`);
131+
}
132+
133+
- name: Run YAML Linting
134+
if: github.event_name == 'pull_request'
135+
uses: actions/github-script@v7
136+
with:
137+
script: |
138+
// Run yamllint on changed YAML files in the PR
139+
const { data: files } = await github.rest.pulls.listFiles({
140+
owner: context.repo.owner,
141+
repo: context.repo.repo,
142+
pull_number: context.payload.pull_request.number,
143+
});
144+
console.log(files.map(file => file.filename).join('\n'));
145+
core.setOutput('files', files.map(file => file.filename).join('\n'));
146+
const command = 'yamllint';
147+
const args = files.map(file => file.filename);
148+
await exec.exec(command, args).catch(error => core.setFailed(error.message));
149+
// set environment variable for next steps
150+
core.exportVariable('EDGE_MT_SPECS', args.join(' '));
151+
// Add labels based on changed files
152+
const specs = args
153+
.map(file => file.split('/')[1])
154+
.filter(spec => spec !== undefined);
155+
// Add labels to the PR
156+
const validSpec = specs.filter(spec => spec && spec.trim().length >0);
157+
try {
158+
validSpec.forEach(spec => console.log(`Package to be labeled as ${spec}`));
159+
await github.rest.issues.addLabels({
160+
owner: context.repo.owner,
161+
repo: context.repo.repo,
162+
issue_number: context.payload.pull_request.number,
163+
labels: [...new Set(validSpec)],
164+
});
165+
}
166+
catch (error) {
167+
core.setFailed(`Failed to add labels: ${error.message}`);
168+
}
169+
170+
- name: Run YAML Syntax Checks
171+
run: |
172+
python3 scripts/check-bdba-yaml.py
173+
174+
- name: Bot End message
175+
uses: actions/github-script@v7
176+
with:
177+
script: |
178+
const username = context.payload.pull_request.user.login;
179+
const ref = context.payload.pull_request.head.ref;
180+
github.rest.issues.createComment({
181+
owner: context.repo.owner,
182+
repo: context.repo.repo,
183+
issue_number: context.payload.pull_request.number,
184+
body: `user @${username} updated the PR on branch ${ref}. YAML Linting and Syntax Checks rerun and was completed.`,
185+
});

.github/workflows/sync-repo.yml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
#
4+
# GitHub Actions workflow to sync SPECS edge-microvisor-toolkit repository to current repository.
5+
---
6+
name: Sync with Edge Microvisor Repository (next)
7+
on:
8+
schedule:
9+
- cron: '0 * * * *' # Runs every hour
10+
push:
11+
paths:
12+
- '.github/workflows/sync-repo.yml'
13+
workflow_dispatch:
14+
jobs:
15+
sync:
16+
name: Sync Edge Microvisor
17+
runs-on: bdba
18+
steps:
19+
- name: Clean workspace
20+
run: |
21+
rm -rf edge-microvisor-repo bdba-config-repo
22+
23+
- name: Checkout current repository
24+
uses: actions/checkout@v4
25+
with:
26+
path: bdba-config-repo
27+
ref: refs/heads/next
28+
29+
- name: Checkout edge-microvisor repository
30+
uses: actions/checkout@v4
31+
with:
32+
repository: open-edge-platform/edge-microvisor-toolkit
33+
path: edge-microvisor-repo
34+
ref: refs/heads/next
35+
36+
- name: Sync with Edge microvisor
37+
run: |
38+
python3 bdba-config-repo/scripts/run-repo-sync.py --edge-repo-path edge-microvisor-repo --bdba-repo-path bdba-config-repo
39+
40+
- name: Checkout Commit Changes
41+
run: |
42+
cd bdba-config-repo
43+
git config user.name "github-actions[bot]"
44+
git config user.email "github-actions[bot]@users.noreply.github.com"
45+
git branch "sync/pull-request-next"
46+
git checkout "sync/pull-request-next"
47+
git add .
48+
git status
49+
git commit -m "Sync SPECS with edge-microvisor-toolkit (next branch) repo"
50+
git log -2
51+
git push origin "sync/pull-request-next" --force
52+
53+
- name: Check PR for sync/pull-request-next exists
54+
id: check_branch
55+
uses: actions/github-script@v7
56+
with:
57+
script: |
58+
const branchName = 'sync/pull-request-next';
59+
const { repo, owner } = context.repo;
60+
61+
// Check if there is already an open pull request from this branch
62+
const { data: pullRequests } = await github.rest.pulls.list({
63+
owner,
64+
repo,
65+
state: 'open',
66+
head: `${owner}:${branchName}`,
67+
});
68+
69+
if (pullRequests.length > 0) {
70+
// A PR already exists for this branch
71+
return 'exists';
72+
}
73+
74+
// No PR exists for this branch yet
75+
return 'missing';
76+
result-encoding: string
77+
78+
- name: Create New Pull Requests
79+
id: create_pr
80+
uses: actions/github-script@v7
81+
if: ${{ steps.check_branch.outputs.result == 'missing' }}
82+
with:
83+
script: |
84+
const { repo, owner } = context.repo;
85+
const { data: pullRequest } = await github.rest.pulls.create({
86+
owner,
87+
repo,
88+
title: 'Sync SPECS with edge-microvisor-toolkit (next branch) repo',
89+
head: 'sync/pull-request-next',
90+
base: 'next',
91+
body: ['This PR synchronizes the current SPECS from the edge-microvisor-toolkit repository.',
92+
'Please review the changes and merge if everything looks good.'].join('\n'),
93+
draft: true,
94+
});
95+
console.log(`Pull request created: ${pullRequest.html_url}`);
96+
return pullRequest.number;
97+
result-encoding: string
98+
99+
- name: Bot Auto Reviewer
100+
uses: actions/github-script@v7
101+
if: ${{ steps.check_branch.outputs.result == 'missing' }}
102+
with:
103+
script: |
104+
try {
105+
await github.rest.pulls.requestReviewers({
106+
owner: context.repo.owner,
107+
repo: context.repo.repo,
108+
pull_number: ${{ steps.create_pr.outputs.result }},
109+
reviewers: ['aaroncyew', 'jinghuitham', 'JiayongT'],
110+
});
111+
console.log('Reviewers added successfully');
112+
} catch (error) {
113+
core.setFailed(`Failed to add reviewers: ${error.message}`);
114+
}
115+
116+
- name: Bot Auto Labels
117+
uses: actions/github-script@v7
118+
if: ${{ steps.check_branch.outputs.result == 'missing' }}
119+
with:
120+
script: |
121+
github.rest.issues.addLabels({
122+
owner: context.repo.owner,
123+
repo: context.repo.repo,
124+
issue_number: ${{ steps.create_pr.outputs.result }},
125+
labels: ['needs-review'],
126+
});

scripts/check-bdba-yaml.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/python
2+
3+
import os
4+
import sys
5+
from yaml import load, Loader
6+
import logging
7+
8+
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG, force=True)
9+
10+
edge_specs = os.environ.get('EDGE_MT_SPECS', '')
11+
check_pass = ' PASS'
12+
check_fail = 'FAIL'
13+
check_warn = ' WARN'
14+
15+
if edge_specs == '':
16+
logging.error("EDGE_MT_SPECS environment variable is not set.")
17+
sys.exit(1)
18+
else:
19+
for spec in edge_specs.split(' '):
20+
if os.path.isfile(spec):
21+
spec_name = spec.split('/')[1]
22+
bdba_yaml = spec.split('/')[-1]
23+
bdba_yaml_ext = bdba_yaml.split('.')[-1]
24+
25+
# Check file extension
26+
if bdba_yaml_ext != 'yaml':
27+
logging.error(f"{check_fail}: File extension check for {spec_name}.")
28+
logging.error(f"{check_fail}: Expected '.yaml' extension but found '.{bdba_yaml_ext}'.")
29+
sys.exit(1)
30+
else:
31+
logging.info(f"{check_pass}: File extension check for {spec_name}.")
32+
33+
# Check specVersion in YAML content
34+
stream = open(spec, 'r')
35+
bdba_data = load(stream, Loader=Loader)
36+
if bdba_data is None:
37+
logging.warning(f"{check_warn}: Content is empty for {spec_name}.")
38+
else:
39+
if 'specVersion' in bdba_data:
40+
logging.info(f"{check_pass}: specVersion check for {spec_name}.")
41+
42+
if bdba_data['specVersion'] == 3:
43+
logging.info(f"{check_pass}: specVersion is '3' for {spec_name}.")
44+
else:
45+
logging.error(f"{check_fail}: specVersion is '{bdba_data['specVersion']}' for {spec_name}, expected '3'.")
46+
else:
47+
logging.error(f"{check_fail}: specVersion check for {spec_name}.")
48+

0 commit comments

Comments
 (0)