diff --git a/scripts/_change_state.ps1 b/scripts/_change_state.ps1 new file mode 100644 index 00000000..cbe1ff53 --- /dev/null +++ b/scripts/_change_state.ps1 @@ -0,0 +1,196 @@ +param ( + [int]$IssueId, + [string]$oldColumnName, + [string]$newColumnName, + [bool]$doNotCheckOldColumnName = 0, + [string]$repoOwner = "Inxton", + [string]$repoName = "axsharp", + [string]$projectName = "simatic-ax" +) + +gh issue list --assignee "@me" --state "open" +$issues = gh issue list --state "open" --assignee "@me" --json number,title | ConvertFrom-Json +$issueIDs = $issues | ForEach-Object { $_.number } +if (-not $IssueId) +{ + $IssueId = Read-Host "Please enter an ID value of the issue" +} + +# Fetch project IDs using GraphQL +$projectIds = gh api graphql -f query=' +query($repoOwner: String!, $repoName: String!) { + repository(owner: $repoOwner, name: $repoName) { + projectsV2(first: 10) { + nodes { + id + title + } + } + } +}' -f repoOwner=$repoOwner -F repoName=$repoName + +$projectId = ($projectIds | ConvertFrom-Json).data.repository.projectsV2.nodes | Where-Object { $_.title -eq $projectName } | Select-Object -ExpandProperty id + +$projectOptions = gh api graphql -f query=' +query($projectId: ID!) { + node(id: $projectId) { + ... on ProjectV2 { + fields(first: 20) { + nodes { + ... on ProjectV2SingleSelectField { + id + name + options { + id + name + } + } + } + } + } + } +}' -f projectId=$projectId | ConvertFrom-Json + +$projectColumns = $projectOptions.data.node.fields.nodes | Where-Object { $_.name -eq 'Status'} +$projectColumnId =$projectColumns.id +if(-not $projectColumnId) +{ + Write-Output "Error: No 'Status' field defined in project ID $projectId (name: $projectName)." + exit 1 +} + +$oldColumn = $projectColumns.options | Where-Object { $_.name -eq $oldColumnName} +if (-not $oldColumn) { + Write-Output "Error: No state '$oldColumnName' defined in project ID $projectId (name: $projectName)." + exit 1 +} +$oldColumnId = $oldColumn.id + +$newColumn = $projectColumns.options | Where-Object { $_.name -eq $newColumnName} +if (-not $newColumn) { + Write-Output "Error: No state '$newColumnName' defined in project ID $projectId (name: $projectName)." + exit 1 +} +$newColumnId = $newColumn.id + +Write-Output "Fetching all items from project: $projectId (name: $projectName)." +# Initialize variables +$hasNextPage = $true +$endCursor = $null +$allItems = @() +$pageNumber = 1 +$itemsCount = 0 + +# Loop through pages +while ($hasNextPage) { + Write-Output "Fetching a page #$pageNumber of items..." + # Execute GraphQL query with pagination + $result = gh api graphql -f query=' + query($projectId: ID!, $cursor: String) { + node(id: $projectId) { + ... on ProjectV2 { + items(first: 100, after: $cursor) { + nodes { + id + fieldValues(first: 10) { + nodes{ + ... on ProjectV2ItemFieldSingleSelectValue { + name + field { + ... on ProjectV2FieldCommon { + name + } + } + } + } + } + content { + ... on Issue { + number + } + } + } + pageInfo { + endCursor + hasNextPage + } + } + } + } + }' -F projectId=$projectId -F cursor=$endCursor -F fieldId=$projectColumnId | ConvertFrom-Json + + # Append fetched items to $allItems + $allItems += $result.data.node.items.nodes + $pageNumber = $pageNumber + 1 + $itemsCount = $itemsCount + $allItems.Count + # Update pagination variables + $endCursor = $result.data.node.items.pageInfo.endCursor + $hasNextPage = $result.data.node.items.pageInfo.hasNextPage + Write-Output "Fetched #$itemsCount items..." +} + +# Output all items +Write-Output "Fetched all items: #$itemsCount" + +Write-Output "Fetching project cards for issue #$IssueId in the '$oldColumnName' column" +# Find the card associated with the issue +$issueCard = $allItems | Where-Object { $_.content.number -eq $IssueId } +if (-not $issueCard) { + Write-Output "Error: No project card found for issue #$IssueId in project ID $projectId (name: $projectName)." + exit 1 +} + +# Discover the 'Status' field value +$fieldValues = $issueCard.fieldValues.nodes +$issueCardHasStatusField = 0 +$issueCardIsInOldColumnName = "" +foreach ($fieldValue in $fieldValues ) +{ + if ($fieldValue.field.name -eq "Status") + { + $issueCardHasStatusField = 1 + $issueCardIsInOldColumnName = $fieldValue.name + break + } +} + +if ($issueCardHasStatusField -eq 0) +{ + Write-Output "Warning: The issue #$IssueId in project ID $projectId (name: $projectName) does not have a defined 'Status' value. Proceeding without 'Status' verification." +} + +if ($issueCardIsInOldColumnName -ne $oldColumnName) +{ + if($doNotCheckOldColumnName -eq 0) + { + Write-Output "Error: The issue #$IssueId in project ID $projectId (name: $projectName) cannot be moved from '$oldColumnName' to '$newColumnName' as it is in '$issueCardIsInOldColumnName'." + exit 1 + } + Write-Output "Moving issue #$IssueId to '$newColumnName' in project ID $projectId (name: $projectName)." +} +else +{ + Write-Output "Moving issue #$IssueId from '$oldColumnName' to '$newColumnName' in project ID $projectId (name: $projectName)." +} + + +$cardId = $issueCard.id + +# Move the issue card to $newColumnName +gh api graphql -f query=' +mutation($projectId: ID!, $cardId: ID!, $projectColumnId: ID!, $newColumnId: String!) { + updateProjectV2ItemFieldValue( + input: { + projectId: $projectId + itemId: $cardId + fieldId: $projectColumnId + value: { + singleSelectOptionId: $newColumnId + } + } + ) { + projectV2Item { + id + } + } +}' -F projectId=$projectId -F cardId=$cardId -F projectColumnId=$projectColumnId -F newColumnId=$newColumnId diff --git a/scripts/_create_issue_branch.ps1 b/scripts/_create_issue_branch.ps1 index 6dc8c1fc..eb5ef1b0 100644 --- a/scripts/_create_issue_branch.ps1 +++ b/scripts/_create_issue_branch.ps1 @@ -1,5 +1,22 @@ param ( - [int]$IssueId ) + [int]$IssueId , + [bool]$doNotCheckOldColumnName = 0 +) + +# Get the current script directory +$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +# Construct the full path to _is_on_dev_nothing_to_commit.ps1 +$_is_on_dev_nothing_to_commit = Join-Path -Path $scriptDir -ChildPath "_is_on_dev_nothing_to_commit.ps1" + +# Call _is_on_dev_nothing_to_commit.ps1 +$is_on_dev_nothing_to_commit = & $_is_on_dev_nothing_to_commit +if(-not $is_on_dev_nothing_to_commit) +{ + Write-Host "You are not currently on the 'dev' branch, or you have some uncommited changes " -ForegroundColor Red + Write-Host "Commit your local changes, sync your local 'dev' branch with the remote and start this script again." -ForegroundColor Red + exit 1 +} + gh issue list --assignee "@me" --state "open" $issues = gh issue list --state "open" --assignee "@me" --json number,title | ConvertFrom-Json @@ -16,42 +33,48 @@ if ([int]::TryParse($IssueId, [ref]$null)) # Check if any of the open issue IDs assigned to @me is equal to entered value if ($issueIDs -contains [int]$IssueId) { - # Get selected issue id and issue title + # Get selected issue id ,issue title and issue label $selectedIssue = $issues | Where-Object { $_.number -eq [int]$IssueId } $selectedIssueNumber = $selectedIssue.number $selectedIssueTitle = $selectedIssue.title - # Checkout dev - Write-Output "Checkout to dev" - git checkout dev + $currentLabels = $selectedIssue.labels | ForEach-Object { $_.name } + # Create branch for the selected issue + Write-Output "Creating branch for the issue number: '$selectedIssueNumber', title: '$selectedIssueTitle'" + gh issue develop $IssueId --base dev --checkout $currentBranch = git branch --show-current - if($currentBranch -eq "dev") + if ($currentBranch -match "^(\d+)-") { - # Get remote changes, if any - git pull - # Create branch for the selected issue - Write-Output "Creating branch for the issue number: '$selectedIssueNumber', title: '$selectedIssueTitle'" - gh issue develop $IssueId --base dev --checkout - # Add all changes - git add . - # Commit all changes - git commit --allow-empty -m "Create draft PR for #$selectedIssueNumber" - # Write changes to remote - Write-Output "Pushing the branch to remote" - git push -u origin $(git branch --show-current) - # Create draft PR - Write-Output "Creating a draft pull request into 'dev'" - gh pr create --base dev --head $(git branch --show-current) --title "$selectedIssueTitle" --body "closes #$selectedIssueNumber" --draft - # Sync - git push - Write-Output "Sync local and remote branches" - git pull origin $(git branch --show-current) - git push - } else + $currentBranchIssueId = $matches[1] + } + else + { + $currentBranchIssueId = $null + } + if(-not $currentBranchIssueId -or $currentBranchIssueId -ne $IssueId) { - Write-Output "Unable to checkout to dev" - Write-Output "Commit your local changes, sync your local 'dev' branch with th remote and start this script again." + Write-Host "Unable to create the new brach for an issue: $IssueId" -ForegroundColor Red exit 1 } + Write-Host "Branch '$currentBranch' for the issue number: '$selectedIssueNumber', title: '$selectedIssueTitle' has been succesfully created." -ForegroundColor Green + # Add all changes + git add . + # Commit all changes + git commit --allow-empty -m "Create draft PR for #$selectedIssueNumber" + # Write changes to remote + Write-Output "Pushing the branch to remote" + git push -u origin $currentBranch + # Create draft PR + Write-Output "Creating a draft pull request into 'dev'" + gh pr create --base dev --head $currentBranch --title "$selectedIssueTitle" --body "closes #$selectedIssueNumber" --draft + # Sync + git push + Write-Output "Sync local and remote branches" + git pull origin $currentBranch + git push + # Construct the full path to _change_stateScriptPath.ps1 + $_change_stateScriptPath = Join-Path -Path $scriptDir -ChildPath "_change_state.ps1" + # Call _change_state.ps1 with the parameters IssueId, oldColumnName, newColumnName,doNotCheckOldColumnName, repoOwner, repoName, projectName + & $_change_stateScriptPath -IssueId $issueID -oldColumnName "Ready" -newColumnName "In progress" -doNotCheckOldColumnName $doNotCheckOldColumnName -repoOwner "Inxton" -repoName "axsharp" -projectName "simatic-ax" } else { Write-Output "Error: The issue ID '$IssueId' does not exist in the list of open issues." diff --git a/scripts/_is_on_dev_nothing_to_commit.ps1 b/scripts/_is_on_dev_nothing_to_commit.ps1 new file mode 100644 index 00000000..d632d938 --- /dev/null +++ b/scripts/_is_on_dev_nothing_to_commit.ps1 @@ -0,0 +1,27 @@ +$currentBranch = git branch --show-current +if($currentBranch -ne "dev") +{ + Write-Output "You are not currently on the 'dev' branch." + Write-Host "You are not currently on the 'dev' branch, but $currentBranch " -ForegroundColor Red + return $false +} +else +{ + Write-Host "You are currently on the 'dev' branch" -ForegroundColor Green +} +$isClean =$false +$status = git status +foreach ($statusLine in $status ) +{ + if ($statusLine -eq "nothing to commit, working tree clean") + { + $isClean = $true + Write-Host "Nothing to commit, working tree clean" -ForegroundColor Green + break + } +} +if(-not $isClean) +{ + Write-Host "You have some uncommited changes on the 'dev' branch" -ForegroundColor Red +} +return $isClean \ No newline at end of file diff --git a/scripts/commit_and_ready_for_review.ps1 b/scripts/commit_and_ready_for_review.ps1 index 3c7e6d97..ce6fb78d 100644 --- a/scripts/commit_and_ready_for_review.ps1 +++ b/scripts/commit_and_ready_for_review.ps1 @@ -6,11 +6,14 @@ else { $commitMessage = $args[0] } +# Get the current script directory +$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +$parentDir = Resolve-Path -Path "$scriptDir\.." +# without this probably just the content of the script folder is added to the commit +cd $parentDir git add . git commit -m "$commitMessage" git push -# Get the current script directory -$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent # Construct the full path to ready_for_review.ps1 $ready_for_reviewScriptPath = Join-Path -Path $scriptDir -ChildPath "ready_for_review.ps1" & $ready_for_reviewScriptPath diff --git a/scripts/create_new_issue.ps1 b/scripts/create_new_issue.ps1 index 4e818119..afc1522a 100644 --- a/scripts/create_new_issue.ps1 +++ b/scripts/create_new_issue.ps1 @@ -1,11 +1,30 @@ param ( - [Parameter(Mandatory=$true)] [string]$IssueTitle, - [Parameter(Mandatory=$true)] [string]$IssueBody ) +if (-not $IssueTitle) +{ + $IssueTitle = Read-Host "Please enter an issue title." +} +if (-not $IssueBody) +{ + $IssueBody = Read-Host "Please enter an issue body." +} + + +if (-not $IssueTitle) +{ + Write-Output "Issue title cannot be an empty string!" + exit 1 +} +if (-not $IssueBody) +{ + $IssueBody = " " +} + + $issue = gh issue create --assignee "@me" --title "$IssueTitle" --body "$IssueBody" --project simatic-ax if ($issue -match ".*/(\d+)$") { @@ -14,11 +33,11 @@ if ($issue -match ".*/(\d+)$") { # Get the current script directory $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent - # Construct the full path to SecondScript.ps1 - $create_issue_branchScriptPath = Join-Path -Path $scriptDir -ChildPath "_create_issue_branch.ps1" + # Construct the full path to _create_issue_branch.ps1 + $_create_issue_branchScriptPath = Join-Path -Path $scriptDir -ChildPath "_create_issue_branch.ps1" - # Call create_issue_branch.ps1 with the parameter IssueId - & $create_issue_branchScriptPath -IssueId $issueID + # Call _create_issue_branch.ps1 with the parameter IssueId and doNotCheckOldColumnName + & $_create_issue_branchScriptPath -IssueId $issueID -doNotCheckOldColumnName $True } else { Write-Output "No numeric ID found for this issue." } diff --git a/scripts/ready_for_review.ps1 b/scripts/ready_for_review.ps1 new file mode 100644 index 00000000..e196cbe8 --- /dev/null +++ b/scripts/ready_for_review.ps1 @@ -0,0 +1,81 @@ +$gitStatus = git status +if($gitStatus -notcontains "nothing to commit, working tree clean") +{ + Write-Output "Working tree is not clean. Commit and push your local changes and run this script again afterwards." +} +else +{ + # Get current branch name + $currentBranch = $(git branch --show-current) + Write-Output "Working tree is clean. Marking '$currentBranch' as ready for review" + # Extract the issue number (assuming "issue-" or "/-description" format) + if ($currentBranch -match "\d+") + { + $issueID = $matches[0] + Write-Output "issueID: $issueID" + # Get the current script directory + $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent + # Construct the full path to _change_stateScriptPath.ps1 + $_change_stateScriptPath = Join-Path -Path $scriptDir -ChildPath "_change_state.ps1" + # Call _change_state.ps1 with the parameters IssueId, oldColumnName, newColumnName,doNotCheckOldColumnName, repoOwner, repoName, projectName + & $_change_stateScriptPath -IssueId $issueID -oldColumnName "In progress" -newColumnName "In review" -doNotCheckOldColumnName $False -repoOwner "Inxton" -repoName "axsharp" -projectName "simatic-ax" + } + else + { + Write-Output "No issue number found in the branch name. Unable to move the issue to 'In review'" + } + + # Get the list of pull requests + $pullRequests = gh pr list --state open --json number,headRefName | ConvertFrom-Json + if (-not $pullRequests) { + Write-Error "No open pull requests found or an error occurred while retrieving them." + exit 1 + } + # Find the pull request matching the current branch + $pullRequest = $pullRequests | Where-Object { $_.headRefName -eq $currentBranch } + if (-not $pullRequest) + { + Write-Output "No pull request found for the current branch ($currentBranch)." + exit 1 + } + $pullRequestNumber = $pullRequest.number + Write-Output "Pull Request Number: $($pullRequestNumber)" + # Assign it to me + gh pr edit $pullRequestNumber --add-assignee "@me" + Write-Host "Please enter the additional reviewers names: i.e.: my_boss_github_name, his_boss_github_name, etc. (upto the galaxy owner)" + Write-Host "If environment variable 'GH_REVIEWERS' exists, these names will be added, otherwise these names will be used as the only reviewers" + $AdditionalReviewers = Read-Host "For empty press enter." + $ReviewComment = Read-Host "Please enter a comment for the reviewers, for empty press enter" + Write-Output "currentBranch: $currentBranch" + if ($Env:GH_REVIEWERS -ne $null) + { + if (-not $AdditionalReviewers) + { + $Reviewers = $Env:GH_REVIEWERS + } + else + { + $Reviewers = $Env:GH_REVIEWERS + "," + $AdditionalReviewers + } + } + else + { + $Reviewers = $AdditionalReviewers + } + if (-not $Reviewers) + { + Write-Error "No reviewers defined." + exit 1 + } + Write-Output "Reviewers: $Reviewers" + $ReviewersArray = $Reviewers -split "," | ForEach-Object { $_.Trim() } + $ReviewersString = $ReviewersArray -join "," + $Command = "gh pr edit --add-reviewer " + $ReviewersString + Invoke-Expression $Command + if ($ReviewComment -ne "") { + $Command = "gh pr comment $pullRequestNumber -b """ + $ReviewComment + """" + Invoke-Expression $Command + } + gh pr ready $pullRequestNumber +} + diff --git a/src/AXSharp.compiler/src/ixc/Program.cs b/src/AXSharp.compiler/src/ixc/Program.cs index 984708ab..c02340cd 100644 --- a/src/AXSharp.compiler/src/ixc/Program.cs +++ b/src/AXSharp.compiler/src/ixc/Program.cs @@ -41,11 +41,11 @@ public static void Main(string[] args) { var recoverCurrentDirectory = Environment.CurrentDirectory; try - { + { Log.ConfigureLogger(o.Versbosity); Log.Logger.Verbose(JsonSerializer.Serialize(o)); - + Project = GenerateIxProject(o); } catch (Exception e) @@ -76,7 +76,7 @@ private static string GetFullPath(string path) } private static AXSharpProject GenerateIxProject(Options options) - { + { var axProjectFolder = string.IsNullOrEmpty(options.AxSourceProjectFolder) ? Environment.CurrentDirectory : options.AxSourceProjectFolder; @@ -109,7 +109,7 @@ private static void DisplayInfo() "THIRD PARTY LICENSES CAN BE FOUND AT \n" + "https://github.com/inxton/axsharp/blob/master/notices.md"); - + Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine($"Using version '{LegalAcrobatics.StcVersion}' of stc."); Console.ForegroundColor = originalColor;