Skip to content
Merged
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
37 changes: 37 additions & 0 deletions Test/private/mocks/invoke-createDraftItem.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"data": {
"addProjectV2DraftIssue": {
"projectItem": {
"id": "PVTI_lADOAlIw4c4BCe3VzggDT7s",
"type": "DRAFT_ISSUE",
"fullDatabaseId": "134434747",
"project": {
"id": "PVT_kwDOAlIw4c4BCe3V",
"url": "https://github.com/orgs/octodemo/projects/700"
},
"content": {
"__typename": "DraftIssue",
"id": "DI_lADOAlIw4c4BCe3VzgJ29YM",
"body": "Body of draftissue",
"title": "DraftIssue created for test ",
"updatedAt": "2025-10-19T10:50:07Z",
"createdAt": "2025-10-19T10:50:07Z"
},
"fieldValues": {
"nodes": [
{
"__typename": "ProjectV2ItemFieldTextValue",
"text": "DraftIssue created for test ",
"field": {
"__typename": "ProjectV2Field",
"id": "PVTF_lADOAlIw4c4BCe3Vzg0rg-M",
"name": "Title",
"dataType": "TITLE"
}
}
]
}
}
}
}
}
25 changes: 25 additions & 0 deletions Test/public/items/project_item_draftissue.test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function Test_NewProjectDraftIssue {

Reset-InvokeCommandMock
Mock_DatabaseRoot

$p = Get-Mock_Project_700 ; $owner = $p.owner ; $projectNumber = $p.number
MockCall_GetProject -MockProject $p

$title = "DraftIssue created for test "
$body = "Body of draftissue"

MockCallJson -Command "Invoke-CreateDraftItem -ProjectId $($p.id) -Title ""$title"" -Body ""$body""" -FileName "invoke-createDraftItem.json"

# Act
$draftIssueId = New-ProjectDraftIssue -Owner $owner -ProjectNumber $projectNumber -Title $title -Body $body


$item = Get-ProjectItem -ItemId $draftIssueId

# Assert
Assert-AreEqual -Expected $draftIssueId -Presented $item.id
Assert-AreEqual -Expected $title -Presented $item.Title
Assert-AreEqual -Expected $body -Presented $item.Body

}
46 changes: 43 additions & 3 deletions public/driver/driver_gh.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -499,16 +499,56 @@ function Get-GraphQLString{

Write-MyDebug -section "driver_gh" -message "Getting GraphQL string from file: $FileName"

$path = getmockfilepath -FileName $FileName

$content = get-content -path $path | Out-String

$content = Expand-GraphQLString -GraphQLString $content

return $content
}

function getmockfilepath{
param(
[Parameter(Mandatory, Position = 0)] [string]$FileName
)

$local = $PSScriptRoot
$public = $local | Split-Path -Parent

$path = $public | Join-Path -ChildPath "graphql" -AdditionalChildPath $FileName

# Verify that the file exists
if(! (Test-Path -Path $path)){
throw "GraphQL file not found at path: $path"
}

$content = get-content -path $path | Out-String
return $path
}

return $content
}
function Expand-GraphQLString{
param(
[Parameter(Mandatory, Position = 0)] [string]$GraphQLString
)

$tags = [regex]::Matches($GraphQLString,'\{\{(\w+)\}\}') | ForEach-Object { $_.Groups[1].Value }

# If no tags found, return the original string
if($tags.Count -eq 0){
return $GraphQLString
}

$content = $GraphQLString

foreach($tag in $tags){
$path = getmockfilepath -FileName "_$tag.tag"
$tagContent = Get-Content -Path $path | Out-String

$content = $content -replace "\{\{$tag\}\}", $tagContent
}

# loop back to expand nested tags
$ret = Expand-GraphQLString -GraphQLString $content

return $ret
}
52 changes: 52 additions & 0 deletions public/driver/issue/Invoke-CreateDraftItem.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
function Invoke-CreateDraftItem{

Check notice

Code scanning / PSScriptAnalyzer

The cmdlet 'Invoke-CreateDraftItem' does not have a help comment. Note

The cmdlet 'Invoke-CreateDraftItem' does not have a help comment.
param(
[Parameter(Mandatory=$true)] [string]$ProjectId,
[Parameter(Mandatory=$true)] [string]$Title,
[Parameter(Mandatory=$false)] [string]$Body
)

# Use the environmentraviable
$token = Get-GithubToken
if(-not $token){
throw "GH Cli Auth Token not available. Run 'gh auth login' in your terminal."
}

# Define the GraphQL query with variables
$mutation = Get-GraphQLString "createDraftItem.mutant"

# Define the headers for the request
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}

# Define the variables for the request
$variables = @{
input = @{
projectId = $ProjectId
title = $Title
body = $Body
}
}

