Jira and Confluence tool examples added#9
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds PowerShell example scripts for interacting with Jira and Confluence APIs, providing developers with ready-to-use functions for common operations like retrieving task information, searching pages, and managing Confluence content.
Key Changes:
- Added Get-JiraTaskInfo function for retrieving Jira task details via REST API
- Added 8 Confluence functions covering space navigation, page search, content management, and CRUD operations
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
| examples/Get-JiraTaskInfo.ps1 | Implements function to retrieve Jira task information using PAT authentication |
| examples/Find-InConfluence.ps1 | Implements comprehensive Confluence API wrapper functions for searching, reading, and managing pages and spaces |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @{ | ||
| "Error" = "Failed to retrieve Jira task information" | ||
| "ErrorMessage" = $_.Exception.Message | ||
| "TaskCode" = $JiraTaskCode |
There was a problem hiding this comment.
Error messages should be more descriptive. The generic message "Failed to retrieve Jira task information" doesn't provide context about what might have gone wrong (e.g., authentication failure, task not found, network error). Consider making the error message more specific or including the HTTP status code if available.
| @{ | |
| "Error" = "Failed to retrieve Jira task information" | |
| "ErrorMessage" = $_.Exception.Message | |
| "TaskCode" = $JiraTaskCode | |
| # Try to extract HTTP status information from the exception, if available | |
| $statusCode = $null | |
| $statusDescription = $null | |
| if ($_.Exception.Response -and $_.Exception.Response.StatusCode) { | |
| $statusCode = $_.Exception.Response.StatusCode.value__ | |
| $statusDescription = $_.Exception.Response.StatusDescription | |
| } | |
| $errorText = "Failed to retrieve Jira task information" | |
| if ($statusCode) { | |
| $errorText += " (HTTP Status: $statusCode" | |
| if ($statusDescription) { | |
| $errorText += " $statusDescription" | |
| } | |
| $errorText += ")" | |
| } | |
| @{ | |
| "Error" = $errorText | |
| "ErrorMessage" = $_.Exception.Message | |
| "TaskCode" = $JiraTaskCode | |
| "StatusCode" = $statusCode | |
| "StatusDescription" = $statusDescription | |
| "ApiUrl" = $apiUrl |
| $searchPosition = $bodyText.IndexOf($searchText) | ||
| $excerpt = "" | ||
| if ($searchPosition -ge 0) { | ||
| $startPos = [Math]::Max(0, $searchPosition - 100) | ||
| $length = [Math]::Min(200, $bodyText.Length - $startPos) | ||
| $excerpt = $bodyText.Substring($startPos, $length).Trim() | ||
| } |
There was a problem hiding this comment.
The search position logic may not work correctly for case-insensitive searches. The CQL query text~'$searchText' performs a fuzzy/case-insensitive search, but IndexOf is case-sensitive by default. This could result in "No match found" (HasMatch = false) even when the CQL search returned the page. Consider using IndexOf with StringComparison.OrdinalIgnoreCase for consistency.
examples/Find-InConfluence.ps1
Outdated
| # create CQL | ||
| if ($spaceKey) { | ||
| $cql = "type=page AND title='$title' AND space='$spaceKey'" | ||
| } else { | ||
| $cql = "type=page AND text='$title'" |
There was a problem hiding this comment.
The CQL query string in Get-PageIdByTitleInConfluence is built by concatenating unescaped user-controlled values ($title, $spaceKey) directly into the CQL expression, which allows CQL injection if these parameters contain quotes or operators. An attacker who can influence title could break out of the quoted literal (e.g. by including ' OR ...) and alter the query to bypass intended space scoping or search constraints, potentially reading unintended content under the privileges of the PAT used. You should properly escape or parameterize user input in the CQL string (e.g. safely encoding quotes and special characters inside the CQL literal) before sending it to Confluence.
| # create CQL | |
| if ($spaceKey) { | |
| $cql = "type=page AND title='$title' AND space='$spaceKey'" | |
| } else { | |
| $cql = "type=page AND text='$title'" | |
| # escape user-controlled values for safe use in CQL string literals | |
| $escapedTitle = $title -replace '\\', '\\\\' | |
| $escapedTitle = $escapedTitle -replace "'", "\'" | |
| $escapedSpaceKey = $spaceKey | |
| if ($escapedSpaceKey) { | |
| $escapedSpaceKey = $escapedSpaceKey -replace '\\', '\\\\' | |
| $escapedSpaceKey = $escapedSpaceKey -replace "'", "\'" | |
| } | |
| # create CQL | |
| if ($spaceKey) { | |
| $cql = "type=page AND title='$escapedTitle' AND space='$escapedSpaceKey'" | |
| } else { | |
| $cql = "type=page AND text='$escapedTitle'" |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Commented-out code removed Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
copy-paste issue fixed Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
escape handling Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
luchezarno
left a comment
There was a problem hiding this comment.
Could you please rerun Copilot?
|
@luchezarno Excellent work on your first PRs. Thanks for jumping through the hoops to tighten it up. I need to update the changelog/readme and psd1 version. Then I can publish. Like I mentioned, I wish I had access to the subsytems so I could try some things. PowerShell functions like this can be used in an MCP setup, as standalone agents and in my new feature as skills (ported the new Claude CLI skills pattern). They each have their pros and cons. Plus, always good to have options. |
|
@dfinke |
|
@luchezarno That looks very useful. Need to think about where to host it. Thank you! |
Jira and Confluence tool examples added in Examples folder
Feel free to use it as you wish