Skip to content

🚀 [Feature]: Manage Atlassian Confluence Cloud from PowerShell#17

Open
Marius Storhaug (MariusStorhaug) wants to merge 33 commits into
mainfrom
feat/decompose-module
Open

🚀 [Feature]: Manage Atlassian Confluence Cloud from PowerShell#17
Marius Storhaug (MariusStorhaug) wants to merge 33 commits into
mainfrom
feat/decompose-module

Conversation

@MariusStorhaug

@MariusStorhaug Marius Storhaug (MariusStorhaug) commented Jul 7, 2026

Copy link
Copy Markdown
Member

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: 41 Confluence commands

Grouped by resource area:

  • AuthConnect-Confluence, Disconnect-Confluence, Get-ConfluenceContext
  • ConfigGet-ConfluenceConfig, Set-ConfluenceConfig
  • APIInvoke-ConfluenceRestMethod (the single generic REST entry point every command wraps)
  • SpacesGet-ConfluenceSpace, Get-ConfluenceSpacePermission, Get-ConfluenceSpaceProperty, plus space administration: New-ConfluenceSpace (create), Update-ConfluenceSpace (partial update), Set-ConfluenceSpace (declarative create-or-replace), Remove-ConfluenceSpace (permanent, asynchronous delete)
  • Site / Pages / BlogPosts / Folders / Comments / Labels / ContentProperties / Attachments / Restrictions / Users — read/write commands per area; page edits use Update-ConfluencePage (renamed from Set-ConfluencePage, since it performs a partial update and the Set verb is reserved for declarative create-or-replace as in Set-ConfluenceSpace)

Each command documents its required OAuth granular scope in its help, and errors surface Atlassian's X-Failure-Category (for example FAILURE_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 #Requires so the build records it as a manifest dependency. Connect once — the token is stored as a SecureString. Store multiple sites or accounts as named contexts and target any of them with -Context.

$token = Read-Host -AsSecureString
Connect-Confluence -ApiBaseUri 'https://api.atlassian.com/ex/confluence/<cloudId>' -Username 'you@example.com' -Token $token -SpaceKey 'DOCS'
$space = Get-ConfluenceSpace -Key 'DOCS'
New-ConfluencePage -SpaceId $space.id -Title 'Release notes' -Body '<p>Hello</p>'

How it is built

  • One function per file under src/functions/{public,private}, grouped by resource area; module state in src/variables/private.
  • No header.ps1 and no source manifest.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.
  • Comment-based help follows the GitHub module style: indented sections, fenced examples, and a documentation-page .LINK first.
  • Examples (Connecting, Pages) and a credential-free surface test, plus a skipped integration scaffold that reads CONFLUENCE_* 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:FunctionTest marker so the framework's source-code test suite passes while per-function tests are deferred.

Technical details

… 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
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Fail ❌
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

Super-linter detected linting errors

For more information, see the GitHub Actions workflow run

Powered by Super-linter

POWERSHELL