# Define the body for the request
$body = @{
query= $mutation
variables = $variables
} | ConvertTo-Json -Depth 10

# Send the request
$response = Invoke-RestMethod -Uri 'https://api.github.com/graphql' -Method Post -Body $body -Headers $headers

# Check if here are errors
if($response.errors){
$response.errors | ForEach-Object {
getErrrorString -Errors $response.errors | Write-MyError
}
return $null
}

# Return the field names
return $response

} Export-ModuleMember -Function Invoke-CreateDraftItem
102 changes: 102 additions & 0 deletions public/graphql/_projectv2item.tag
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
id, type, fullDatabaseId,
project{ id, url},
content{__typename,
... on DraftIssue {id,body,title,updatedAt,createdAt},
... on PullRequest{id,body,title,updatedAt,createdAt,number,url,state,repository{name,owner{login}}
comments(last: $lastComments){
totalCount,
nodes{createdAt,updatedAt,url,body,fullDatabaseId,author{login}}
}
},
... on Issue{id,body,title,updatedAt,createdAt,number,url,state,repository{name,owner{login}}
comments(last: $lastComments){
totalCount,
nodes{createdAt,updatedAt,url,body,fullDatabaseId,author{login}}
}
}
},
fieldValues(first: 100){
nodes{__typename,
... on ProjectV2ItemFieldDateValue{date,field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldIterationValue{title,startDate,duration,field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldLabelValue{labels(first: 10){nodes{name
}
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldNumberValue{number,field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldSingleSelectValue{name,field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldTextValue{text,field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldMilestoneValue{milestone{title,description,dueOn
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldPullRequestValue{pullRequests(first: 10){nodes{url
}
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldRepositoryValue{repository{url
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldUserValue{users(first: 10){nodes{login
}
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
},... on ProjectV2ItemFieldReviewerValue{reviewers(first: 10){nodes{__typename,... on Team{name
},... on User{login
}
}
},field{__typename,... on ProjectV2Field{id,name,dataType
},... on ProjectV2IterationField{id,name,dataType
},... on ProjectV2SingleSelectField{id,name,dataType,options{id,name
}
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions public/graphql/createDraftItem.mutant
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mutation CreateDraftItem($input:AddProjectV2DraftIssueInput! $lastComments: Int=5 ){
addProjectV2DraftIssue(input:$input){
projectItem {{projectv2item}}
}
}
54 changes: 54 additions & 0 deletions public/items/project_item_draftissue.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

Set-MyInvokeCommandAlias -Alias createDraftItem -Command 'Invoke-CreateDraftItem -ProjectId {projectid} -Title "{title}" -Body "{body}"'


function New-ProjectDraftIssue {

Check notice

Code scanning / PSScriptAnalyzer

The cmdlet 'New-ProjectDraftIssue' does not have a help comment. Note

The cmdlet 'New-ProjectDraftIssue' does not have a help comment.

Check warning

Code scanning / PSScriptAnalyzer

Function 'New-ProjectDraftIssue' has verb that could change system state. Therefore, the function has to support 'ShouldProcess'. Warning

Function 'New-ProjectDraftIssue' has verb that could change system state. Therefore, the function has to support 'ShouldProcess'.
[CmdletBinding()]
param (
[Parameter()][string]$Owner,
[Parameter()][string] $ProjectNumber,
[Parameter(Mandatory,Position=0)][string]$Title,
[Parameter(Position=1)][string]$Body,
[Parameter()][switch]$NoCache,
[Parameter()][switch]$OpenOnCreation

Check warning

Code scanning / PSScriptAnalyzer

The parameter 'OpenOnCreation' has been declared but not used. Warning

The parameter 'OpenOnCreation' has been declared but not used.
)

($Owner, $ProjectNumber) = Get-OwnerAndProjectNumber -Owner $Owner -ProjectNumber $ProjectNumber

$db = Get-Project -Owner $Owner -ProjectNumber $ProjectNumber

$params = @{
title = $Title | ConvertTo-InvokeParameterString
body = $Body | ConvertTo-InvokeParameterString
projectid = $db.ProjectId
}

$params | ConvertTo-Json | Write-Verbose

$response = Invoke-MyCommand -Command "createDraftItem" -Parameters $params

$item = $response.data.addProjectV2DraftIssue.projectItem

if ($item) {
$ret = $item.id

if (! $NoCache) {
"Adding item [$ret] to cache" | Write-Verbose

$item = $item | Convert-NodeItemToHash

Set-Item $db $item

Save-ProjectDatabaseSafe -Database $db

}

return $ret

}
else {
"Item not added to project" | Write-MyError
return $null
}

} Export-ModuleMember -Function New-ProjectDraftIssue