Skip to content

Commit 1ddc86f

Browse files
Copilotdiberry
andcommitted
Add workflow validation system with actionlint and action version checking
Co-authored-by: diberry <[email protected]>
1 parent 21a31c3 commit 1ddc86f

File tree

4 files changed

+343
-0
lines changed

4 files changed

+343
-0
lines changed

.github/workflows/README.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# GitHub Actions Workflows
2+
3+
This directory contains GitHub Actions workflows for the Azure TypeScript LangChainJS repository.
4+
5+
## Available Workflows
6+
7+
### 1. Validate Workflows (`validate-workflows.yml`)
8+
9+
This workflow automatically validates all GitHub Actions workflows in the repository to ensure they are properly configured and using up-to-date actions.
10+
11+
**Features:**
12+
- **Syntax Validation**: Uses `actionlint` to validate workflow YAML syntax and check for common issues
13+
- **Action Availability Check**: Verifies that all referenced GitHub Actions are still available
14+
- **Version Tracking**: Lists all actions and their versions in use
15+
- **Automated Reports**: Generates a detailed report of all actions and their status
16+
17+
**When it runs:**
18+
- On push/pull request when workflow files are modified
19+
- Weekly on Mondays at 9:00 AM UTC (scheduled check for outdated actions)
20+
- Manually via workflow dispatch
21+
22+
**Jobs:**
23+
1. **validate-workflows**: Runs actionlint to check syntax and best practices
24+
2. **check-action-versions**: Uses action-validator to check for outdated versions
25+
3. **detect-outdated-actions**: Extracts and analyzes all actions used in workflows
26+
4. **summary**: Provides a consolidated summary of all validation jobs
27+
28+
**Outputs:**
29+
- A downloadable report artifact containing all actions and versions in use
30+
- GitHub step summary with validation results
31+
32+
### 2. CI (`ci.yml`)
33+
34+
Continuous integration workflow that builds and tests the project.
35+
36+
**When it runs:**
37+
- On push to the `main` branch
38+
- On pull requests to the `main` branch
39+
- Manually via workflow dispatch
40+
41+
**Jobs:**
42+
1. **build**: Installs dependencies and builds the project
43+
44+
## Validation Tools
45+
46+
### actionlint
47+
A static checker for GitHub Actions workflow files. It catches common mistakes and enforces best practices.
48+
49+
**Installation:**
50+
```bash
51+
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
52+
```
53+
54+
**Usage:**
55+
```bash
56+
actionlint .github/workflows/*.yml
57+
```
58+
59+
### action-validator
60+
Checks for outdated GitHub Actions versions.
61+
62+
**Installation:**
63+
```bash
64+
npm install -g action-validator
65+
```
66+
67+
**Usage:**
68+
```bash
69+
action-validator .github/workflows/your-workflow.yml
70+
```
71+
72+
## Best Practices
73+
74+
1. **Pin Actions to Specific Versions**: Always use specific commit SHAs or version tags (e.g., `actions/checkout@v4`) instead of branches
75+
2. **Keep Actions Updated**: Regularly review and update actions to their latest versions
76+
3. **Test Workflow Changes**: Use workflow dispatch or create test branches to validate changes before merging
77+
4. **Review Weekly Reports**: Check the scheduled validation runs to identify outdated actions
78+
79+
## Adding New Workflows
80+
81+
When adding new workflows:
82+
83+
1. Create your workflow file in `.github/workflows/`
84+
2. Ensure it passes `actionlint` validation locally:
85+
```bash
86+
actionlint .github/workflows/your-new-workflow.yml
87+
```
88+
3. Commit and push - the validate-workflows workflow will automatically check your new file
89+
4. Review the validation results in the GitHub Actions tab
90+
91+
## Troubleshooting
92+
93+
### Workflow Validation Failures
94+
95+
If the validate-workflows workflow fails:
96+
97+
1. Check the job logs for specific error messages
98+
2. Run `actionlint` locally to get detailed error information
99+
3. Fix the issues and push the changes
100+
4. The validation will run automatically on your next push
101+
102+
### Common Issues
103+
104+
- **Syntax Errors**: Check YAML indentation and syntax
105+
- **Deprecated Actions**: Update to the latest version of the action
106+
- **Unknown Actions**: Verify the action name and that the repository is public
107+
- **Shell Script Issues**: Ensure proper quoting and use of variables in shell scripts
108+
109+
## Security Considerations
110+
111+
- Only use actions from trusted sources (verified creators or well-known organizations)
112+
- Pin actions to specific commit SHAs for maximum security
113+
- Review action source code before using new actions
114+
- Keep actions updated to receive security patches
115+
116+
## Resources
117+
118+
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
119+
- [actionlint Repository](https://github.com/rhysd/actionlint)
120+
- [GitHub Actions Security Best Practices](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
workflow_dispatch:
9+
10+
jobs:
11+
build:
12+
name: Build and Test
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Node.js
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: '20'
23+
cache: 'npm'
24+
25+
- name: Install dependencies
26+
run: npm ci
27+
28+
- name: Build project
29+
run: npm run build
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
name: Validate GitHub Actions Workflows
2+
3+
on:
4+
push:
5+
paths:
6+
- '.github/workflows/**'
7+
pull_request:
8+
paths:
9+
- '.github/workflows/**'
10+
workflow_dispatch:
11+
schedule:
12+
# Run weekly on Monday at 9:00 AM UTC to check for outdated actions
13+
- cron: '0 9 * * 1'
14+
15+
jobs:
16+
validate-workflows:
17+
name: Validate Workflow Files
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Install actionlint
25+
run: |
26+
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
27+
sudo mv ./actionlint /usr/local/bin/
28+
actionlint --version
29+
30+
- name: Run actionlint
31+
run: |
32+
echo "Running actionlint to validate workflow syntax and best practices..."
33+
actionlint -color
34+
continue-on-error: false
35+
36+
check-action-versions:
37+
name: Check Action Versions
38+
runs-on: ubuntu-latest
39+
40+
steps:
41+
- name: Checkout repository
42+
uses: actions/checkout@v4
43+
44+
- name: Setup Node.js
45+
uses: actions/setup-node@v4
46+
with:
47+
node-version: '20'
48+
49+
- name: Install action-validator
50+
run: npm install -g action-validator
51+
52+
- name: Validate action versions
53+
run: |
54+
echo "Checking for outdated GitHub Actions..."
55+
# Find all workflow files and check each one
56+
for workflow in .github/workflows/*.yml .github/workflows/*.yaml; do
57+
if [ -f "$workflow" ]; then
58+
echo "Checking $workflow..."
59+
action-validator "$workflow" || true
60+
fi
61+
done
62+
continue-on-error: true
63+
64+
detect-outdated-actions:
65+
name: Detect Outdated Actions
66+
runs-on: ubuntu-latest
67+
68+
steps:
69+
- name: Checkout repository
70+
uses: actions/checkout@v4
71+
72+
- name: Extract actions from workflows
73+
id: extract-actions
74+
run: |
75+
echo "Extracting actions from workflow files..."
76+
mkdir -p /tmp/workflow-analysis
77+
78+
# Extract all 'uses:' lines from workflow files
79+
find .github/workflows -name "*.yml" -o -name "*.yaml" | while IFS= read -r workflow; do
80+
echo "Analyzing $workflow"
81+
grep -E "^\s*uses:" "$workflow" | sed 's/.*uses:\s*//' | sed 's/#.*//' | sed 's/\s*$//' >> /tmp/workflow-analysis/actions.txt || true
82+
done
83+
84+
# Remove duplicates and sort
85+
if [ -f /tmp/workflow-analysis/actions.txt ]; then
86+
sort -u /tmp/workflow-analysis/actions.txt > /tmp/workflow-analysis/unique_actions.txt
87+
echo "Found actions:"
88+
cat /tmp/workflow-analysis/unique_actions.txt
89+
90+
# Count actions
91+
ACTION_COUNT=$(wc -l < /tmp/workflow-analysis/unique_actions.txt)
92+
echo "Total unique actions: $ACTION_COUNT"
93+
else
94+
echo "No actions found in workflows"
95+
fi
96+
97+
- name: Check action availability
98+
run: |
99+
echo "Checking if actions are available on GitHub..."
100+
101+
if [ ! -f /tmp/workflow-analysis/unique_actions.txt ]; then
102+
echo "No actions to check"
103+
exit 0
104+
fi
105+
106+
while IFS= read -r action; do
107+
# Skip local actions (starting with ./)
108+
if [[ "$action" == ./* ]]; then
109+
echo "✓ Local action: $action (skipped)"
110+
continue
111+
fi
112+
113+
# Extract owner/repo and version
114+
ACTION_PATH=$(echo "$action" | cut -d'@' -f1)
115+
ACTION_VERSION=$(echo "$action" | cut -d'@' -f2)
116+
117+
# Check if action exists
118+
if [[ "$ACTION_PATH" == *"/"* ]]; then
119+
REPO_URL="https://github.com/$ACTION_PATH"
120+
echo "Checking $ACTION_PATH@$ACTION_VERSION..."
121+
122+
# Use GitHub API to check if repo exists (no auth needed for public repos)
123+
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$REPO_URL")
124+
125+
if [ "$HTTP_CODE" -eq 200 ]; then
126+
echo "✓ Action available: $action"
127+
else
128+
echo "✗ Action not found or inaccessible: $action (HTTP $HTTP_CODE)"
129+
fi
130+
fi
131+
done < /tmp/workflow-analysis/unique_actions.txt
132+
133+
- name: Generate action version report
134+
run: |
135+
{
136+
echo "## Action Version Report"
137+
echo ""
138+
echo "This report lists all GitHub Actions used in workflows:"
139+
echo ""
140+
} > /tmp/workflow-analysis/report.md
141+
142+
if [ -f /tmp/workflow-analysis/unique_actions.txt ]; then
143+
{
144+
echo "| Action | Version | Status |"
145+
echo "|--------|---------|--------|"
146+
} >> /tmp/workflow-analysis/report.md
147+
148+
while IFS= read -r action; do
149+
ACTION_PATH=$(echo "$action" | cut -d'@' -f1)
150+
ACTION_VERSION=$(echo "$action" | cut -d'@' -f2)
151+
echo "| \`$ACTION_PATH\` | \`$ACTION_VERSION\` | ✓ In use |" >> /tmp/workflow-analysis/report.md
152+
done < /tmp/workflow-analysis/unique_actions.txt
153+
else
154+
echo "No actions found in workflows." >> /tmp/workflow-analysis/report.md
155+
fi
156+
157+
{
158+
echo ""
159+
echo "---"
160+
echo "Generated on: $(date -u)"
161+
} >> /tmp/workflow-analysis/report.md
162+
163+
cat /tmp/workflow-analysis/report.md
164+
165+
- name: Upload report
166+
uses: actions/upload-artifact@v4
167+
if: always()
168+
with:
169+
name: workflow-validation-report
170+
path: /tmp/workflow-analysis/report.md
171+
retention-days: 30
172+
173+
summary:
174+
name: Validation Summary
175+
runs-on: ubuntu-latest
176+
needs: [validate-workflows, check-action-versions, detect-outdated-actions]
177+
if: always()
178+
179+
steps:
180+
- name: Create summary
181+
run: |
182+
{
183+
echo "# Workflow Validation Summary"
184+
echo ""
185+
echo "✅ All workflow validation jobs completed"
186+
echo ""
187+
echo "## Jobs Status:"
188+
echo "- Validate Workflows: ${{ needs.validate-workflows.result }}"
189+
echo "- Check Action Versions: ${{ needs.check-action-versions.result }}"
190+
echo "- Detect Outdated Actions: ${{ needs.detect-outdated-actions.result }}"
191+
} >> "$GITHUB_STEP_SUMMARY"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,6 @@ build/
146146
# Bicep compiled ARM templates
147147
infra/**/*.json
148148
!infra/**/*.parameters.json
149+
150+
# actionlint binary (downloaded for local testing)
151+
actionlint

0 commit comments

Comments
 (0)