Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions .github/workflows/update-api-capability-map.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
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@v4
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@v4
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

- name: Build API drift report
shell: pwsh
run: ./tools/Build-PfbApiDriftReport.ps1

- name: Run tests
shell: pwsh
run: |
Install-Module -Name Pester -MinimumVersion 5.0 -Force -SkipPublisherCheck -Scope CurrentUser
Import-Module Pester -MinimumVersion 5.0 -Force
# Posh-SSH is an optional runtime dependency (see Private/Get-PfbApiTokenViaSsh.ps1),
# but Get-PfbApiTokenViaSsh.Tests.ps1 mocks its cmdlets (New-SSHSession, etc.) --
# Pester can only mock a command that's resolvable, so it must be installed here
# even though the module under test never actually opens an SSH connection.
Install-Module -Name Posh-SSH -Force -SkipPublisherCheck -Scope CurrentUser
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 = Get-Content 'Reports/PfbApiDriftReport.json' -Raw | ConvertFrom-Json -Depth 20
$driftSummary = "$($drift.uncoveredEndpoints.Count) uncovered endpoints, $($drift.parameterGaps.Count) parameter gaps, $($drift.validateSetDrift.Count) ValidateSet drift findings, $($drift.newValidateSetCandidates.Count) new ValidateSet candidates"
"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'
uses: peter-evans/create-pull-request@v6
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 `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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

# Test report output (regenerated each run)
_test_report.html
testResults.xml

# Build output (regenerated by scripts/build.ps1 / Tests/Generate-Reports.ps1)
# Cover everything under build/ — there's no reason any of it should be committed.
Expand All @@ -13,6 +14,9 @@ build/
.vs/
.vscode/

# Local git worktrees (see using-git-worktrees skill)
.worktrees/

# Dev-only scratch files
.env.ps1
swagger.json
Expand All @@ -24,6 +28,13 @@ Tests/.coverage-*.csv
.superpowers/
docs/superpowers/

# Cached raw OpenAPI specs (tools/Update-PfbApiSpecs.ps1) — build-time input only, never
# read at runtime. Deliberately NOT committed: at ~1-3MB per REST version (~48MB for the
# full history), committing these would bloat every clone of this repo, which today is
# also what users copy directly into their PSModulePath (see README "From source").
# Only the small derived Data/PfbCapabilityMap.json is committed/shipped.
tools/specs/

# PowerShell
*.pssproj.user

Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,45 @@

All notable changes to `PureStorageFlashBladePowerShell` are documented in this file.

## [2.2.0] - 2026-07-22

API version-awareness plus seven documented-but-unexposed query-parameter enums.

### Added

- API capability check. A generated capability map (`Data/PfbCapabilityMap.json`)
records the REST API version that introduced every endpoint, query parameter, and
field; a REST-to-Purity//FB version map (`Data/PfbVersionMap.json`) makes the errors
readable. `Invoke-PfbApiRequest` now runs a fail-fast check (`Assert-PfbApiCapability`)
that rejects a call **before any HTTP request** when the connected array's version
cannot support what is being asked, with a clear "upgrade the array or omit the
unsupported option(s)" message. The check **fails safe**: a missing map, an unmatched
endpoint, or an unresolvable version is a graceful no-op, never a false rejection.
- Seven query-parameter enums the REST API documents but the cmdlets never exposed
(all additive, default to "not sent"): `Get-PfbArrayConnectionPerformanceReplication -Type`,
`Get-PfbArrayPerformanceReplication -Type`, `Test-PfbSupport -TestType`,
`Invoke-PfbNetworkTrace -Method`, `Get-PfbFileSystemSession -Protocol`,
`Remove-PfbFileSystemSession -Protocol`, and `Get-PfbPolicyAllMember -MemberType`
(an `ArgumentCompleter` rather than a `ValidateSet`, because that value set grew from
4 to 5 at REST v2.17 and a hard set would block a value the array accepts).
- A reporting-only maintainer toolchain under `tools/` (value-enum extraction,
field-to-cmdlet validation recommendations, and a combined API drift report). Nothing
is wired into cmdlet validation yet; that is a deliberate follow-on decision.

### Fixed

- `Get-`/`Remove-PfbFileSystemSession`: removed the `-Id` parameter (the endpoint has no
`ids` query parameter in any spec version, so it never worked), corrected `-Name` help
(it filters by the session's own generated name, not a file system name), and made
`-Protocol` its own mutually-exclusive parameter set. On `Remove-PfbFileSystemSession`,
`-Protocol` is a genuine array-wide bulk-terminate mode and now requires an explicit
`-Force` switch.

### Changed

- `scripts/build.ps1` and `scripts/Publish-Gallery.ps1` now bundle `Data/` into the
built and branded packages, so the capability check is live for installed copies.

## [2.1.2] - 2026-07-20

API-drift cleanup: parameter-validation fixes and removal of three cmdlets that
Expand Down
Loading