Powershell自动提交代码到Github
小虾米 半吊子CRUD工程师

前提

  • 本地已安装powershell,且配置ps1文件可执行

  • 本地已安装git,且你监控的文件夹已经跟远程Github仓库建立联系,在次目录下执行git remote -v结果不为空

当前Powershell版本:

当前Git版本:

远程仓库:

监听特定的文件夹下的文件修改,并写入日志

参考博客:Monitoring Folders for File Changes - powershell.one

以下为我的脚本,替换>>>开头的注释所在的变量,然后保存为.ps1文件即可使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# >>> 指定监控路径
$BlogRepoPath = 'path2monitoredFolder'

# >>> 指定日志文件夹
$basicLogPath = 'path2logFolder'

# >>> 指定监控路径对应的远程仓库名
$remoteReposity = 'remoteRepositoryName'

# specify which files you want to monitor
$FileFilter = '*'

# specify whether you want to monitor subfolders as well:
$IncludeSubfolders = $true

# specify the file or folder properties you want to monitor:
$AttributeFilter = [IO.NotifyFilters]::FileName, [IO.NotifyFilters]::LastWrite

try {
$watcher = New-Object -TypeName System.IO.FileSystemWatcher -Property @{
Path = $BlogRepoPath
Filter = $FileFilter
IncludeSubdirectories = $IncludeSubfolders
NotifyFilter = $AttributeFilter
}

# define the code that should execute when a change occurs:
$action = {
# the code is receiving this to work with:

# change type information:
$details = $event.SourceEventArgs
$Name = $details.Name
$OldName = $details.OldName
$FullPath = $details.FullPath
$OldFullPath = $details.OldFullPath

if ($FullPath.StartsWith("$BlogRepoPath\.git") -and -not($FullPath.Contains(".github")) ){
<# Action to perform if the condition is true #>
return
}
# node_modules/
# if ($FullPath.StartsWith("$BlogRepoPath\node_modules")){
# <# Action to perform if the condition is true #>
# return
# }
# public/
if ($FullPath.StartsWith("$BlogRepoPath\public")){
<# Action to perform if the condition is true #>
return
}
# db.json
if ($FullPath.StartsWith("$BlogRepoPath\db.json")){
<# Action to perform if the condition is true #>
return
}

# 准备日志
if (-not (Get-Item -Path $basicLogPath)) {
return
}
$year = (get-date).Year
$mouth = (get-date).Month
$day = (get-date).Day
$filePath = "$basicLogPath\$year-$mouth"
if (-not (Get-Item -Path $filePath)) {
New-Item -ItemType Directory -Path $filePath
}
$logFile = "$filePath\$year-$mouth-$day.log"
if (-not (Get-Item -Path $logFile)) {
New-Item -ItemType File -Path $logFile
}

# type of change:
$ChangeType = $details.ChangeType

# when the change occured:
$Timestamp = $event.TimeGenerated

# save information to a global variable for testing purposes
# so you can examine it later
# MAKE SURE YOU REMOVE THIS IN PRODUCTION!
$global:all = $details

# now you can define some action to take based on the
# details about the change event:

# let's compose a message:
$text = "{0} was {1} at {2}" -f $FullPath, $ChangeType, $Timestamp
# Write-Host ""
# Write-Host $text -ForegroundColor DarkYellow
# Out-File -Append -FilePath $logFile -InputObject ""
Out-File -Append -FilePath $logFile -InputObject $text

# you can also execute code based on change type here:
switch ($ChangeType) {
'Changed' {
"CHANGE"
# 修改的时候提交也要等 5 秒
Start-Sleep -Seconds 1
}
'Created' { "CREATED" }
'Deleted' {
"DELETED"
# to illustrate that ALL changes are picked up even if
# handling an event takes a lot of time, we artifically
# extend the time the handler needs whenever a file is deleted
# Write-Host "Deletion Handler Start" -ForegroundColor Gray
Out-File -Append -FilePath $logFile -InputObject "Deletion Handler Start"
Start-Sleep -Seconds 1
# Write-Host "Deletion Handler End" -ForegroundColor Gray
Out-File -Append -FilePath $logFile -InputObject "Deletion Handler End"
}
'Renamed' {
# this executes only when a file was renamed
$text = "File {0} was renamed to {1}" -f $OldName, $Name
# Write-Host $text -ForegroundColor Yellow
Out-File -Append -FilePath $logFile -InputObject $text
}

# any unhandled change types surface here:
default {
# Write-Host $_ -ForegroundColor Red -BackgroundColor White
Out-File -Append -FilePath $logFile -InputObject $_
}
}

# git 先更新 再提交
# 日志添加时间,
# 目录添加忽略条件。不监听 .git目录下的文件
# 添加一个延时,不要提交太频繁
git -C $BlogRepoPath pull $remoteReposity master
git -C $BlogRepoPath add -A
git -C $BlogRepoPath commit -m 'auto commit'
git -C $BlogRepoPath push $remoteReposity
Out-File -Append -FilePath $logFile -InputObject "push to github $remoteReposity"

}

# subscribe your event handler to all event types that are
# important to you. Do this as a scriptblock so all returned
# event handlers can be easily stored in $handlers:
$handlers = . {
Register-ObjectEvent -InputObject $watcher -EventName Changed -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Deleted -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action
}

# monitoring starts now:
$watcher.EnableRaisingEvents = $true

# Write-Host "Watching for changes to $BlogRepoPath"
# Out-File -Append -FilePath $logFile -InputObject '------------------------------------------------------------------------------------------------------------------------'
# Out-File -Append -FilePath $logFile -InputObject "Watching for changes to $BlogRepoPath"


# since the FileSystemWatcher is no longer blocking PowerShell
# we need a way to pause PowerShell while being responsive to
# incoming events. Use an endless loop to keep PowerShell busy:
do {
# Wait-Event waits for a second and stays responsive to events
# Start-Sleep in contrast would NOT work and ignore incoming events
Wait-Event -Timeout 60

# write a dot to indicate we are still monitoring:
# Write-Host "." -NoNewline
# Out-File -Append -FilePath $logFile -InputObject "."


} while ($true)
}
finally {
# this gets executed when user presses CTRL+C:

# stop monitoring
$watcher.EnableRaisingEvents = $false

# remove the event handlers
$handlers | ForEach-Object {
Unregister-Event -SourceIdentifier $_.Name
}

# event handlers are technically implemented as a special kind
# of background job, so remove the jobs now:
$handlers | Remove-Job

# properly dispose the FileSystemWatcher:
$watcher.Dispose()

# Write-Warning "Event Handler disabled, monitoring ends."
Out-File -Append -FilePath $logFile -InputObject "Event Handler disabled, monitoring ends."

}

