如何将Azure DevOps构件推送至OneDrive SharePoint文件夹
Azure DevOps CI 推送构件至OneDrive个人文件夹解决方案
一、前置准备(Azure AD应用注册)
- 登录Azure门户,创建一个单租户的Azure AD应用注册
- 进入应用的“证书和密码”页面,生成客户端密钥并保存(该密钥仅显示一次,务必妥善保管)
- 进入“API权限”页面,添加Microsoft Graph应用权限:
Files.ReadWrite.All,并点击“授予管理员同意” - 记录以下信息:租户ID(Azure AD目录ID)、客户端ID(应用程序ID)、刚才生成的客户端密钥
二、Azure DevOps流水线配置
- 在Azure DevOps项目的“库”中创建变量组,添加3个变量:
TenantId:填入刚才记录的租户IDClientId:填入客户端IDClientSecret:填入客户端密钥,勾选“保密”选项
- 在CI流水线的YAML或经典编辑器中,引用该变量组
三、PowerShell上传脚本实现
将以下脚本添加到CI流水线的PowerShell任务中,根据实际情况修改参数:
# 从变量组读取配置 $tenantId = "$(TenantId)" $clientId = "$(ClientId)" $clientSecret = "$(ClientSecret)" # 配置参数:替换为你的用户UPN和目标文件夹路径 $userUpn = "bar@foo.com" # 对应你的OneDrive用户邮箱,可从Azure AD用户列表获取 $targetFolderPath = "/BuildArtifacts" # OneDrive中的目标文件夹路径,根目录填"/" $artifactPath = "$(Build.ArtifactStagingDirectory)" # CI构件生成目录 # 1. 获取Microsoft Graph访问令牌 $tokenUri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" $tokenBody = @{ client_id = $clientId scope = "https://graph.microsoft.com/.default" client_secret = $clientSecret grant_type = "client_credentials" } $tokenResponse = Invoke-RestMethod -Uri $tokenUri -Method Post -Body $tokenBody $accessToken = $tokenResponse.access_token # 2. 检查并创建目标文件夹(如果不存在) function Ensure-FolderExists { param( [string]$FolderPath, [string]$AccessToken, [string]$UserUpn ) $folderCheckUri = "https://graph.microsoft.com/v1.0/users/$UserUpn/drive/root:$FolderPath" try { Invoke-RestMethod -Uri $folderCheckUri -Method Get -Headers @{Authorization = "Bearer $AccessToken"} Write-Host "目标文件夹已存在: $FolderPath" } catch { if ($_.Exception.Response.StatusCode -eq 404) { $folderName = $FolderPath.Split("/")[-1] $parentPath = if ($FolderPath -eq "/") { "/" } else { $FolderPath.Substring(0, $FolderPath.LastIndexOf("/")) } $createUri = "https://graph.microsoft.com/v1.0/users/$UserUpn/drive/root:$parentPath:/children" $createBody = @{ name = $folderName folder = @{} "@microsoft.graph.conflictBehavior" = "fail" } | ConvertTo-Json Invoke-RestMethod -Uri $createUri -Method Post -Headers @{Authorization = "Bearer $AccessToken"; "Content-Type" = "application/json"} -Body $createBody Write-Host "成功创建目标文件夹: $FolderPath" } else { throw "检查文件夹时出错: $_" } } } Ensure-FolderExists -FolderPath $targetFolderPath -AccessToken $accessToken -UserUpn $userUpn # 3. 遍历并上传构件文件 $files = Get-ChildItem -Path $artifactPath -File -Recurse foreach ($file in $files) { $uploadUri = "https://graph.microsoft.com/v1.0/users/$userUpn/drive/root:$targetFolderPath/$($file.Name):/content" $fileContent = Get-Content -Path $file.FullName -Raw -Encoding Byte try { Invoke-RestMethod -Uri $uploadUri -Method Put -Headers @{Authorization = "Bearer $accessToken"} -Body $fileContent -ContentType "application/octet-stream" Write-Host "✅ 成功上传文件: $($file.Name)" } catch { Write-Warning "❌ 上传文件失败 $($file.Name): $_" } }
关键说明
- 关于Graph URL配置:个人OneDrive的Graph端点格式为
https://graph.microsoft.com/v1.0/users/{用户UPN}/drive/root:{文件夹路径},其中用户UPN是你的OneDrive关联邮箱,文件夹路径从根目录开始(如/Builds/202405) - 若需上传子目录结构,可修改脚本中的文件遍历和上传路径逻辑,保持目录映射
- 确保流水线代理有足够权限读取构件目录,且网络可访问Microsoft Graph和Azure AD端点
内容的提问来源于stack exchange,提问作者elongez
相关产品推荐
相关产品推荐

