简介
Gitlab Runner在Windows上运行之后,我们在.gitlab-ci.yml中编写script语句,思路和Linux是一样。但是考虑到Windows的特点,为了让程序员少接触一些知识点,以及给未来执行作业的时候预留更多的操作空间。简单说就是未来修改执行作业时候的逻辑,但是每个软件仓库根目录下的.gitlab-ci.yml不需要改动,我们一共编写了6个PowerShell脚本,和1个适配Directory.Build.props技术的windows批处理文件。
这里有两个PowerShell,一个是在Windows Gitlab Runner服务器上运行,另外一个是在Web应用程序服务器上运行。前者调用后者。
1、Gitlab Runner服务器上的PowerShell
# 设置环境变量以支持UTF-8编码
param (
[Parameter(Mandatory=$true)]
[string]$ssh_rsa_file,
[Parameter(Mandatory=$true)]
[string]$web_output_path,
[Parameter(Mandatory=$true)]
[string]$remote_username,
[Parameter(Mandatory=$true)]
[string]$remote_server,
[Parameter(Mandatory=$true)]
[string]$remote_root_dir_name,
[Parameter(Mandatory=$true)]
[string]$remote_site_name,
[Parameter(Mandatory=$true)]
[string]$remote_windows_web_app_pool,
[Parameter(Mandatory=$true)]
[string]$web_app_name,
[Parameter(Mandatory=$true)]
[string]$version_id
)
chcp 65001
$version_id = $version_id.Replace('.','_')
# 确保所有参数值中的特殊字符被适当转义,特别是对于包含在路径或字符串中的双引号
$escapedSiteName = $remote_site_name -replace "'", "''"
$escapedPool = $remote_windows_web_app_pool -replace "'", "''"
$escapedAppName = $web_app_name -replace "'", "''"
$escapedVersion = $version_id -replace "'", "''"
$remote_script_path = "c:\welcome-gitlab-runner\Setup-WebApp.ps1"
# 构建远程脚本调用的参数字符串,保持简单并确保参数间以空格分隔
$remoteParams = "-remote_site_name '$escapedSiteName' -remote_windows_web_app_pool '$escapedPool' -web_app_name '$escapedAppName' -version_id '$escapedVersion'"
# 构建完整的SSH命令,注意引号的正确使用和转义
$sshCmd = "ssh -i `"$ssh_rsa_file`" -o ""StrictHostKeyChecking=no"" -v `"$remote_username@$remote_server`" 'powershell.exe -ExecutionPolicy Bypass -File `"$remote_script_path`" $remoteParams'"
# 注意:$remote_script_path 应替换为实际的远程脚本路径,如"c:\for-gitlab-runner\Setup-LodaWebApp.ps1"
# 打印命令以供调试
Write-Host "Executing Command: $sshCmd"
# 执行SSH命令
Invoke-Expression $sshCmd
if ($LASTEXITCODE -ne 0) {
if ($Errors.Count -gt 0) {
Write-Host "清空远程目录时出错:" $Errors[0].Exception.Message
Write-Host "错误信息:" $Errors[0].Exception.Message
Write-Host "堆栈跟踪:" $Errors[0].Exception.StackTrace
}
else {
Write-Host "没有错误信息记录。"
}
}
$remote_dir = "C:\" + $remote_root_dir_name + "\" + $web_app_name + "\" + $version_id
scp -i $ssh_rsa_file -o StrictHostKeyChecking=no -rv ${web_output_path}"\*" ${remote_username}@${remote_server}:$remote_dir
Exit $LASTEXITCODE
2、Web应用程序服务器上的PowerShell
根据前边脚本的内容,
$remote_script_path = "c:\welcome-gitlab-runner\Setup-WebApp.ps1"
可以知道我们这个脚本,要放置在Web应用程序服务器的对应位置。
内容如下:
param(
[Parameter(Mandatory=$true)]
[string]$remote_site_name,
[Parameter(Mandatory=$true)]
[string]$remote_windows_web_app_pool,
[Parameter(Mandatory=$true)]
[string]$web_app_name,
[Parameter(Mandatory=$true)]
[string]$version_id
)
chcp 65001
Write-Host "已绑定的参数及其值:"
$PSBoundParameters.GetEnumerator() | ForEach-Object {
Write-Host "$($_.Key): $($_.Value)"
}
$version_id = $version_id.Replace('.','_')
$AppPhysicalPath = "C:\loda\" + ${web_app_name} + "\" + $version_id
New-Item -Path $AppPhysicalPath -ItemType Directory -Force
# 定义IIS PowerShell模块路径,根据实际情况调整
$IISModulePath = "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\WebAdministration\WebAdministration.psd1"
if (!(Test-Path $IISModulePath)) {
Write-Error "IIS Administration PowerShell module not found at $IISModulePath"
exit 1
}
Import-Module $IISModulePath
# 确保应用池存在
if (!(Get-ChildItem IIS:\AppPools | Where-Object { $_.Name -eq $remote_windows_web_app_pool })) {
Write-Error "Application Pool '$remote_windows_web_app_pool' does not exist."
exit 1
}
# 确保站点存在
$sitePath = "IIS:\Sites\$remote_site_name"
if (!(Test-Path $sitePath)) {
Write-Error "Site '$remote_site_name' does not exist."
exit 1
}
# 创建应用程序
Write-Host "Creating application '$web_app_name' under site '$remote_site_name' with physical path '$AppPhysicalPath'"
NEW-WebApplication -Name $web_app_name -Site $remote_site_name -ApplicationPool $remote_windows_web_app_pool -PhysicalPath $AppPhysicalPath -Force
if($LASTEXITCODE -ne 0)
{
Write-Error "Failed to create the application."
exit $LASTEXITCODE
}
# 确认操作成功
$appPath = Join-Path $sitePath $web_app_name
if (Test-Path $appPath) {
Write-Host "Application created successfully at '$appPath'."
} else {
Write-Error "Failed to create the application."
}
exit 0
黑夜里不停折腾的代码行者。