对此,相比于参考博客中的源码,这里做出了几点改进:

  • 将 Write-Host 打印日志改为通过 Out-File 将日志写入文件,且日志文件按天区分,自动创建。

  • 在.git文件夹、public文件夹和db.json文件出现修改的时候不提交到GitHub,避免出现提交循环,同时节约内存。

将此ps1脚本设置为开机自启

设置powershell脚本开机启动有点麻烦,需要在外面套一层.bat文件,同时还会有闪屏的问题,即打开一个cmd窗口执行完语句之后又快速关闭。为了解决这个问题,在.bat文件的外面再套一层.vbs即可解决,最终文件如下:

  1. 创建script.vbs

    1
    2
    3
    4
    Dim WinScriptHost
    Set WinScriptHost = CreateObject("WScript.Shell")
    WinScriptHost.Run Chr(34) & "path2batfile\script.bat" & Chr(34), 0
    Set WinScriptHost = Nothing
  2. 创建script.bat

    1
    pwsh.exe -file path2powershellScript\script.ps1
  3. 将上一小节的脚本保存为script.ps1,放到path2powershellScript指定的位置即可。

  4. script.vbs创建快捷方式,然后放到C:\Users\<user_name>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup文件夹,系统开机的时候,会自动执行此文件夹下的脚本或者软件。

  • 本文标题:Powershell自动提交代码到Github
  • 本文作者:小虾米
  • 创建时间:2022-07-14 08:10:00
  • 本文链接:https://xiashuo.xyz/2022/07/14/Powershell自动提交代码到Github/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论