�[32;1mRuleName                           �[0m�[32;1m Severity    �[0m�[32;1m ScriptName�[0m�[32;1m Line �[0m�[32;1m Message�[0m
�[32;1m--------                           �[0m �[32;1m--------    �[0m �[32;1m----------�[0m �[32;1m---- �[0m �[32;1m-------�[0m
PSUseDeclaredVarsMoreThanAssignment Warning      Pages.ps1  25    The variable
s                                                                 'child' is as
                                                                  signed but ne
                                                                  ver used.


�[32;1mRuleName                           �[0m�[32;1m Severity    �[0m�[32;1m ScriptName�[0m�[32;1m Line �[0m�[32;1m Message�[0m
�[32;1m--------                           �[0m �[32;1m--------    �[0m �[32;1m----------�[0m �[32;1m---- �[0m �[32;1m-------�[0m
PSAvoidLongLines                    Warning      Confluence 73    Line exceeds
                                                 .Tests.ps1       the configure
                                                                  d maximum len
                                                                  gth of 150 ch
                                                                  aracters
PSAvoidUsingConvertToSecureStringWi Error        Confluence 72    File 'Conflue
thPlainText                                      .Tests.ps1       nce.Tests.ps1
                                                                  ' uses Conver
                                                                  tTo-SecureStr
                                                                  ing with plai
                                                                  ntext. This w
                                                                  ill expose se
                                                                  cure informat
                                                                  ion. Encrypte
                                                                  d standard st
                                                                  rings should
                                                                  be used inste
                                                                  ad.

- 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)
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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).
@MariusStorhaug Marius Storhaug (MariusStorhaug) added the minor Minor change, version 0.x.0 increase label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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.
@MariusStorhaug Marius Storhaug (MariusStorhaug) changed the title 🚀 [Feature]: Decompose the Confluence client into the PSModule source layout 🚀 [Feature]: Manage Atlassian Confluence Cloud from PowerShell Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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).
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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.
Comment thread .github/workflows/Process-PSModule.yml Fixed
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Super-linter summary

Language Validation result
CHECKOV Pass ✅
GITHUB_ACTIONS Pass ✅
GITLEAKS Pass ✅
GIT_MERGE_CONFLICT_MARKERS Pass ✅
MARKDOWN Pass ✅
NATURAL_LANGUAGE Pass ✅
POWERSHELL Pass ✅
PRE_COMMIT Pass ✅
SPELL_CODESPELL Pass ✅
TRIVY Pass ✅
YAML Pass ✅

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-ConfluenceRestMethod as 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.

Comment thread src/functions/public/Attachments/Add-ConfluenceAttachment.ps1
Comment thread README.md Outdated
Comment thread examples/Connecting.ps1 Outdated
Comment thread examples/Connecting.ps1 Outdated
Comment thread .github/workflows/Process-PSModule.yml Outdated
Comment thread tests/Confluence.Tests.ps1
Comment thread SCOPES.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 55 out of 55 changed files in this pull request and generated 2 comments.

Comment thread src/functions/public/API/Invoke-ConfluenceRestMethod.ps1 Outdated
Comment thread SCOPES.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 55 out of 55 changed files in this pull request and generated 1 comment.

Comment thread src/functions/public/API/Invoke-ConfluenceRestMethod.ps1
Rewrite tests/Confluence.Tests.ps1 into a full integration suite that drives the module's own commands through create/read/update/delete for pages, folders, comments, labels, content properties and attachments, and reads spaces, permissions, properties, restrictions, users, blog posts and the raw REST entry point. Each command's processed object is logged with LogGroup so outputs are visible in the run log (matching the PSModule/GitHub test style).

Add context-storage tests: profile fields, SecureString token, default and -ListAvailable contexts, multiple named contexts targeted with -Context, and config round-trip.

Remove the #SkipTest:FunctionTest markers now that every public function is invoked by a test, so the source-code FunctionTest check passes without deferral warnings.

Get-ConfluenceConfig now returns a defensive copy so callers cannot corrupt the in-memory configuration cache; changes still flow through Set-ConfluenceConfig.
Confluence briefly returns HTTP 409 when an attachment is deleted immediately after upload (observed on the macOS runner while Linux/Windows passed). The Remove-ConfluenceAttachment test now retries the delete on a conflict with a short backoff so it reflects the eventual-consistency behaviour instead of flaking.
…Page to Update-ConfluencePage

Add New/Update/Set/Remove-ConfluenceSpace so spaces can be created, modified,
declaratively upserted, and permanently deleted (v1 space endpoints; delete is
async and returns a 202 long-running task). Rename Set-ConfluencePage to
Update-ConfluencePage because it performs a partial update (increments the
version), reserving the Set verb for declarative create-or-replace as used by
Set-ConfluenceSpace. Update README quick-start, SCOPES scope map, and the Pages
example to the new verb, and document the space-administration scope
requirements (write:space / delete:space / read:content.metadata).
…e integration scaffold

Add a #SkipTest:FunctionTest marker to every public function so the framework
source-code suite passes while per-function tests are deferred until the
repository Confluence credentials are wired up. Replace the comprehensive live
CRUD integration block with a minimal skipped smoke scaffold (resolve current
user, resolve configured space) that still runs only when all CONFLUENCE_*
credentials are present, and update the module-surface command inventory to
include the new space commands and the Update-ConfluencePage rename. Also drop
the defensive shallow copy in Get-ConfluenceConfig, returning the live config.
…artup failure

The workflow was pinned to commit ea019351 on the feat/52-test-secrets branch
(PR #365). That PR was squash-merged and its branch deleted, so the commit is no
longer reachable from any ref and GitHub Actions can no longer resolve the
reusable workflow, causing every run to fail at startup with zero jobs. The
TestData secret interface from PR #365 shipped in v6.0.0, so repin to the current
release v6.1.0 (0d7a2f0b), whose workflow_call interface still accepts the
APIKey and TestData secrets this caller passes.
…, TestData bridge)

Repinning to v6.1.0 surfaced three gaps in the source/test wiring:

- Add the #SkipTest:FunctionTest marker to Connect-Confluence and
  Get-ConfluenceAccessibleResource, the two public functions the marker pass
  missed. The FunctionTest source-code check requires every public function to
  have a test or the marker; slimming the integration suite removed the calls
  that previously covered them, so both were flagged.
- Wrap the 152-character query line in Update-ConfluenceSpace so it satisfies
  PSAvoidLongLines (the repo linter sets MaximumLineLength = 150).
- Add .github/scripts/Expose-TestData.ps1 (the canonical Process-PSModule v6
  script) so the ModuleLocal/Module test jobs can expose the caller-provided
  TestData secret. The caller workflow already passes TestData but the bridge
  script that turns it into environment variables was missing.
…ata)

Bump the reusable workflow pin from v6.1.1 to v6.1.2 and remove the consumer-side .github/scripts/Expose-TestData.ps1. v6.1.2 exposes the caller-provided TestData secret with a framework-side Import-TestData step, so the per-repo bridge script is no longer needed.
Fix the 42 Build-Docs textlint terminology errors by using 'ID' in the .SYNOPSIS/.DESCRIPTION/.PARAMETER prose across the commands. Code, backticked field names (e.g. the API 'id' field) and fenced examples are unchanged.
…g clone

Replace the slim smoke scaffold with the full live integration suite that exercises every command against the live Confluence site (gated on the CONFLUENCE_* credentials, skipped when absent) so coverage clears the 50% target. Add a scope-safe Space administration context for New/Update/Set/Remove-ConfluenceSpace using a random key so nothing persists when the write scope is absent. Restore the shallow-copy return in Get-ConfluenceConfig so callers cannot mutate the in-memory config cache.
The Build-Docs job's NATURAL_LANGUAGE (textlint terminology) linter flagged the lowercase 'api' path segment in '/wiki/rest/api,' in the generated docs (outputs/docs/API/Invoke-ConfluenceRestMethod.md:111), suggesting 'API'. That segment is a literal Confluence REST v1 path and must stay lowercase. Wrapping the /wiki/... paths in the -ApiEndpoint and -ApiVersion parameter help in backticks renders them as inline code, which textlint skips - matching how the already-passing backticked URLs in other command help are handled.
@MariusStorhaug Marius Storhaug (MariusStorhaug) marked this pull request as ready for review July 11, 2026 13:42
Copilot AI review requested due to automatic review settings July 11, 2026 13:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 59 out of 59 changed files in this pull request and generated 2 comments.

Comment on lines +11 to +14
[CmdletBinding()]
param()

BeforeAll {
$env:CONFLUENCE_SITE
$env:CONFLUENCE_USERNAME
$env:CONFLUENCE_SPACE_KEY
) | Where-Object { [string]::IsNullOrEmpty($_) }
v6.1.3 bumps the framework's internal lint/test action deps (Invoke-ScriptAnalyzer v5.0.0, Test-PSModule v3.0.14 -> Invoke-Pester v5.1.0); consumer linting now runs against the latest PSScriptAnalyzer. v6.1.4 fixes the Plan job crashing on schedule/workflow_dispatch (non-PR) events by bumping Resolve-PSModuleVersion to v1.1.5 (Fixes PSModule/Process-PSModule#373). The Settings contract is unchanged, so the caller keeps passing only APIKey + TestData.
Copilot AI review requested due to automatic review settings July 11, 2026 17:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 59 out of 59 changed files in this pull request and generated 3 comments.

Comment on lines +108 to +115
$missingIntegrationVars = @(
$env:CONFLUENCE_API_TOKEN
$env:CONFLUENCE_SITE
$env:CONFLUENCE_USERNAME
$env:CONFLUENCE_SPACE_KEY
) | Where-Object { [string]::IsNullOrEmpty($_) }

Context 'Integration' -Skip:(@($missingIntegrationVars).Count -gt 0) {
Comment on lines +135 to +136
$stored = Set-Context -ID $Name -Context $context -Vault $script:Confluence.ContextVault -PassThru
Set-ConfluenceConfig -Name 'DefaultContext' -Value $Name
Comment on lines +35 to +40
if ($PSCmdlet.ShouldProcess($Name, 'Remove Confluence credential context')) {
Remove-Context -ID $Name -Vault $script:Confluence.ContextVault -ErrorAction SilentlyContinue
if ($script:Confluence.Config['DefaultContext'] -eq $Name) {
Set-ConfluenceConfig -Name 'DefaultContext' -Value ''
}
}
Copilot AI review requested due to automatic review settings July 11, 2026 18:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 59 out of 59 changed files in this pull request and generated 2 comments.

[CmdletBinding()]
param()

BeforeAll {
$env:CONFLUENCE_SITE
$env:CONFLUENCE_USERNAME
$env:CONFLUENCE_SPACE_KEY
) | Where-Object { [string]::IsNullOrEmpty($_) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Minor change, version 0.x.0 increase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants