@babajide234/git-merge-workflow 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/npm-publish-github-packages.yml +36 -0
- package/.github/workflows/publish.yml +34 -0
- package/DEVELOPER_GUIDE.md +96 -0
- package/GitMergeWorkflow.psd1 +18 -0
- package/GitMergeWorkflow.psm1 +343 -0
- package/Install.ps1 +31 -0
- package/PUBLISHING.md +41 -0
- package/README.md +112 -0
- package/bin/cli.js +30 -0
- package/package.json +29 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
+
|
|
4
|
+
name: Node.js Package
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [created]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: 20
|
|
18
|
+
- run: npm ci
|
|
19
|
+
- run: npm test
|
|
20
|
+
|
|
21
|
+
publish-gpr:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
packages: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: 20
|
|
32
|
+
registry-url: https://npm.pkg.github.com/
|
|
33
|
+
- run: npm ci
|
|
34
|
+
- run: npm publish
|
|
35
|
+
env:
|
|
36
|
+
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Publish PowerShell Module
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish-to-gallery:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v3
|
|
13
|
+
|
|
14
|
+
- name: Build and Publish
|
|
15
|
+
env:
|
|
16
|
+
NUGET_KEY: ${{ secrets.NUGET_KEY }}
|
|
17
|
+
shell: pwsh
|
|
18
|
+
run: |
|
|
19
|
+
Publish-Module -Path . -NuGetApiKey $env:NUGET_KEY -Verbose
|
|
20
|
+
|
|
21
|
+
publish-to-npm:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
needs: publish-to-gallery
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v3
|
|
26
|
+
- uses: actions/setup-node@v3
|
|
27
|
+
with:
|
|
28
|
+
node-version: '16.x'
|
|
29
|
+
registry-url: 'https://registry.npmjs.org'
|
|
30
|
+
|
|
31
|
+
- run: npm install
|
|
32
|
+
- run: npm publish --access public
|
|
33
|
+
env:
|
|
34
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Developer Guide: Git Merge Workflow (GMW)
|
|
2
|
+
|
|
3
|
+
This guide explains how the **Git Merge Workflow** PowerShell module works and how you can modify it.
|
|
4
|
+
|
|
5
|
+
## 📂 Project Structure
|
|
6
|
+
|
|
7
|
+
The module is located at:
|
|
8
|
+
`c:\Users\jyde2\OneDrive\Documents\WindowsPowerShell\Modules\GitMergeWorkflow`
|
|
9
|
+
|
|
10
|
+
- **GitMergeWorkflow.psd1**: The *Module Manifest*. Contains metadata (version, author, description) and defines which files are processed when the module is imported.
|
|
11
|
+
- **GitMergeWorkflow.psm1**: The *Script Module*. Contains the actual source code and logic for the functions. **This is where you will make most changes.**
|
|
12
|
+
- **Install.ps1**: A helper script to install the module on a new machine.
|
|
13
|
+
- **package.json**: configuration for NPM publishing (if applicable).
|
|
14
|
+
|
|
15
|
+
## 🧠 How It Works
|
|
16
|
+
|
|
17
|
+
The core logic resides in `GitMergeWorkflow.psm1`.
|
|
18
|
+
|
|
19
|
+
### Main Function: `Invoke-GitMergeWorkflow`
|
|
20
|
+
This is the function executed when you run `gmw`.
|
|
21
|
+
|
|
22
|
+
1. **Configuration Loading**:
|
|
23
|
+
- Calls `Get-GitWorkflowConfig` to look for a `.git-merge-workflow.json` file in your repository root.
|
|
24
|
+
- Sets defaults (`develop` for target, `-staging` for suffix) if no config is found.
|
|
25
|
+
|
|
26
|
+
2. **Environment Checks**:
|
|
27
|
+
- Checks if `git` is available and if the current directory is a git repository.
|
|
28
|
+
- Validates that you are NOT currently on the target branch (e.g., `develop`) or the staging branch.
|
|
29
|
+
|
|
30
|
+
3. **Staging Phase**:
|
|
31
|
+
- Determines the staging branch name (e.g., `feature-xyz-staging`).
|
|
32
|
+
- Checks if the staging branch exists locally or remotely.
|
|
33
|
+
- **Merges** your current feature branch into this staging branch.
|
|
34
|
+
- **Pushes** the staging branch to the remote (`origin`).
|
|
35
|
+
- *Recent Update*: This step now includes error handling. If the push fails (e.g., permissions issue), it asks if you want to skip and proceed.
|
|
36
|
+
|
|
37
|
+
4. **Target Phase**:
|
|
38
|
+
- Checkouts the target branch (`develop`).
|
|
39
|
+
- Pulls the latest changes.
|
|
40
|
+
- **Merges** the staging branch into the target branch.
|
|
41
|
+
- **Pushes** the target branch to remote.
|
|
42
|
+
|
|
43
|
+
5. **Cleanup**:
|
|
44
|
+
- Returns you to your original feature branch.
|
|
45
|
+
|
|
46
|
+
### Helper Functions
|
|
47
|
+
- `Exec-Git`: A wrapper around git commands to handle errors and verbose output consistently.
|
|
48
|
+
- `New-GitWorkflowConfig`: Generates the JSON configuration file.
|
|
49
|
+
|
|
50
|
+
## 🛠️ How to Edit and Test
|
|
51
|
+
|
|
52
|
+
Since this is a PowerShell module, changes are not picked up immediately if the module is already loaded in your session.
|
|
53
|
+
|
|
54
|
+
### 1. Edit the Code
|
|
55
|
+
Open `GitMergeWorkflow.psm1` in VS Code or your preferred editor.
|
|
56
|
+
|
|
57
|
+
**Example**: Adding a new log message.
|
|
58
|
+
```powershell
|
|
59
|
+
# Inside Invoke-GitMergeWorkflow
|
|
60
|
+
Write-Host "Starting my custom workflow..." -ForegroundColor Magenta
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Reload the Module
|
|
64
|
+
After saving your changes, you must reload the module in your PowerShell terminal to see them take effect.
|
|
65
|
+
|
|
66
|
+
Run this command:
|
|
67
|
+
```powershell
|
|
68
|
+
Import-Module GitMergeWorkflow -Force
|
|
69
|
+
```
|
|
70
|
+
*The `-Force` flag is crucial as it unloads the old version and loads the new one.*
|
|
71
|
+
|
|
72
|
+
### 3. Test
|
|
73
|
+
Run the command again:
|
|
74
|
+
```powershell
|
|
75
|
+
gmw -WhatIf
|
|
76
|
+
```
|
|
77
|
+
*Using `-WhatIf` (Dry Run) is a safe way to test logic changes without actually running git commands, provided the script supports it (mostly used for ShouldProcess).*
|
|
78
|
+
|
|
79
|
+
For real testing, just run `gmw` in a test repository.
|
|
80
|
+
|
|
81
|
+
## 📦 Configuration
|
|
82
|
+
|
|
83
|
+
The behavior can be customized per-repository using a `.git-merge-workflow.json` file:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"TargetBranch": "main",
|
|
88
|
+
"StagingSuffix": "-qa",
|
|
89
|
+
"Remote": "upstream"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
You can generate this file using:
|
|
94
|
+
```powershell
|
|
95
|
+
New-GitWorkflowConfig
|
|
96
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
@{
|
|
2
|
+
RootModule = 'GitMergeWorkflow.psm1'
|
|
3
|
+
ModuleVersion = '1.0.0'
|
|
4
|
+
GUID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
|
5
|
+
Author = 'babajide Tomoshegbo'
|
|
6
|
+
CompanyName = 'babajide234'
|
|
7
|
+
Copyright = '(c) 2025 Expedier. All rights reserved.'
|
|
8
|
+
Description = 'Automated Git workflow for merging feature branches through staging to develop'
|
|
9
|
+
PowerShellVersion = '5.1'
|
|
10
|
+
FunctionsToExport = @('Invoke-GitMergeWorkflow', 'New-GitWorkflowConfig', 'Get-GitWorkflowConfig')
|
|
11
|
+
AliasesToExport = @('git-merge-workflow', 'gmw')
|
|
12
|
+
PrivateData = @{
|
|
13
|
+
PSData = @{
|
|
14
|
+
Tags = @('Git', 'Workflow', 'Automation', 'Merge', 'DevOps')
|
|
15
|
+
ProjectUri = 'https://github.com/babajide234/GitMergeWorkflow'
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
|
|
2
|
+
function Get-GitWorkflowConfig {
|
|
3
|
+
<#
|
|
4
|
+
.SYNOPSIS
|
|
5
|
+
Retrieves the Git Merge Workflow configuration from the current repository
|
|
6
|
+
.DESCRIPTION
|
|
7
|
+
Looks for a .git-merge-workflow.json file in the root of the git repository.
|
|
8
|
+
If found, parses and returns the configuration.
|
|
9
|
+
If not found, returns null.
|
|
10
|
+
#>
|
|
11
|
+
[CmdletBinding()]
|
|
12
|
+
param()
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
# Get git root
|
|
16
|
+
$gitRoot = git rev-parse --show-toplevel 2>$null
|
|
17
|
+
if ($LASTEXITCODE -eq 0 -and $gitRoot) {
|
|
18
|
+
$configPath = Join-Path $gitRoot ".git-merge-workflow.json"
|
|
19
|
+
if (Test-Path $configPath) {
|
|
20
|
+
return Get-Content $configPath -Raw | ConvertFrom-Json
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
} catch {
|
|
24
|
+
Write-Verbose "Error reading config: $_"
|
|
25
|
+
}
|
|
26
|
+
return $null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function New-GitWorkflowConfig {
|
|
30
|
+
<#
|
|
31
|
+
.SYNOPSIS
|
|
32
|
+
Creates a new configuration file for the Git Merge Workflow
|
|
33
|
+
.DESCRIPTION
|
|
34
|
+
Creates a .git-merge-workflow.json file in the root of the current git repository.
|
|
35
|
+
.PARAMETER TargetBranch
|
|
36
|
+
The default target branch (default: develop)
|
|
37
|
+
.PARAMETER StagingSuffix
|
|
38
|
+
The suffix for staging branches (default: -staging)
|
|
39
|
+
.PARAMETER Remote
|
|
40
|
+
The default remote name (default: origin)
|
|
41
|
+
.EXAMPLE
|
|
42
|
+
New-GitWorkflowConfig -TargetBranch "main" -StagingSuffix "-test"
|
|
43
|
+
#>
|
|
44
|
+
[CmdletBinding(SupportsShouldProcess=$true)]
|
|
45
|
+
param(
|
|
46
|
+
[string]$TargetBranch = "develop",
|
|
47
|
+
[string]$StagingSuffix = "-staging",
|
|
48
|
+
[string]$Remote = "origin"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Check if in git repo
|
|
52
|
+
$gitRoot = git rev-parse --show-toplevel 2>$null
|
|
53
|
+
if ($LASTEXITCODE -ne 0 -or -not $gitRoot) {
|
|
54
|
+
Write-Error "Not in a git repository. Please run inside a git repository."
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
$configPath = Join-Path $gitRoot ".git-merge-workflow.json"
|
|
59
|
+
|
|
60
|
+
$config = @{
|
|
61
|
+
TargetBranch = $TargetBranch
|
|
62
|
+
StagingSuffix = $StagingSuffix
|
|
63
|
+
Remote = $Remote
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
$json = $config | ConvertTo-Json -Depth 2
|
|
67
|
+
|
|
68
|
+
if ($PSCmdlet.ShouldProcess($configPath, "Create configuration file")) {
|
|
69
|
+
$json | Set-Content $configPath
|
|
70
|
+
Write-Host "Configuration file created at: $configPath" -ForegroundColor Green
|
|
71
|
+
Write-Host "Content:" -ForegroundColor Cyan
|
|
72
|
+
Write-Host $json
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function Invoke-GitMergeWorkflow {
|
|
77
|
+
<#
|
|
78
|
+
.SYNOPSIS
|
|
79
|
+
Automated Git workflow to merge current branch to staging and then to develop
|
|
80
|
+
.DESCRIPTION
|
|
81
|
+
This function automates the process of:
|
|
82
|
+
1. Getting the current branch name
|
|
83
|
+
2. Merging current branch to {branch}-staging
|
|
84
|
+
3. Merging {branch}-staging to develop
|
|
85
|
+
4. Pushing all changes
|
|
86
|
+
|
|
87
|
+
Configuration can be stored in .git-merge-workflow.json in the repository root.
|
|
88
|
+
.PARAMETER CommitMessage
|
|
89
|
+
Optional commit message if there are uncommitted changes
|
|
90
|
+
.PARAMETER StagingBranch
|
|
91
|
+
Optional custom staging branch name.
|
|
92
|
+
Defaults to {current-branch}{staging-suffix} (configured in JSON or defaults to -staging)
|
|
93
|
+
.PARAMETER TargetBranch
|
|
94
|
+
Optional target branch name.
|
|
95
|
+
Defaults to 'develop' or value in configuration file.
|
|
96
|
+
.PARAMETER Remote
|
|
97
|
+
Optional remote name.
|
|
98
|
+
Defaults to 'origin' or value in configuration file.
|
|
99
|
+
.EXAMPLE
|
|
100
|
+
Invoke-GitMergeWorkflow
|
|
101
|
+
.EXAMPLE
|
|
102
|
+
Invoke-GitMergeWorkflow -CommitMessage "Fix: Updated business contact form"
|
|
103
|
+
.EXAMPLE
|
|
104
|
+
git-merge-workflow -CommitMessage "Feature: Added new component" -WhatIf
|
|
105
|
+
#>
|
|
106
|
+
|
|
107
|
+
[CmdletBinding(SupportsShouldProcess=$true)]
|
|
108
|
+
param(
|
|
109
|
+
[Parameter(Mandatory=$false)]
|
|
110
|
+
[string]$CommitMessage = "",
|
|
111
|
+
|
|
112
|
+
[Parameter(Mandatory=$false)]
|
|
113
|
+
[string]$StagingBranch = "",
|
|
114
|
+
|
|
115
|
+
[Parameter(Mandatory=$false)]
|
|
116
|
+
[string]$TargetBranch = "",
|
|
117
|
+
|
|
118
|
+
[Parameter(Mandatory=$false)]
|
|
119
|
+
[string]$Remote = ""
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Load configuration
|
|
123
|
+
$config = Get-GitWorkflowConfig
|
|
124
|
+
|
|
125
|
+
# Set defaults (Priority: Parameter > Config > Hardcoded Default)
|
|
126
|
+
if (-not $TargetBranch) {
|
|
127
|
+
$TargetBranch = if ($config.TargetBranch) { $config.TargetBranch } else { "develop" }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (-not $Remote) {
|
|
131
|
+
$Remote = if ($config.Remote) { $config.Remote } else { "origin" }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
$stagingSuffix = if ($config.StagingSuffix) { $config.StagingSuffix } else { "-staging" }
|
|
135
|
+
|
|
136
|
+
# Internal helper to execute git commands with error handling
|
|
137
|
+
function Exec-Git {
|
|
138
|
+
[CmdletBinding()]
|
|
139
|
+
param(
|
|
140
|
+
[Parameter(Mandatory=$true, Position=0)]
|
|
141
|
+
[string]$Command,
|
|
142
|
+
|
|
143
|
+
[Parameter(Mandatory=$false)]
|
|
144
|
+
[string]$ErrorMessage,
|
|
145
|
+
|
|
146
|
+
[Parameter(Mandatory=$false)]
|
|
147
|
+
[switch]$IgnoreError,
|
|
148
|
+
|
|
149
|
+
[Parameter(Mandatory=$false)]
|
|
150
|
+
[switch]$ReturnOutput,
|
|
151
|
+
|
|
152
|
+
[Parameter(ValueFromRemainingArguments=$true)]
|
|
153
|
+
[string[]]$Arguments
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
$cmdDesc = "git $Command $Arguments"
|
|
157
|
+
|
|
158
|
+
if ($PSCmdlet.ShouldProcess("Git Repository", "Execute: $cmdDesc")) {
|
|
159
|
+
# Construct the command to run
|
|
160
|
+
# Note: We use & operator to run git with arguments
|
|
161
|
+
$output = & git $Command $Arguments 2>&1
|
|
162
|
+
$exitCode = $LASTEXITCODE
|
|
163
|
+
|
|
164
|
+
if ($ReturnOutput) {
|
|
165
|
+
return $output
|
|
166
|
+
} elseif ($output) {
|
|
167
|
+
# If not capturing output, write it to the stream (except errors which we handle below)
|
|
168
|
+
$output | ForEach-Object { Write-Verbose $_ }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (-not $IgnoreError -and $exitCode -ne 0) {
|
|
172
|
+
$msg = if ($ErrorMessage) { $ErrorMessage } else { "Git command failed: $cmdDesc" }
|
|
173
|
+
throw "$msg`nDetails: $output"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Write-Host "`n=== Git Merge Workflow ===" -ForegroundColor Cyan
|
|
179
|
+
Write-Host "Starting automated merge process...`n" -ForegroundColor Cyan
|
|
180
|
+
|
|
181
|
+
# Check if we're in a git repository
|
|
182
|
+
try {
|
|
183
|
+
Exec-Git "rev-parse" "--is-inside-work-tree" -ErrorMessage "Not a git repository" -ReturnOutput | Out-Null
|
|
184
|
+
} catch {
|
|
185
|
+
Write-Error $_.Exception.Message
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# Get current branch
|
|
190
|
+
$currentBranch = (git branch --show-current).Trim()
|
|
191
|
+
Write-Host "Current branch: $currentBranch" -ForegroundColor Yellow
|
|
192
|
+
|
|
193
|
+
if ([string]::IsNullOrWhiteSpace($currentBranch)) {
|
|
194
|
+
Write-Error "Could not determine current branch."
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
# Validate we are not on target or explicitly named staging
|
|
199
|
+
if ($currentBranch -eq $TargetBranch) {
|
|
200
|
+
Write-Error "You are currently on the target branch '$TargetBranch'. Please checkout your feature branch first."
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Define staging branch
|
|
205
|
+
if (-not $StagingBranch) {
|
|
206
|
+
$StagingBranch = "$currentBranch$stagingSuffix"
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if ($currentBranch -eq $StagingBranch) {
|
|
210
|
+
Write-Error "You are currently on the staging branch '$StagingBranch'. Please checkout your feature branch first."
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
Write-Host "`nStaging branch: $StagingBranch" -ForegroundColor Yellow
|
|
215
|
+
Write-Host "Target branch: $TargetBranch" -ForegroundColor Yellow
|
|
216
|
+
Write-Host "Remote: $Remote" -ForegroundColor Yellow
|
|
217
|
+
|
|
218
|
+
# Store starting branch to return to it later
|
|
219
|
+
$originalBranch = $currentBranch
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
# Verify remote connection before proceeding
|
|
223
|
+
Write-Host "`nVerifying connection to $Remote..." -ForegroundColor Yellow
|
|
224
|
+
Exec-Git -Command "ls-remote" -Arguments $Remote, "HEAD" -ErrorMessage "Could not connect to remote '$Remote'. Please check your internet connection and git credentials." -ReturnOutput | Out-Null
|
|
225
|
+
Write-Host "Connection successful!" -ForegroundColor Green
|
|
226
|
+
|
|
227
|
+
# Check for uncommitted changes
|
|
228
|
+
$status = git status --porcelain
|
|
229
|
+
if ($status) {
|
|
230
|
+
if ($CommitMessage) {
|
|
231
|
+
Write-Host "`nCommitting changes..." -ForegroundColor Yellow
|
|
232
|
+
if ($PSCmdlet.ShouldProcess("Current Branch", "Add all changes and commit with message '$CommitMessage'")) {
|
|
233
|
+
Exec-Git "add" "." -ErrorMessage "Failed to add changes"
|
|
234
|
+
Exec-Git "commit" "-m" "$CommitMessage" -ErrorMessage "Failed to commit changes"
|
|
235
|
+
Write-Host "Changes committed!" -ForegroundColor Green
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
Write-Error "You have uncommitted changes! Please commit them first or use -CommitMessage parameter"
|
|
239
|
+
git status
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
# --- Handle Staging Branch ---
|
|
245
|
+
|
|
246
|
+
# Check if staging branch exists locally
|
|
247
|
+
$branchExists = git branch --list $StagingBranch
|
|
248
|
+
if (-not $branchExists) {
|
|
249
|
+
Write-Host "`nStaging branch doesn't exist locally. Checking remote..." -ForegroundColor Yellow
|
|
250
|
+
# Check if exists on remote (explicit check to avoid silent failures)
|
|
251
|
+
$remoteBranchExists = $false
|
|
252
|
+
try {
|
|
253
|
+
$lsRemote = Exec-Git -Command "ls-remote" -Arguments "--heads", $Remote, $StagingBranch -ReturnOutput
|
|
254
|
+
if ($lsRemote) { $remoteBranchExists = $true }
|
|
255
|
+
} catch {
|
|
256
|
+
Write-Warning "Could not check remote branch: $_"
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if ($remoteBranchExists) {
|
|
260
|
+
Write-Host "Fetching remote staging branch..." -ForegroundColor Yellow
|
|
261
|
+
Exec-Git -Command "fetch" -Arguments $Remote, $StagingBranch
|
|
262
|
+
Exec-Git -Command "checkout" -Arguments "-b", $StagingBranch, "$Remote/$StagingBranch"
|
|
263
|
+
} else {
|
|
264
|
+
Write-Host "Creating new staging branch..." -ForegroundColor Yellow
|
|
265
|
+
Exec-Git -Command "checkout" -Arguments "-b", $StagingBranch
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
Write-Host "Checking out staging branch..." -ForegroundColor Yellow
|
|
269
|
+
Exec-Git -Command "checkout" -Arguments $StagingBranch
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
# Pull latest from staging (if tracked)
|
|
273
|
+
Write-Host "`nPulling latest changes from staging..." -ForegroundColor Yellow
|
|
274
|
+
# We use IgnoreError because it might fail if there's no tracking info yet, which is acceptable here
|
|
275
|
+
Exec-Git -Command "pull" -Arguments $Remote, $StagingBranch -IgnoreError
|
|
276
|
+
|
|
277
|
+
# Merge current branch into staging
|
|
278
|
+
Write-Host "`nMerging $currentBranch into $StagingBranch..." -ForegroundColor Yellow
|
|
279
|
+
Exec-Git -Command "merge" -Arguments $currentBranch, "--no-ff", "-m", "Merge $currentBranch into $StagingBranch" -ErrorMessage "Merge conflict detected in staging! Please resolve conflicts manually."
|
|
280
|
+
|
|
281
|
+
Write-Host "Successfully merged to staging!" -ForegroundColor Green
|
|
282
|
+
|
|
283
|
+
# Push staging
|
|
284
|
+
Write-Host "`nPushing $StagingBranch to remote..." -ForegroundColor Yellow
|
|
285
|
+
try {
|
|
286
|
+
Exec-Git -Command "push" -Arguments "-u", $Remote, $StagingBranch -ErrorMessage "Failed to push staging branch"
|
|
287
|
+
Write-Host "Staging branch pushed!" -ForegroundColor Green
|
|
288
|
+
} catch {
|
|
289
|
+
Write-Warning "Failed to push staging branch to remote."
|
|
290
|
+
Write-Warning "Error: $_"
|
|
291
|
+
if ($PSCmdlet.ShouldContinue("Do you want to skip pushing the staging branch and continue to merge into $TargetBranch?", "Skip Staging Push")) {
|
|
292
|
+
Write-Host "Skipping staging push..." -ForegroundColor Yellow
|
|
293
|
+
} else {
|
|
294
|
+
throw $_
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# --- Handle Target Branch ---
|
|
299
|
+
|
|
300
|
+
# Checkout target branch
|
|
301
|
+
Write-Host "`nChecking out $TargetBranch branch..." -ForegroundColor Yellow
|
|
302
|
+
Exec-Git "checkout" $TargetBranch -ErrorMessage "Failed to checkout $TargetBranch"
|
|
303
|
+
|
|
304
|
+
# Pull latest from target
|
|
305
|
+
Write-Host "Pulling latest changes from $TargetBranch..." -ForegroundColor Yellow
|
|
306
|
+
Exec-Git "pull" $Remote $TargetBranch -ErrorMessage "Failed to pull $TargetBranch"
|
|
307
|
+
|
|
308
|
+
# Merge staging into target
|
|
309
|
+
Write-Host "`nMerging $StagingBranch into $TargetBranch..." -ForegroundColor Yellow
|
|
310
|
+
Exec-Git "merge" $StagingBranch "--no-ff" "-m" "Merge $StagingBranch into $TargetBranch" -ErrorMessage "Merge conflict detected in target! Please resolve conflicts manually."
|
|
311
|
+
|
|
312
|
+
Write-Host "Successfully merged to target!" -ForegroundColor Green
|
|
313
|
+
|
|
314
|
+
# Push target
|
|
315
|
+
Write-Host "`nPushing $TargetBranch to remote..." -ForegroundColor Yellow
|
|
316
|
+
Exec-Git "push" $Remote $TargetBranch -ErrorMessage "Failed to push $TargetBranch branch"
|
|
317
|
+
Write-Host "$TargetBranch branch pushed!" -ForegroundColor Green
|
|
318
|
+
|
|
319
|
+
Write-Host "`n=== Workflow Complete! ===" -ForegroundColor Green
|
|
320
|
+
Write-Host "Summary:" -ForegroundColor Cyan
|
|
321
|
+
Write-Host " ✓ Merged: $originalBranch → $StagingBranch → $TargetBranch" -ForegroundColor White
|
|
322
|
+
Write-Host " ✓ All changes pushed to remote`n" -ForegroundColor White
|
|
323
|
+
|
|
324
|
+
} catch {
|
|
325
|
+
Write-Error $_.Exception.Message
|
|
326
|
+
Write-Host "`nWorkflow failed. Attempting to return to original branch..." -ForegroundColor Red
|
|
327
|
+
} finally {
|
|
328
|
+
# Return to original branch
|
|
329
|
+
$finalBranch = (git branch --show-current).Trim()
|
|
330
|
+
if ($originalBranch -and $finalBranch -ne $originalBranch) {
|
|
331
|
+
Write-Host "`nReturning to $originalBranch..." -ForegroundColor Yellow
|
|
332
|
+
if ($PSCmdlet.ShouldProcess("Cleanup", "Checkout $originalBranch")) {
|
|
333
|
+
git checkout $originalBranch 2>$null | Out-Null
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
# Create aliases for easier usage
|
|
340
|
+
New-Alias -Name git-merge-workflow -Value Invoke-GitMergeWorkflow -Force
|
|
341
|
+
New-Alias -Name gmw -Value Invoke-GitMergeWorkflow -Force
|
|
342
|
+
|
|
343
|
+
Export-ModuleMember -Function Invoke-GitMergeWorkflow, New-GitWorkflowConfig, Get-GitWorkflowConfig -Alias git-merge-workflow, gmw
|
package/Install.ps1
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Simple installation script for GitMergeWorkflow module
|
|
2
|
+
|
|
3
|
+
$moduleName = "GitMergeWorkflow"
|
|
4
|
+
$currentUserModules = [System.IO.Path]::Combine($env:USERPROFILE, "Documents", "WindowsPowerShell", "Modules")
|
|
5
|
+
$destPath = Join-Path $currentUserModules $moduleName
|
|
6
|
+
|
|
7
|
+
Write-Host "Installing $moduleName to $destPath..." -ForegroundColor Cyan
|
|
8
|
+
|
|
9
|
+
# Create modules directory if it doesn't exist
|
|
10
|
+
if (-not (Test-Path $currentUserModules)) {
|
|
11
|
+
New-Item -Path $currentUserModules -ItemType Directory -Force | Out-Null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# Copy module files
|
|
15
|
+
$scriptPath = $PSScriptRoot
|
|
16
|
+
if (-not $scriptPath) { $scriptPath = Get-Location }
|
|
17
|
+
|
|
18
|
+
if (Test-Path $destPath) {
|
|
19
|
+
Write-Warning "Module already exists. Updating..."
|
|
20
|
+
Remove-Item $destPath -Recurse -Force
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Copy-Item -Path $scriptPath -Destination $destPath -Recurse -Force
|
|
24
|
+
|
|
25
|
+
# Verify installation
|
|
26
|
+
if (Test-Path (Join-Path $destPath "$moduleName.psd1")) {
|
|
27
|
+
Write-Host "Installation successful!" -ForegroundColor Green
|
|
28
|
+
Write-Host "You can now run: Import-Module $moduleName" -ForegroundColor Yellow
|
|
29
|
+
} else {
|
|
30
|
+
Write-Error "Installation failed."
|
|
31
|
+
}
|
package/PUBLISHING.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# How to Publish `@babajide234/git-merge-workflow` to npm
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
1. **NPM Account**: You must have an account on [npmjs.com](https://www.npmjs.com/).
|
|
6
|
+
2. **Login**: You must be logged in as `babajide234`.
|
|
7
|
+
|
|
8
|
+
## Publishing Steps
|
|
9
|
+
|
|
10
|
+
1. **Login to npm**:
|
|
11
|
+
Open your terminal in the project directory and run:
|
|
12
|
+
```bash
|
|
13
|
+
npm login
|
|
14
|
+
```
|
|
15
|
+
Follow the prompts to authenticate via the browser.
|
|
16
|
+
|
|
17
|
+
2. **Verify Configuration**:
|
|
18
|
+
Ensure `package.json` has the correct version.
|
|
19
|
+
Current version: `1.0.0`
|
|
20
|
+
|
|
21
|
+
3. **Publish**:
|
|
22
|
+
By default, scoped packages (`@org/pkg`) are published as **private**.
|
|
23
|
+
|
|
24
|
+
- **To publish publicly** (visible to everyone):
|
|
25
|
+
```bash
|
|
26
|
+
npm publish --access public
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **To publish privately** (only visible to org members - requires paid npm plan):
|
|
30
|
+
```bash
|
|
31
|
+
npm publish
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Post-Publishing
|
|
35
|
+
|
|
36
|
+
- **Update Version**: For future updates, remember to bump the version number in `package.json` (e.g., `1.0.1`) before publishing again.
|
|
37
|
+
```bash
|
|
38
|
+
npm version patch # 1.0.0 -> 1.0.1
|
|
39
|
+
npm version minor # 1.0.0 -> 1.1.0
|
|
40
|
+
npm version major # 1.0.0 -> 2.0.0
|
|
41
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Git Merge Workflow PowerShell Module
|
|
2
|
+
|
|
3
|
+
Automate your git merge workflow with safety and ease. This module helps you merge your current feature branch to a staging branch (e.g., `feature-branch-staging`), and then to a target branch (e.g., `develop`), ensuring a consistent workflow.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Automated Merging**: Merges current branch -> Staging -> Target.
|
|
8
|
+
- **Safety Checks**: Prevents running on wrong branches, checks for uncommitted changes.
|
|
9
|
+
- **Conflict Handling**: Stops immediately on merge conflicts so you can resolve them.
|
|
10
|
+
- **Automatic Cleanup**: Returns you to your original branch even if the script fails.
|
|
11
|
+
- **Configurable**: Define project-specific settings via a JSON configuration file.
|
|
12
|
+
- **Dry Run**: Support for `-WhatIf` to preview actions.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Via NPM (Recommended for Node.js users)
|
|
17
|
+
You can install this tool globally using npm:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g @expedier/git-merge-workflow
|
|
21
|
+
```
|
|
22
|
+
This will make the `gmw` and `git-merge-workflow` commands available in your terminal.
|
|
23
|
+
|
|
24
|
+
### Manual Installation
|
|
25
|
+
1. Download this repository.
|
|
26
|
+
2. Run the included installation script:
|
|
27
|
+
```powershell
|
|
28
|
+
.\Install.ps1
|
|
29
|
+
```
|
|
30
|
+
Or copy the `GitMergeWorkflow` folder to your PowerShell modules directory manually.
|
|
31
|
+
3. Import the module (if not auto-loaded):
|
|
32
|
+
```powershell
|
|
33
|
+
Import-Module GitMergeWorkflow
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Basic Usage
|
|
39
|
+
Run the workflow from your feature branch:
|
|
40
|
+
```powershell
|
|
41
|
+
Invoke-GitMergeWorkflow
|
|
42
|
+
# OR use the alias
|
|
43
|
+
gmw
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### With Commit Message
|
|
47
|
+
If you have uncommitted changes, you can commit them as part of the workflow:
|
|
48
|
+
```powershell
|
|
49
|
+
gmw -CommitMessage "Feat: Completed login page"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Dry Run (Preview)
|
|
53
|
+
See what commands would be executed without actually running them:
|
|
54
|
+
```powershell
|
|
55
|
+
gmw -WhatIf
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Custom Branches
|
|
59
|
+
Override default branches on the fly:
|
|
60
|
+
```powershell
|
|
61
|
+
gmw -TargetBranch "main" -StagingBranch "custom-staging"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
You can create a configuration file for your project so you don't have to pass parameters every time.
|
|
67
|
+
|
|
68
|
+
1. Navigate to your project root.
|
|
69
|
+
2. Run the configuration generator:
|
|
70
|
+
```powershell
|
|
71
|
+
New-GitWorkflowConfig -TargetBranch "main" -StagingSuffix "-test"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This creates a `.git-merge-workflow.json` file:
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"TargetBranch": "main",
|
|
78
|
+
"StagingSuffix": "-test",
|
|
79
|
+
"Remote": "origin"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Publishing (For Maintainers)
|
|
84
|
+
|
|
85
|
+
### GitHub Actions
|
|
86
|
+
This repository is configured to automatically publish to:
|
|
87
|
+
1. **PowerShell Gallery** (if `NUGET_KEY` secret is set)
|
|
88
|
+
2. **NPM Registry** (if `NPM_TOKEN` secret is set)
|
|
89
|
+
|
|
90
|
+
When you create a new Release in GitHub.
|
|
91
|
+
|
|
92
|
+
### Manual Publishing
|
|
93
|
+
|
|
94
|
+
**To NPM:**
|
|
95
|
+
```bash
|
|
96
|
+
npm login
|
|
97
|
+
npm publish --access public
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**To PowerShell Gallery:**
|
|
101
|
+
```powershell
|
|
102
|
+
Publish-Module -Path . -NuGetApiKey <Your-API-Key>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Functions
|
|
106
|
+
|
|
107
|
+
- `Invoke-GitMergeWorkflow` (Alias: `gmw`, `git-merge-workflow`): The main workflow command.
|
|
108
|
+
- `New-GitWorkflowConfig`: Generates the `.git-merge-workflow.json` configuration file.
|
|
109
|
+
- `Get-GitWorkflowConfig`: Reads the current configuration.
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Path to the PowerShell module
|
|
7
|
+
const modulePath = path.resolve(__dirname, '../GitMergeWorkflow.psd1');
|
|
8
|
+
|
|
9
|
+
// Arguments passed to the CLI
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
|
|
12
|
+
// Construct the PowerShell command
|
|
13
|
+
// We import the module and then invoke the function with passed arguments
|
|
14
|
+
const psCommand = `
|
|
15
|
+
$ErrorActionPreference = 'Stop'
|
|
16
|
+
Import-Module '${modulePath}' -Force
|
|
17
|
+
Invoke-GitMergeWorkflow ${args.join(' ')}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
// Determine which PowerShell executable to use (pwsh for Core, powershell for Windows PowerShell)
|
|
21
|
+
const psExecutable = process.platform === 'win32' ? 'powershell' : 'pwsh';
|
|
22
|
+
|
|
23
|
+
const child = spawn(psExecutable, ['-NoProfile', '-Command', psCommand], {
|
|
24
|
+
stdio: 'inherit',
|
|
25
|
+
shell: true
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
child.on('exit', (code) => {
|
|
29
|
+
process.exit(code);
|
|
30
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@babajide234/git-merge-workflow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Automated Git workflow for merging feature branches through staging to develop",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"git-merge-workflow": "./bin/cli.js",
|
|
8
|
+
"gmw": "./bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"git",
|
|
15
|
+
"workflow",
|
|
16
|
+
"powershell",
|
|
17
|
+
"automation",
|
|
18
|
+
"devops"
|
|
19
|
+
],
|
|
20
|
+
"author": "babajide Tomoshegbo",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/babajide234/GitMergeWorkflow.git"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=14"
|
|
28
|
+
}
|
|
29
|
+
}
|