Skip to content

Commit 82338d3

Browse files
chore: New GitHub Actions workflows to automate code quality checks, testing, and repository maintenance
2 parents cb062a9 + b35a3e9 commit 82338d3

22 files changed

Lines changed: 1392 additions & 708 deletions

.flake8

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[flake8]
2+
max-line-length = 88
3+
extend-ignore = E501
4+
exclude = .venv, frontend
5+
ignore = E203, W503, G004, G200
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Broken Link Checker
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '**/*.md'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
actions: read
12+
13+
jobs:
14+
markdown-link-check:
15+
name: Check Markdown Broken Links
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout Repo
20+
uses: actions/checkout@v6
21+
with:
22+
fetch-depth: 0
23+
24+
# For PR : Get only changed markdown files
25+
- name: Get changed markdown files (PR only)
26+
id: changed-markdown-files
27+
if: github.event_name == 'pull_request'
28+
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v46
29+
with:
30+
files: |
31+
**/*.md
32+
33+
34+
# For PR: Check broken links only in changed files
35+
- name: Check Broken Links in Changed Markdown Files
36+
id: lychee-check-pr
37+
if: github.event_name == 'pull_request' && steps.changed-markdown-files.outputs.any_changed == 'true'
38+
uses: lycheeverse/lychee-action@v2.7.0
39+
with:
40+
args: >
41+
--verbose --no-progress --exclude ^https?://
42+
${{ steps.changed-markdown-files.outputs.all_changed_files }}
43+
failIfEmpty: false
44+
env:
45+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
47+
# For manual trigger: Check all markdown files in repo
48+
- name: Check Broken Links in All Markdown Files in Entire Repo (Manual Trigger)
49+
id: lychee-check-manual
50+
if: github.event_name == 'workflow_dispatch'
51+
uses: lycheeverse/lychee-action@v2.7.0
52+
with:
53+
args: >
54+
--verbose --no-progress --exclude ^https?://
55+
'**/*.md'
56+
failIfEmpty: false
57+
env:
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/codeql.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
paths:
7+
- '**/*.py'
8+
- '.github/workflows/codeql.yml'
9+
pull_request:
10+
branches: [ "main" ]
11+
paths:
12+
- '**/*.py'
13+
- '.github/workflows/codeql.yml'
14+
schedule:
15+
- cron: '17 11 * * 0'
16+
17+
jobs:
18+
analyze:
19+
name: Analyze
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 360
22+
permissions:
23+
actions: read
24+
contents: read
25+
security-events: write
26+
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
language: [ 'python' ]
31+
32+
steps:
33+
- name: Checkout repository
34+
uses: actions/checkout@v6
35+
36+
- name: Initialize CodeQL
37+
uses: github/codeql-action/init@v4
38+
with:
39+
languages: ${{ matrix.language }}
40+
41+
- name: Perform CodeQL Analysis
42+
uses: github/codeql-action/analyze@v4
43+
with:
44+
category: "/language:${{matrix.language}}"

.github/workflows/pylint.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: PyLint
2+
3+
on:
4+
push:
5+
paths:
6+
- 'content-gen/src/backend/**/*.py'
7+
- 'content-gen/src/backend/requirements*.txt'
8+
- '.flake8'
9+
- '.github/workflows/pylint.yml'
10+
11+
permissions:
12+
contents: read
13+
actions: read
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-latest
18+
strategy:
19+
matrix:
20+
python-version: ["3.11"]
21+
steps:
22+
- uses: actions/checkout@v6
23+
24+
- name: Set up Python ${{ matrix.python-version }}
25+
uses: actions/setup-python@v6
26+
with:
27+
python-version: ${{ matrix.python-version }}
28+
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install -r content-gen/src/backend/requirements.txt
33+
pip install flake8 # Ensure flake8 is installed explicitly
34+
35+
- name: Run flake8
36+
run: |
37+
flake8 --config=.flake8 content-gen/src/backend # Specify the directory to lint

