-
Notifications
You must be signed in to change notification settings - Fork 195
Auto-update ms.date in docs-mslearn on PR changes #1985
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
Merged
+310
β0
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| name: Update ms.date in docs-mslearn | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'docs-mslearn/**/*.md' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| update-dates: | ||
| name: Update ms.date in changed markdown files | ||
| runs-on: ubuntu-latest | ||
| # Only run on PRs from the same repo (not forks) to allow pushing | ||
| if: github.event.pull_request.head.repo.full_name == github.repository | ||
| steps: | ||
| - name: Checkout PR branch | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.head_ref }} | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Get changed markdown files | ||
| id: changed-files | ||
| uses: tj-actions/changed-files@v44 | ||
| with: | ||
| files: 'docs-mslearn/**/*.md' | ||
|
|
||
| - name: Update ms.date in changed files | ||
| if: steps.changed-files.outputs.any_changed == 'true' | ||
| run: | | ||
| # Get current date in MM/DD/YYYY format | ||
| CURRENT_DATE=$(date +'%m/%d/%Y') | ||
| echo "Updating ms.date to: $CURRENT_DATE" | ||
|
|
||
| # Process each changed markdown file | ||
| for file in ${{ steps.changed-files.outputs.all_changed_files }}; do | ||
| echo "Processing: $file" | ||
|
|
||
| # Check if file has ms.date in frontmatter and update it | ||
| if grep -q "^ms\.date:" "$file"; then | ||
| # Use sed to replace the ms.date line | ||
| sed -i "s/^ms\.date:.*$/ms.date: $CURRENT_DATE/" "$file" | ||
| echo " Updated ms.date in $file" | ||
| else | ||
| echo " No ms.date found in $file, skipping" | ||
| fi | ||
| done | ||
|
|
||
| - name: Check for changes | ||
| id: check-changes | ||
| run: | | ||
| if git diff --quiet; then | ||
| echo "has_changes=false" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "has_changes=true" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Commit and push changes | ||
| if: steps.check-changes.outputs.has_changes == 'true' | ||
| run: | | ||
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | ||
| git config --local user.name "github-actions[bot]" | ||
| git add -u docs-mslearn/ | ||
| git commit -m "chore: Update ms.date in docs-mslearn files" | ||
| git push | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| BeforeDiscovery { | ||
| $docsPath = Join-Path (Get-Item -Path $PSScriptRoot).Parent.Parent.Parent.Parent.FullName 'docs-mslearn' | ||
| $markdownFiles = Get-ChildItem -Path $docsPath -Recurse -Filter '*.md' -File | ||
| } | ||
|
|
||
| Describe 'Microsoft Learn docs - [<_.Name>]' -ForEach $markdownFiles { | ||
| BeforeAll { | ||
| $file = $_ | ||
| $content = Get-Content -Path $file.FullName -Raw | ||
|
|
||
| # Extract frontmatter (content between first pair of ---) | ||
| $frontmatterMatch = [regex]::Match($content, '^---\r?\n([\s\S]*?)\r?\n---') | ||
| $hasFrontmatter = $frontmatterMatch.Success | ||
| $frontmatter = if ($hasFrontmatter) { $frontmatterMatch.Groups[1].Value } else { '' } | ||
|
|
||
| # Extract ms.date value | ||
| $msDateMatch = [regex]::Match($frontmatter, '^ms\.date:\s*(.+)$', [System.Text.RegularExpressions.RegexOptions]::Multiline) | ||
| $hasMsDate = $msDateMatch.Success | ||
| $msDateValue = if ($hasMsDate) { $msDateMatch.Groups[1].Value.Trim() } else { '' } | ||
|
|
||
| # Helper function to parse date | ||
| function Test-MsDateValid { | ||
| param([string]$DateString) | ||
| try { | ||
| $null = [datetime]::ParseExact($DateString, 'MM/dd/yyyy', [System.Globalization.CultureInfo]::InvariantCulture) | ||
| return $true | ||
| } catch { | ||
| return $false | ||
| } | ||
| } | ||
|
|
||
| function Get-MsDateParsed { | ||
| param([string]$DateString) | ||
| try { | ||
| return [datetime]::ParseExact($DateString, 'MM/dd/yyyy', [System.Globalization.CultureInfo]::InvariantCulture) | ||
| } catch { | ||
| return $null | ||
| } | ||
| } | ||
| } | ||
|
|
||
| It 'Should have YAML frontmatter' { | ||
| $hasFrontmatter | Should -BeTrue -Because "Microsoft Learn docs require YAML frontmatter" | ||
| } | ||
|
|
||
| It 'Should have ms.date field' { | ||
| $hasMsDate | Should -BeTrue -Because "Microsoft Learn docs require an ms.date field in frontmatter" | ||
| } | ||
|
|
||
| It 'Should have ms.date in MM/DD/YYYY format' { | ||
| if (-not $hasMsDate) { | ||
| Set-ItResult -Skipped -Because "ms.date field is missing" | ||
| return | ||
| } | ||
|
|
||
| # Validate format: MM/DD/YYYY | ||
| $msDateValue | Should -Match '^\d{2}/\d{2}/\d{4}$' -Because "ms.date must be in MM/DD/YYYY format (found: $msDateValue)" | ||
| } | ||
|
|
||
| It 'Should have a valid ms.date value' { | ||
| if (-not $hasMsDate) { | ||
| Set-ItResult -Skipped -Because "ms.date field is missing" | ||
| return | ||
| } | ||
|
|
||
| # Try to parse the date | ||
| $isValidDate = Test-MsDateValid -DateString $msDateValue | ||
| $isValidDate | Should -BeTrue -Because "ms.date must be a valid date (found: $msDateValue)" | ||
| } | ||
|
|
||
| It 'Should not have ms.date in the future' { | ||
| if (-not $hasMsDate) { | ||
| Set-ItResult -Skipped -Because "ms.date field is missing" | ||
| return | ||
| } | ||
|
|
||
| $parsedDate = Get-MsDateParsed -DateString $msDateValue | ||
| if (-not $parsedDate) { | ||
| Set-ItResult -Skipped -Because "ms.date is not a valid date" | ||
| return | ||
| } | ||
|
|
||
| $parsedDate | Should -BeLessOrEqual (Get-Date) -Because "ms.date should not be in the future" | ||
| } | ||
|
|
||
| It 'Should have ms.date within reasonable range (after 2020)' { | ||
| if (-not $hasMsDate) { | ||
| Set-ItResult -Skipped -Because "ms.date field is missing" | ||
| return | ||
| } | ||
|
|
||
| $parsedDate = Get-MsDateParsed -DateString $msDateValue | ||
| if (-not $parsedDate) { | ||
| Set-ItResult -Skipped -Because "ms.date is not a valid date" | ||
| return | ||
| } | ||
|
|
||
| $minDate = [datetime]::new(2020, 1, 1) | ||
| $parsedDate | Should -BeGreaterOrEqual $minDate -Because "ms.date seems too old (FinOps toolkit started in 2020)" | ||
| } | ||
| } |
130 changes: 130 additions & 0 deletions
130
src/powershell/Tests/Unit/Action.UpdateMsLearnDates.Tests.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| Describe 'update-mslearn-dates GitHub Action' { | ||
| BeforeAll { | ||
| $workflowPath = Join-Path (Get-Item -Path $PSScriptRoot).Parent.Parent.Parent.Parent.FullName '.github/workflows/update-mslearn-dates.yml' | ||
| $workflowContent = Get-Content -Path $workflowPath -Raw | ||
| } | ||
|
|
||
| Context 'Workflow file structure' { | ||
| It 'Should exist' { | ||
| Test-Path $workflowPath | Should -BeTrue | ||
| } | ||
|
|
||
| It 'Should have a name' { | ||
| $workflowContent | Should -Match '^name:\s*.+' | ||
| } | ||
| } | ||
|
|
||
| Context 'Trigger configuration' { | ||
| It 'Should trigger on pull_request' { | ||
| $workflowContent | Should -Match 'on:\s*\r?\n\s+pull_request:' | ||
| } | ||
|
|
||
| It 'Should only trigger for docs-mslearn markdown files' { | ||
| $workflowContent | Should -Match "paths:\s*\r?\n\s+- 'docs-mslearn/\*\*/\*\.md'" | ||
| } | ||
|
|
||
| It 'Should not trigger on push events' { | ||
| # Ensure there's no 'push:' trigger at the top level | ||
| $workflowContent | Should -Not -Match 'on:\s*\r?\n\s+push:' | ||
| } | ||
| } | ||
|
|
||
| Context 'Permissions' { | ||
| It 'Should have contents write permission' { | ||
| $workflowContent | Should -Match 'contents:\s*write' | ||
| } | ||
|
|
||
| It 'Should have pull-requests write permission' { | ||
| $workflowContent | Should -Match 'pull-requests:\s*write' | ||
| } | ||
| } | ||
|
|
||
| Context 'Job configuration' { | ||
| It 'Should have update-dates job' { | ||
| $workflowContent | Should -Match 'jobs:\s*\r?\n\s+update-dates:' | ||
| } | ||
|
|
||
| It 'Should run on ubuntu-latest' { | ||
| $workflowContent | Should -Match 'runs-on:\s*ubuntu-latest' | ||
| } | ||
|
|
||
| It 'Should have fork protection condition' { | ||
| $workflowContent | Should -Match 'if:\s*github\.event\.pull_request\.head\.repo\.full_name\s*==\s*github\.repository' | ||
| } | ||
| } | ||
|
|
||
| Context 'Workflow steps' { | ||
| It 'Should checkout the PR branch' { | ||
| $workflowContent | Should -Match 'uses:\s*actions/checkout@v\d+' | ||
| $workflowContent | Should -Match 'ref:\s*\$\{\{\s*github\.head_ref\s*\}\}' | ||
| } | ||
|
|
||
| It 'Should use changed-files action' { | ||
| $workflowContent | Should -Match 'uses:\s*tj-actions/changed-files@v\d+' | ||
| } | ||
|
|
||
| It 'Should filter changed-files to docs-mslearn markdown' { | ||
| $workflowContent | Should -Match "files:\s*'docs-mslearn/\*\*/\*\.md'" | ||
| } | ||
|
|
||
| It 'Should have step to update ms.date' { | ||
| $workflowContent | Should -Match 'name:\s*Update ms\.date' | ||
| } | ||
|
|
||
| It 'Should use correct date format (MM/DD/YYYY)' { | ||
| $workflowContent | Should -Match "date \+'%m/%d/%Y'" | ||
| } | ||
|
|
||
| It 'Should use sed to replace ms.date line' { | ||
| $workflowContent | Should -Match 'sed -i' | ||
| $workflowContent | Should -Match 's/\^ms\\\.date:' | ||
| } | ||
|
|
||
| It 'Should have step to check for changes before committing' { | ||
| $workflowContent | Should -Match 'name:\s*Check for changes' | ||
| $workflowContent | Should -Match 'git diff --quiet' | ||
| } | ||
|
|
||
| It 'Should have step to commit and push' { | ||
| $workflowContent | Should -Match 'name:\s*Commit and push' | ||
| } | ||
|
|
||
| It 'Should only commit when there are changes' { | ||
| $workflowContent | Should -Match "if:\s*steps\.check-changes\.outputs\.has_changes\s*==\s*'true'" | ||
| } | ||
|
|
||
| It 'Should use github-actions bot for commits' { | ||
| $workflowContent | Should -Match 'github-actions\[bot\]@users\.noreply\.github\.com' | ||
| $workflowContent | Should -Match 'user\.name.*github-actions\[bot\]' | ||
| } | ||
|
|
||
| It 'Should use conventional commit format' { | ||
| $workflowContent | Should -Match 'git commit -m.*chore:' | ||
| } | ||
| } | ||
|
|
||
| Context 'Sed command validation' { | ||
| It 'Should have correct sed regex to match ms.date at line start' { | ||
| # The sed command should use ^ to anchor to start of line | ||
| $workflowContent | Should -Match 's/\^ms\\\.date:\.\*\$/ms\.date:' | ||
| } | ||
|
|
||
| It 'Should replace entire ms.date line' { | ||
| # Pattern should end with .* to match rest of line | ||
| $workflowContent | Should -Match 'ms\\\.date:\.\*\$' | ||
| } | ||
| } | ||
|
|
||
| Context 'Security considerations' { | ||
| It 'Should use GITHUB_TOKEN for checkout' { | ||
| $workflowContent | Should -Match 'token:\s*\$\{\{\s*secrets\.GITHUB_TOKEN\s*\}\}' | ||
| } | ||
|
|
||
| It 'Should only add docs-mslearn files to commit' { | ||
| $workflowContent | Should -Match 'git add docs-mslearn/' | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.