🚀 [Feature]: Manage Atlassian Confluence Cloud from PowerShell#17
🚀 [Feature]: Manage Atlassian Confluence Cloud from PowerShell#17Marius Storhaug (MariusStorhaug) wants to merge 20 commits into
Conversation
… layout Implements the first working version of the module by porting the generalized Confluence REST v2 client and decomposing it into the PSModule one-function-per-file source layout. - 35 public functions grouped by resource area (Auth, Config, API, Spaces, Site, Pages, BlogPosts, Folders, Comments, Labels, ContentProperties, Attachments, Restrictions, Users) - 4 private helpers (Auth, Config); module state in variables/private - Declares a dependency on the Context module via #Requires in header.ps1 (RequiredVersion 8.1.6), following the GitHub module pattern; credentials/config persist in the 'PSModule.Confluence' context vault - Removes the template scaffold placeholders; adds Connecting/Pages examples and a credential-free surface test plus a skipped integration scaffold that reads connection details from environment secrets - No tenant-specific data is included; examples use generic placeholders
Super-linter summary
Super-linter detected linting errors For more information, see the GitHub Actions workflow run Powered by Super-linter POWERSHELL |
- Drop the unused child-page variable in the Pages example - Splat Connect-Confluence in the integration test to stay within the line-length limit - Suppress PSAvoidUsingConvertToSecureStringWithPlainText (the API token is a CI environment secret)
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
…point The oversized module design comment lived only in header.ps1. Drop the file and relocate the two #Requires statements (PowerShell 7.0 and Context 8.1.6) to the top of Invoke-ConfluenceRestMethod.ps1 — the core function that every command routes through — so the build still generates the manifest's RequiredModules and PowerShellVersion. The framework injects the default CmdletBinding/param header when header.ps1 is absent.
The build generates the full manifest, and when the source manifest has no tags it collects them from the repository topics (Build-PSModuleManifest reads repositoryTopics). Repo topics set: confluence, atlassian, psmodule, powershell, powershell-module, pwsh, rest, rest-api. A missing source manifest is fully supported (the build starts from an empty manifest and derives version, description, project/license/icon URIs, and exports).
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
…d to its docs page Indent the help sections and add blank lines between them, wrap examples in fenced powershell blocks with a short description, and make the first .LINK each public command's documentation page (https://psmodule.io/Confluence/Functions/<Area>/<Command>/). Atlassian API references follow as additional .LINK entries. Private helpers are indented too but keep no docs link.
Keeps the implemented-module README over main's placeholder, keeps PSModuleTest.Tests.ps1 removed (replaced by Confluence.Tests.ps1), applies the Pester 6.x requirement from #16 to Confluence.Tests.ps1, and picks up the Process-PSModule workflow bump to v5.5.7.
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
Test-SourceCode requires a test for every public function; integration tests are deferred until the repository's Confluence credentials are configured, so mark each public function with #SkipTest:FunctionTest and a reason. Build-Docs runs markdownlint on the generated docs, which flagged the bare Confluence API URL in the Connect-Confluence -ApiBaseUri help — escape it with backticks (MD034).
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
Add SCOPES.md: the full granular Confluence scope set (22 scopes: 12 read, 6 write, 4 delete) the module's commands use, ready to paste when creating or rotating a scoped (ATSTT) API token used with Basic auth against the API gateway. Each scope maps to the commands that need it. Linked from the README.
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
…dule TestSecrets/TestVariables Replaces secrets: inherit with an explicit declaration of exactly what the module tests need: CONFLUENCE_API_TOKEN via TestSecrets (masked) and CONFLUENCE_API_BASE_URI / CONFLUENCE_USERNAME / CONFLUENCE_SPACE_KEY via TestVariables (not masked). Pinned to the Process-PSModule feature branch (PR #365) until it is released.
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
…OPES.md Updates SCOPES.md to the 48 granular scopes currently configured (25 read, 14 write, 9 delete), grouped by verb. Keeps the current-command mapping, flags that read:blogpost:confluence is no longer configured (Get-ConfluenceBlogPost would 403), and adds an "Additional scopes available for new commands" table listing candidate cmdlets the extra scopes unlock (custom content, databases, groups, users, restriction writes, analytics, comment updates, permission checks, configuration, space settings, embeds, whiteboard delete).
… cloud ID New public function resolves an Atlassian Confluence Cloud site to its cloud ID via the public /_edge/tenant_info endpoint, so callers can supply a site name or URL (bare subdomain, host, or full URL; pipeline supported) instead of the cloud ID. Unauthenticated; no scope required. Also reverts an accidental Context->Get-Context edit in the test file and registers the command in the surface test.
… map Connect-Confluence now takes -Site (name/host/URL, resolved to a cloud ID via the public tenant_info endpoint) or -CloudId (faster, direct); it builds the api.atlassian.com/ex/confluence/<cloudId> gateway base internally. Adds Get-ConfluenceAccessibleResource (lists sites/cloudIds/scopes a bearer token can reach) and an internal v1/v2 API-path map (v1 -> /wiki/rest/api, v2 -> /wiki/api/v2) usable via Invoke-ConfluenceRestMethod -ApiVersion. Integration test connects with -Site from CONFLUENCE_SITE.
…eCloudId; record token scopes on connect - Rename ConvertTo-ConfluenceCloudId to Get-ConfluenceCloudId: the function performs a GET against /_edge/tenant_info, so a Get- verb is accurate. Help, examples, the Connect-Confluence reference, and the surface test are updated. - Connect-Confluence now collects the token's scopes from the accessible-resources endpoint and stores them on the context (Scopes), so callers can see what the token can do. Collection is best-effort and never fails the connection.
…CodeQL-clean)
Adopt the combined TestData secret from Process-PSModule: one object with
"secrets" (masked) and "variables" (not masked) instead of separate TestSecrets
and TestVariables. Reference the token with the direct "${{ secrets.X }}" form to
resolve the CodeQL "excessive secrets exposure" alert, and keep the blob on one
folded line so GitHub registers a single mask. Repin to the framework branch head.
There was a problem hiding this comment.
Pull request overview
This PR turns the repository into a functional Confluence Cloud PowerShell module, adding a context-backed connection model plus a generic REST invoker and a first set of resource cmdlets, with updated docs/examples and CI wiring.
Changes:
- Adds
Invoke-ConfluenceRestMethodas the core Confluence REST wrapper, plus Context-based connect/disconnect/config helpers. - Introduces public cmdlets across key Confluence resources (spaces, pages, folders, comments, labels, attachments, restrictions, etc.) and supporting private helpers/state.
- Replaces placeholder scaffolding with real docs/examples, scopes documentation, a surface/integration test scaffold, and updated workflow secret/test-data handling.
Reviewed changes
Copilot reviewed 55 out of 55 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/PSModuleTest.Tests.ps1 | Removes scaffold “hello world” test. |
| tests/Confluence.Tests.ps1 | Adds module surface tests and skipped integration scaffold driven by env vars. |
| src/variables/private/Confluence.ps1 | Introduces module state (vault name, API path map, default config). |
| src/scripts/loader.ps1 | Removes placeholder loader output. |
| src/init/initializer.ps1 | Removes placeholder initializer output. |
| src/header.ps1 | Removes placeholder header stub. |
| src/functions/public/Users/Get-ConfluenceCurrentUser.ps1 | Adds cmdlet to resolve current authenticated user via v1 endpoint. |
| src/functions/public/Spaces/Get-ConfluenceSpaceProperty.ps1 | Adds cmdlet to list/get space properties. |
| src/functions/public/Spaces/Get-ConfluenceSpacePermission.ps1 | Adds cmdlet to list space permission assignments. |
| src/functions/public/Spaces/Get-ConfluenceSpace.ps1 | Adds cmdlet to fetch a space by key/id with default context fallback. |
| src/functions/public/Site/Get-ConfluenceSiteInfo.ps1 | Adds cmdlet to return cloudId + browsable site URL probe. |
| src/functions/public/Site/Get-ConfluenceCloudId.ps1 | Adds cmdlet to resolve cloudId via public tenant_info endpoint. |
| src/functions/public/Restrictions/Get-ConfluenceRestriction.ps1 | Adds cmdlet to read page restrictions via v1 endpoint. |
| src/functions/public/Pages/Set-ConfluencePage.ps1 | Adds cmdlet to update a page (read current, increment version, PUT). |
| src/functions/public/Pages/Remove-ConfluencePage.ps1 | Adds cmdlet to trash/purge pages with optional recursive deletion of children. |
| src/functions/public/Pages/New-ConfluencePage.ps1 | Adds cmdlet to create pages (optionally under a parent). |
| src/functions/public/Pages/Get-ConfluencePageVersion.ps1 | Adds cmdlet to list page version history. |
| src/functions/public/Pages/Get-ConfluencePageChild.ps1 | Adds cmdlet to list direct child pages. |
| src/functions/public/Pages/Get-ConfluencePage.ps1 | Adds cmdlet to fetch a page with requested body format. |
| src/functions/public/Pages/Get-ConfluenceDescendant.ps1 | Adds cmdlet to list descendants with automatic pagination. |
| src/functions/public/Labels/Remove-ConfluenceLabel.ps1 | Adds cmdlet to remove a label from a page via v1 endpoint. |
| src/functions/public/Labels/Get-ConfluenceLabel.ps1 | Adds cmdlet to list labels on a page via v2 endpoint. |
| src/functions/public/Labels/Add-ConfluenceLabel.ps1 | Adds cmdlet to add labels via v1 endpoint with explicit JSON array payload. |
| src/functions/public/Get-PSModuleTest.ps1 | Removes scaffold public function. |
| src/functions/public/Folders/Remove-ConfluenceFolder.ps1 | Adds cmdlet to delete/trash a folder. |
| src/functions/public/Folders/New-ConfluenceFolder.ps1 | Adds cmdlet to create a folder (optional parent). |
| src/functions/public/Folders/Get-ConfluenceFolder.ps1 | Adds cmdlet to fetch a folder by id. |
| src/functions/public/ContentProperties/Set-ConfluenceContentProperty.ps1 | Adds cmdlet to create/update a content property with version increment. |
| src/functions/public/ContentProperties/Remove-ConfluenceContentProperty.ps1 | Adds cmdlet to delete a content property by id. |
| src/functions/public/ContentProperties/Get-ConfluenceContentProperty.ps1 | Adds cmdlet to list/get content properties by key. |
| src/functions/public/Config/Set-ConfluenceConfig.ps1 | Adds cmdlet to set and persist module config in the Context vault. |
| src/functions/public/Config/Get-ConfluenceConfig.ps1 | Adds cmdlet to read module config (whole or key). |
| src/functions/public/Comments/Remove-ConfluenceComment.ps1 | Adds cmdlet to delete footer comments by id. |
| src/functions/public/Comments/Get-ConfluenceComment.ps1 | Adds cmdlet to list footer comments on a page. |
| src/functions/public/Comments/Add-ConfluenceComment.ps1 | Adds cmdlet to create a footer comment. |
| src/functions/public/BlogPosts/Get-ConfluenceBlogPost.ps1 | Adds cmdlet to list/get blog posts. |
| src/functions/public/Auth/Get-ConfluenceContext.ps1 | Adds cmdlet to retrieve stored Confluence contexts/default context. |
| src/functions/public/Auth/Get-ConfluenceAccessibleResource.ps1 | Adds cmdlet to call accessible-resources with bearer token. |
| src/functions/public/Auth/Disconnect-Confluence.ps1 | Adds cmdlet to remove a stored context and clear default if needed. |
| src/functions/public/Auth/Connect-Confluence.ps1 | Adds cmdlet to resolve cloudId (optional), validate token, store context, set default. |
| src/functions/public/Attachments/Remove-ConfluenceAttachment.ps1 | Adds cmdlet to delete attachments by id. |
| src/functions/public/Attachments/Get-ConfluenceAttachment.ps1 | Adds cmdlet to list attachments for a page or get by id. |
| src/functions/public/Attachments/Add-ConfluenceAttachment.ps1 | Adds cmdlet to upload an attachment via multipart form. |
| src/functions/public/API/Invoke-ConfluenceRestMethod.ps1 | Adds core REST invoker (auth/header, pagination, error shaping, debug redaction). |
| src/functions/private/Config/Initialize-ConfluenceConfig.ps1 | Adds private config loader/backfill/persist logic. |
| src/functions/private/Config/ConvertTo-ConfluenceHashtable.ps1 | Adds helper to convert stored objects into mutable hashtables. |
| src/functions/private/Auth/Resolve-ConfluenceToken.ps1 | Adds helper to extract plaintext token from SecureString/string. |
| src/functions/private/Auth/Resolve-ConfluenceContext.ps1 | Adds helper to resolve context object/name/default into a usable context. |
| src/finally.ps1 | Removes placeholder “last loader” output. |
| SCOPES.md | Adds scope inventory and mapping from cmdlets to required Confluence scopes. |
| README.md | Updates README from placeholder to install/usage/docs for the implemented module. |
| examples/Pages.ps1 | Adds example script for CRUD-ish page workflows plus labels/comments. |
| examples/General.ps1 | Removes unrelated scaffold example content. |
| examples/Connecting.ps1 | Adds example script for connecting and managing contexts/config. |
| .github/workflows/Process-PSModule.yml | Updates workflow to pin a feature SHA and pass minimal secrets/test data. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…lign blog post scope
…void redundant config writes
…e-ConfluencePage -Purge
Confluence is now a working PowerShell module: connect to an Atlassian Confluence Cloud site once and manage pages, spaces, blog posts, folders, comments, labels, content properties, attachments, and restrictions as first-class PowerShell commands. This first version ports the generalized Confluence REST v2 client into the PSModule source layout and wires it to the Process-PSModule build.
New: 35 Confluence commands
Grouped by resource area:
Connect-Confluence,Disconnect-Confluence,Get-ConfluenceContextGet-ConfluenceConfig,Set-ConfluenceConfigInvoke-ConfluenceRestMethod(the single generic REST entry point every command wraps)Each command documents its required OAuth granular scope in its help, and errors surface Atlassian's
X-Failure-Category(for exampleFAILURE_CLIENT_SCOPE_CHECK) so permission/scope failures are easy to spot. Every command's help links to its documentation page (https://psmodule.io/Confluence/Functions/<Area>/<Command>/) followed by the relevant Atlassian API reference.New: reusable connections via Context
Credentials and module configuration persist through the Context module, declared via
#Requiresso the build records it as a manifest dependency. Connect once — the token is stored as aSecureString. Store multiple sites or accounts as named contexts and target any of them with-Context.How it is built
src/functions/{public,private}, grouped by resource area; module state insrc/variables/private.header.ps1and no sourcemanifest.psd1— the build generates the manifest, derives the module tags from the repository topics, and reads the#Requires(PowerShell 7.0 and Context) from the source..LINKfirst.Connecting,Pages) and a credential-free surface test, plus a skipped integration scaffold that readsCONFLUENCE_*environment secrets. Tests require Pester 6.x.Tests and secrets
No tenant-specific data is included — examples use generic placeholders. The integration tests are skipped unless connection details are provided through repository environment secrets (
CONFLUENCE_API_BASE_URI,CONFLUENCE_USERNAME,CONFLUENCE_API_TOKEN,CONFLUENCE_SPACE_KEY), which will be wired up in a follow-up. Until then, each public function carries a#SkipTest:FunctionTestmarker so the framework's source-code test suite passes while per-function tests are deferred.Technical details
main: kept the implemented-module README over the placeholder (📖 [Docs]: README pages now use the standard module landing-page format #15), adopted the Pester 6.x requirement (⚙️ [Maintenance]: Require Pester 6.x in test files #16), and picked up the Process-PSModule workflow bump to v5.5.7 (Bump PSModule/Process-PSModule/.github/workflows/workflow.yml from 5.4.6 to 5.5.7 #14)..LINKresolves to its docs page, and the module assembles and imports with all 35 public functions.major/minor/patch/NoReleaselabels created for the release automation.