.github/workflows/stale-bot.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: "Manage Stale Issues, PRs & Unmerged Branches"
2+
on:
3+
schedule:
4+
- cron: '30 1 * * *' # Runs daily at 1:30 AM UTC
5+
workflow_dispatch: # Allows manual triggering
6+
permissions:
7+
contents: write
8+
issues: write
9+
pull-requests: write
10+
jobs:
11+
stale:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Mark Stale Issues and PRs
15+
uses: actions/stale@v10
16+
with:
17+
stale-issue-message: "This issue is stale because it has been open 180 days with no activity. Remove stale label or comment, or it will be closed in 30 days."
18+
stale-pr-message: "This PR is stale because it has been open 180 days with no activity. Please update or it will be closed in 30 days."
19+
days-before-stale: 180
20+
days-before-close: 30
21+
exempt-issue-labels: "keep"
22+
exempt-pr-labels: "keep"
23+
cleanup-branches:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout Repository
27+
uses: actions/checkout@v6
28+
with:
29+
fetch-depth: 0 # Fetch full history for accurate branch checks
30+
- name: Fetch All Branches
31+
run: git fetch --all --prune
32+
- name: List Merged Branches With No Activity in Last 3 Months
33+
run: |
34+
echo "Branch Name,Last Commit Date,Committer,Committed In Branch,Action" > merged_branches_report.csv
35+
for branch in $(git for-each-ref --format '%(refname:short) %(committerdate:unix)' refs/remotes/origin | awk -v date=$(date -d '3 months ago' +%s) '$2 < date {print $1}'); do
36+
if [[ "$branch" != "origin/main" && "$branch" != "origin/dev" && "$branch" != "origin/demo" ]]; then
37+
branch_name=${branch#origin/}
38+
git fetch origin "$branch_name" || echo "Could not fetch branch: $branch_name"
39+
last_commit_date=$(git log -1 --format=%ci "origin/$branch_name" || echo "Unknown")
40+
committer_name=$(git log -1 --format=%cn "origin/$branch_name" || echo "Unknown")
41+
committed_in_branch=$(git branch -r --contains "origin/$branch_name" | tr -d ' ' | paste -sd "," -)
42+
echo "$branch_name,$last_commit_date,$committer_name,$committed_in_branch,Delete" >> merged_branches_report.csv
43+
fi
44+
done
45+
- name: List PR Approved and Merged Branches Older Than 30 Days
46+
run: |
47+
for branch in $(gh api repos/${{ github.repository }}/pulls --state closed --paginate --jq '.[] | select(.merged_at != null and (.base.ref == "main" or .base.ref == "dev" or .base.ref == "demo")) | select(.merged_at | fromdateiso8601 < (now - 2592000)) | .head.ref'); do
48+
git fetch origin "$branch" || echo "Could not fetch branch: $branch"
49+
last_commit_date=$(git log -1 --format=%ci origin/$branch || echo "Unknown")
50+
committer_name=$(git log -1 --format=%cn origin/$branch || echo "Unknown")
51+
committed_in_branch=$(git branch -r --contains "origin/$branch" | tr -d ' ' | paste -sd "," -)
52+
echo "$branch,$last_commit_date,$committer_name,$committed_in_branch,Delete" >> merged_branches_report.csv
53+
done
54+
env:
55+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56+
- name: List Open PR Branches With No Activity in Last 3 Months
57+
run: |
58+
for branch in $(gh api repos/${{ github.repository }}/pulls --state open --jq '.[] | select(.base.ref == "main" or .base.ref == "dev" or .base.ref == "demo") | .head.ref'); do
59+
git fetch origin "$branch" || echo "Could not fetch branch: $branch"
60+
last_commit_date=$(git log -1 --format=%ci origin/$branch || echo "Unknown")
61+
committer_name=$(git log -1 --format=%cn origin/$branch || echo "Unknown")
62+
if [[ $(date -d "$last_commit_date" +%s) -lt $(date -d '3 months ago' +%s) ]]; then
63+
committed_in_branch=$(git branch -r --contains "origin/$branch" | tr -d ' ' | paste -sd "," -)
64+
echo "$branch,$last_commit_date,$committer_name,$committed_in_branch,Delete" >> merged_branches_report.csv
65+
fi
66+
done
67+
env:
68+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69+
- name: Upload CSV Report of Inactive Branches
70+
uses: actions/upload-artifact@v6
71+
with:
72+
name: merged-branches-report
73+
path: merged_branches_report.csv
74+
retention-days: 30
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: validate template property for telemetry
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- 'content-gen/azure.yaml'
9+
10+
permissions:
11+
contents: read
12+
actions: read
13+
14+
jobs:
15+
validate-template-property:
16+
name: validate-template-property
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v6
22+
23+
- name: Check for required metadata template line
24+
run: |
25+
if grep -E '^\s*#\s*template:\s*content-generation@' content-gen/azure.yaml; then
26+
echo "ERROR: 'template' line is commented out in content-gen/azure.yaml! Please uncomment template line."
27+
exit 1
28+
fi
29+
30+
if ! grep -E '^\s*template:\s*content-generation@' content-gen/azure.yaml; then
31+
echo "ERROR: Required 'template' line is missing in content-gen/azure.yaml! Please add template line for telemetry."
32+
exit 1
33+
fi
34+
echo "template line is present and not commented."

.github/workflows/test.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Test Workflow with Coverage
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
paths:
9+
- '**/*.py'
10+
- 'content-gen/src/backend/requirements*.txt'
11+
- '.github/workflows/test.yml'
12+
pull_request:
13+
types:
14+
- opened
15+
- ready_for_review
16+
- reopened
17+
- synchronize
18+
branches:
19+
- main
20+
- dev
21+
paths:
22+
- '**/*.py'
23+
- 'content-gen/src/backend/requirements*.txt'
24+
- '.github/workflows/test.yml'
25+
26+
permissions:
27+
contents: read
28+
actions: read
29+
30+
jobs:
31+
backend_tests:
32+
runs-on: ubuntu-latest
33+
34+
steps:
35+
- name: Checkout code
36+
uses: actions/checkout@v6
37+
38+
- name: Set up Python
39+
uses: actions/setup-python@v6
40+
with:
41+
python-version: "3.11"
42+
43+
- name: Install Backend Dependencies
44+
run: |
45+
python -m pip install --upgrade pip
46+
pip install -r content-gen/src/backend/requirements.txt
47+
pip install pytest-cov
48+
pip install pytest-asyncio
49+
50+
- name: Check if Backend Test Files Exist
51+
id: check_backend_tests
52+
run: |
53+
if [ -z "$(find content-gen/src/tests -type f -name 'test_*.py' 2>/dev/null)" ]; then
54+
echo "No backend test files found, skipping backend tests."
55+
echo "skip_backend_tests=true" >> $GITHUB_ENV
56+
else
57+
echo "Backend test files found, running tests."
58+
echo "skip_backend_tests=false" >> $GITHUB_ENV
59+
fi
60+
61+
- name: Run Backend Tests with Coverage
62+
if: env.skip_backend_tests == 'false'
63+
run: |
64+
pytest --cov=. --cov-report=term-missing --cov-report=xml ./content-gen/src/tests
65+
66+
- name: Skip Backend Tests
67+
if: env.skip_backend_tests == 'true'
68+
run: |
69+
echo "Skipping backend tests because no test files were found."

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ Follow the quick deploy steps on the deployment guide to deploy this solution to
7878
<br/>
7979

8080
> ⚠️ **Important: Check Azure OpenAI Quota Availability**
81-
<br/>To ensure sufficient quota is available in your subscription, please follow [quota check instructions guide](./docs/QuotaCheck.md) before you deploy the solution.
81+
<br/>To ensure sufficient quota is available in your subscription, please follow [quota check instructions guide](./content-gen/docs/QuotaCheck.md) before you deploy the solution.
8282
8383
<br/>
8484

8585
### Prerequisites and costs
8686

87-
To deploy this solution accelerator, ensure you have access to an [Azure subscription](https://azure.microsoft.com/free/) with the necessary permissions to create **resource groups, resources, app registrations, and assign roles at the resource group level**. This should include Contributor role at the subscription level and Role Based Access Control role on the subscription and/or resource group level. Follow the steps in [Azure Account Set Up](./docs/AzureAccountSetUp.md).
87+
To deploy this solution accelerator, ensure you have access to an [Azure subscription](https://azure.microsoft.com/free/) with the necessary permissions to create **resource groups, resources, app registrations, and assign roles at the resource group level**. This should include Contributor role at the subscription level and Role Based Access Control role on the subscription and/or resource group level. Follow the steps in [Azure Account Set Up](./content-gen/docs/AzureAccountSetUp.md).
8888

8989
Check the [Azure Products by Region](https://azure.microsoft.com/en-us/explore/global-infrastructure/products-by-region/?products=all&regions=all) page and select a **region** where the following services are available.
9090

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## Azure account setup
2+
3+
1. Sign up for a [free Azure account](https://azure.microsoft.com/free/) and create an Azure Subscription.
4+
2. Check that you have the necessary permissions:
5+
* Your Azure account must have `Microsoft.Authorization/roleAssignments/write` permissions, such as [Role Based Access Control Administrator](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#role-based-access-control-administrator-preview), [User Access Administrator](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#user-access-administrator), or [Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#owner).
6+
* Your Azure account also needs `Microsoft.Resources/deployments/write` permissions on the subscription level.
7+
8+
You can view the permissions for your account and subscription by following the steps below:
9+
- Navigate to the [Azure Portal](https://portal.azure.com/) and click on `Subscriptions` under 'Navigation'
10+
- Select the subscription you are using for this accelerator from the list.
11+
- If you try to search for your subscription and it does not come up, make sure no filters are selected.
12+
- Select `Access control (IAM)` and you can see the roles that are assigned to your account for this subscription.
13+
- If you want to see more information about the roles, you can go to the `Role assignments`
14+
tab and search by your account name and then click the role you want to view more information about.

0 commit comments

Comments
 (0)