Update API Capability Map #2
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
| name: Update API Capability Map | |
| # Keeps Data/PfbCapabilityMap.json (and, when an SSOT API key is configured, | |
| # Data/PfbVersionMap.json) in sync with newly-published FlashBlade REST API versions. | |
| # See tools/lib/PfbSpecTools.ps1 for how the manifest is derived, and tools/README.md | |
| # for the overall pipeline this feeds into. | |
| # | |
| # Note: tools/specs/ (the raw cached OpenAPI specs) is deliberately NOT committed to the | |
| # repo — see .gitignore — instead it's persisted across runs via actions/cache below, keyed | |
| # per-run-id with a prefix restore-key so each run restores the most recent prior cache. | |
| # Update-PfbApiSpecs.ps1 skips any version already present on disk, so a cache hit means | |
| # only newly-published versions get fetched instead of the full ~28-version history. Only | |
| # the small derived Data/PfbCapabilityMap.json is tracked and diffed for the PR below. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: ['Public/**'] | |
| schedule: | |
| # Mondays 03:17 UTC - arbitrary off-peak time, avoids the top-of-hour thundering herd. | |
| - cron: '17 3 * * 1' | |
| workflow_dispatch: {} | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| update-capability-map: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Capture previously-known REST versions | |
| id: previous | |
| shell: pwsh | |
| run: | | |
| $versions = @() | |
| if (Test-Path 'Data/PfbCapabilityMap.json') { | |
| $versions = (Get-Content 'Data/PfbCapabilityMap.json' -Raw | ConvertFrom-Json -Depth 5).generatedFrom | |
| } | |
| "versions=$($versions -join ',')" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
| - name: Restore cached spec files | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: tools/specs | |
| key: pfb-specs-${{ github.run_id }} | |
| restore-keys: | | |
| pfb-specs- | |
| - name: Fetch all published REST API spec versions | |
| shell: pwsh | |
| run: ./tools/Update-PfbApiSpecs.ps1 | |
| - name: Save spec cache | |
| uses: actions/cache/save@v6 | |
| if: always() | |
| with: | |
| path: tools/specs | |
| key: pfb-specs-${{ github.run_id }} | |
| - name: Build capability map | |
| shell: pwsh | |
| run: ./tools/Build-PfbCapabilityMap.ps1 | |
| - name: Update REST<->Purity version map (skips gracefully if not configured) | |
| shell: pwsh | |
| env: | |
| SSOT_API_KEY: ${{ secrets.SSOT_API_KEY }} | |
| SSOT_BASE_URI: ${{ secrets.SSOT_BASE_URI }} | |
| SSOT_TOPIC_ID: ${{ secrets.SSOT_TOPIC_ID }} | |
| run: ./tools/Update-PfbVersionMap.ps1 | |
| - name: Build value-enum map | |
| shell: pwsh | |
| run: ./tools/Build-PfbValueEnumMap.ps1 | |
| - name: Build field-cmdlet map | |
| shell: pwsh | |
| run: ./tools/Build-PfbFieldCmdletMap.ps1 | |
| # Position is load-bearing, do not reorder: this must run AFTER "Fetch all published | |
| # REST API spec versions" (the generator walks tools/specs/ and never fetches) and | |
| # BEFORE "Build API drift report" (the report reads Data/PfbResponseShapeMap.json). | |
| # Placed after the report, CI would build the report from the stale committed map and | |
| # then overwrite it -- a report and map that disagree, with no error raised. | |
| - name: Build response shape map | |
| shell: pwsh | |
| run: ./tools/Build-PfbResponseShapeMap.ps1 | |
| - name: Build API drift report | |
| shell: pwsh | |
| run: ./tools/Build-PfbApiDriftReport.ps1 | |
| # Pinned + cached, with retry on the gallery path; see | |
| # .github/actions/install-test-modules/action.yml (including why Posh-SSH is | |
| # needed at all -- Pester can only mock a resolvable command). | |
| - name: Install test dependencies | |
| uses: ./.github/actions/install-test-modules | |
| with: | |
| shell: pwsh | |
| - name: Run tests | |
| shell: pwsh | |
| run: | | |
| Import-Module Pester -MinimumVersion 5.0 -Force | |
| Import-Module Posh-SSH -Force | |
| $cfg = New-PesterConfiguration | |
| $cfg.Run.Path = 'Tests' | |
| $cfg.Run.Exit = $true | |
| $cfg.Output.Verbosity = 'Detailed' | |
| Invoke-Pester -Configuration $cfg | |
| - name: Check for changes | |
| id: diff | |
| run: | | |
| if [ -n "$(git status --porcelain -- Data Reports)" ]; then | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Summarize new versions | |
| id: summary | |
| if: steps.diff.outputs.changed == 'true' | |
| shell: pwsh | |
| run: | | |
| $oldVersions = @('${{ steps.previous.outputs.versions }}' -split ',' | Where-Object { $_ }) | |
| $newManifest = Get-Content 'Data/PfbCapabilityMap.json' -Raw | ConvertFrom-Json -Depth 5 | |
| $newlyAdded = $newManifest.generatedFrom | Where-Object { $oldVersions -notcontains $_ } | |
| "new_versions=$($newlyAdded -join ', ')" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
| # $drift.parameterGaps.Count counts ENDPOINTS that have at least one gap, not | |
| # individual fields -- it was mislabeled "parameter gaps" here, which read as a | |
| # field-level count. Query/body/read-only are separate categories on the report | |
| # (see tools/Build-PfbApiDriftReport.ps1), so the field-level total is the sum of | |
| # each category's own field count, computed honestly from the report rather than | |
| # re-using the endpoint count under a field-shaped label. | |
| $drift = Get-Content 'Reports/PfbApiDriftReport.json' -Raw | ConvertFrom-Json -Depth 20 | |
| $queryFieldCount = (@($drift.parameterGaps.missingQueryParameters) | Measure-Object).Count | |
| $bodyFieldCount = (@($drift.parameterGaps.missingBodyProperties) | Measure-Object).Count | |
| $readOnlyFieldCount = (@($drift.parameterGaps.readOnlyFields) | Measure-Object).Count | |
| # Same @() guard as above, for the same reason: ConvertFrom-Json yields a bare | |
| # object for a single-element array and $null for a missing key, so a direct | |
| # .Count is unreliable for both. | |
| $responseRemovalCount = (@($drift.responseFieldRemovals) | Measure-Object).Count | |
| $responseRenameCount = (@($drift.responseFieldRenameCandidates) | Measure-Object).Count | |
| $unhandledEnvelopeCount = (@($drift.unhandledResponseEnvelopeFields) | Measure-Object).Count | |
| $driftSummary = "$($drift.uncoveredEndpoints.Count) uncovered endpoints, $($drift.parameterGaps.Count) endpoints with parameter gaps ($queryFieldCount missing query fields, $bodyFieldCount missing body fields, $readOnlyFieldCount read-only fields), $($drift.systemicGaps.Count) systemic gaps, $($drift.validateSetDrift.Count) ValidateSet drift findings, $($drift.newValidateSetCandidates.Count) new ValidateSet candidates, $responseRemovalCount response field removals (one per endpoint+field pair), $responseRenameCount response field rename candidates, $unhandledEnvelopeCount unhandled response envelope fields" | |
| "drift_summary=$driftSummary" | Out-File -FilePath $env:GITHUB_OUTPUT -Append | |
| - name: Open pull request | |
| if: steps.diff.outputs.changed == 'true' && github.repository == 'dmann000/fb-powershell' | |
| # v8 for the node24 runtime (v6 and v7 both run on node20 and emit a deprecation | |
| # warning). Safe jump despite skipping a major: v7's only breaking changes were | |
| # renaming the `git-token` input to `branch-token` and removing the deprecated | |
| # PULL_REQUEST_NUMBER output env var, neither of which this step uses. | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| commit-message: 'Update API capability map' | |
| title: "Update API capability map${{ steps.summary.outputs.new_versions && format(' (new REST versions: {0})', steps.summary.outputs.new_versions) || '' }}" | |
| body: | | |
| Automated update from the `update-api-capability-map` workflow. | |
| - Re-fetched every published REST API spec version from the FlashBlade | |
| swagger index (not committed - see `.gitignore`) and rebuilt | |
| `Data/PfbCapabilityMap.json` from the full history. | |
| - Updated `Data/PfbVersionMap.json` if an `SSOT_API_KEY` secret is | |
| configured; otherwise left untouched (see `tools/Update-PfbVersionMap.ps1`). | |
| - Rebuilt `Data/PfbResponseShapeMap.json`, the response-side counterpart to the | |
| capability map, which feeds the drift report's response-shape findings. | |
| - Rebuilt `Reports/PfbValueEnumMap.json`, `Reports/PfbFieldCmdletMap.json`, and | |
| `Reports/PfbApiDriftReport.json` (+ their Markdown companions) -- see | |
| `Reports/README.md` for what each answers. | |
| New REST versions detected: ${{ steps.summary.outputs.new_versions || 'none - see diff (e.g. a version-map-only update once an SSOT_API_KEY secret was configured, or new parameters/fields added to existing endpoints in a point release)' }} | |
| API drift report: ${{ steps.summary.outputs.drift_summary || 'no drift-report changes this run' }} | |
| branch: automated/update-api-capability-map | |
| delete-branch: true | |
| add-paths: | | |
| Data | |
| Reports |