mirror of
https://github.com/actions/runner.git
synced 2025-12-11 04:46:58 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2247f2e3ea | ||
|
|
81fe044a22 | ||
|
|
3ba55f86a9 | ||
|
|
61f9d3f656 |
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@@ -1,48 +1,34 @@
|
|||||||
name: Runner CI
|
name: Runner CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- releases/*
|
- releases/*
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||||
include:
|
include:
|
||||||
- runtime: linux-x64
|
- os: ubuntu-latest
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
- os: macOS-latest
|
||||||
- runtime: linux-arm64
|
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
- os: windows-latest
|
||||||
- runtime: linux-arm
|
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: osx-x64
|
|
||||||
os: macOS-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: win-x64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} layout Release
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
@@ -50,19 +36,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} test
|
${{ matrix.devScript }} test
|
||||||
working-directory: src
|
working-directory: src
|
||||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
# Create runner package tar.gz/zip
|
||||||
- name: Package Release
|
- name: Package Release
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} package Release
|
${{ matrix.devScript }} package Release
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact
|
# Upload runner package tar.gz/zip as artifact
|
||||||
- name: Publish Artifact
|
- name: Publish Artifact
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: runner-package-${{ matrix.runtime }}
|
name: runner-package-${{ matrix.os }}
|
||||||
path: _package
|
path: _package
|
||||||
|
|||||||
184
.github/workflows/release.yml
vendored
184
.github/workflows/release.yml
vendored
@@ -1,184 +0,0 @@
|
|||||||
name: Runner CD
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- src/runnerversion_block # Change this to src/runnerversion when we are ready.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
|
||||||
include:
|
|
||||||
- runtime: linux-x64
|
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: linux-arm64
|
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: linux-arm
|
|
||||||
os: ubuntu-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: osx-x64
|
|
||||||
os: macOS-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: win-x64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
|
|
||||||
# Build runner layout
|
|
||||||
- name: Build & Layout Release
|
|
||||||
run: |
|
|
||||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
|
||||||
working-directory: src
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
- name: L0
|
|
||||||
run: |
|
|
||||||
${{ matrix.devScript }} test
|
|
||||||
working-directory: src
|
|
||||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
|
||||||
- name: Package Release
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
run: |
|
|
||||||
${{ matrix.devScript }} package Release
|
|
||||||
working-directory: src
|
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact.
|
|
||||||
# Since each package name is unique, so we don't need to put ${{matrix}} info into artifact name
|
|
||||||
- name: Publish Artifact
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: actions/upload-artifact@v1
|
|
||||||
with:
|
|
||||||
name: runner-packages
|
|
||||||
path: _package
|
|
||||||
|
|
||||||
release:
|
|
||||||
needs: build
|
|
||||||
runs-on: linux-latest
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# Download runner package tar.gz/zip produced by 'build' job
|
|
||||||
- name: Download Artifact
|
|
||||||
uses: actions/download-artifact@v1
|
|
||||||
with:
|
|
||||||
name: runner-packages
|
|
||||||
|
|
||||||
# Create ReleaseNote file
|
|
||||||
- name: Create ReleaseNote
|
|
||||||
id: releaseNote
|
|
||||||
uses: actions/github-script@0.3.0
|
|
||||||
with:
|
|
||||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
// Get runner version from ./src/runnerVersion file
|
|
||||||
const versionContent = await github.repos.getContents({
|
|
||||||
owner: '${{ github.event.repository.owner.name }}',
|
|
||||||
repo: '${{ github.event.repository.name }}',
|
|
||||||
path: 'src/runnerversion'
|
|
||||||
ref: ${{ github.sha }}
|
|
||||||
})
|
|
||||||
const runnerVersion = Buffer.from(versionContent.data.content, 'base64').toString()
|
|
||||||
console.log("Runner Version ' + runnerVersion)
|
|
||||||
core.setOutput('version', runnerVersion);
|
|
||||||
|
|
||||||
// Query GitHub release ensure version is bumped
|
|
||||||
const latestRelease = await github.repos.getLatestRelease({
|
|
||||||
owner: '${{ github.event.repository.owner.name }}',
|
|
||||||
repo: '${{ github.event.repository.name }}'
|
|
||||||
})
|
|
||||||
console.log(latestRelease.name)
|
|
||||||
const latestReleaseVersion = latestRelease.name.substring(1)
|
|
||||||
const vLatest = latestReleaseVersion.split('.')
|
|
||||||
const vNew = runnerVersion.split('.')
|
|
||||||
let versionBumped = true
|
|
||||||
for (let i = 0; i < 3; ++i) {
|
|
||||||
var v1 = parseInt(vLatest[i], 10);
|
|
||||||
var v2 = parseInt(vNew[i], 10);
|
|
||||||
if (v2 > v1) {
|
|
||||||
console.log(runnerVersion + " > " + latestReleaseVersion + "(Latest)")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v1 > v2) {
|
|
||||||
versionBumped = false
|
|
||||||
core.setFailed(runnerVersion + " < " + latestReleaseVersion + "(Latest)")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate release note
|
|
||||||
if (versionBumped) {
|
|
||||||
const releaseNoteContent = await github.repos.getContents({
|
|
||||||
owner: '${{ github.event.repository.owner.name }}',
|
|
||||||
repo: '${{ github.event.repository.name }}',
|
|
||||||
path: 'releaseNote.md'
|
|
||||||
ref: ${{ github.sha }}
|
|
||||||
})
|
|
||||||
const releaseNote = Buffer.from(releaseNoteContent.data.content, 'base64').toString().replace("<RUNNER_VERSION>", runnerVersion)
|
|
||||||
console.log(releaseNote)
|
|
||||||
core.setOutput('note', releaseNote);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create GitHub release
|
|
||||||
- uses: actions/create-release@v1
|
|
||||||
id: createRelease
|
|
||||||
name: Create ${{ steps.releaseNote.outputs.version }} Runner Release
|
|
||||||
with:
|
|
||||||
tag_name: "v${{ steps.releaseNote.outputs.version }}"
|
|
||||||
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
|
||||||
body: ${{ steps.releaseNote.outputs.note }}
|
|
||||||
prerelease: true
|
|
||||||
|
|
||||||
# Upload release assets
|
|
||||||
- name: Upload Release Asset (win-x64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ./actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-x64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ./actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (mac-x64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ./actions-runner-mac-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-mac-x64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-arm)
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ./actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-arm64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.1
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ./actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
**/libs
|
**/libs
|
||||||
**/*.xproj
|
**/*.xproj
|
||||||
**/*.xproj.user
|
**/*.xproj.user
|
||||||
|
**/*.sln
|
||||||
**/.vs
|
**/.vs
|
||||||
**/.vscode
|
**/.vscode
|
||||||
**/*.error
|
**/*.error
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.29411.138
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Common", "src\Runner.Common\Runner.Common.csproj", "{084289A3-CD7A-42E0-9219-4348B4B7E19B}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Listener", "src\Runner.Listener\Runner.Listener.csproj", "{7D461AEE-BF2A-4855-BD96-56921160B36A}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.PluginHost", "src\Runner.PluginHost\Runner.PluginHost.csproj", "{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Plugins", "src\Runner.Plugins\Runner.Plugins.csproj", "{C23AFD6F-4DCD-4243-BC61-865BE31B9168}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Sdk", "src\Runner.Sdk\Runner.Sdk.csproj", "{D0484633-DA97-4C34-8E47-1DADE212A57A}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunnerService", "src\Runner.Service\Windows\RunnerService.csproj", "{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Runner.Worker", "src\Runner.Worker\Runner.Worker.csproj", "{C2F5B9FA-2621-411F-8EB2-273ED276F503}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk", "src\Sdk\Sdk.csproj", "{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "src\Test\Test.csproj", "{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{084289A3-CD7A-42E0-9219-4348B4B7E19B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7D461AEE-BF2A-4855-BD96-56921160B36A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D0320EB1-CB6D-4179-BFDC-2F2B664A370C}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C23AFD6F-4DCD-4243-BC61-865BE31B9168}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D0484633-DA97-4C34-8E47-1DADE212A57A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D12EBD71-0464-46D0-8394-40BCFBA0A6F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C2F5B9FA-2621-411F-8EB2-273ED276F503}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D2EE812B-E4DF-49BB-AE87-12BC49949B5F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {4A831DDA-3860-45E5-930E-BB3A7833AE80}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
12
assets.json
12
assets.json
@@ -16,17 +16,5 @@
|
|||||||
"platform": "linux-x64",
|
"platform": "linux-x64",
|
||||||
"version": "<RUNNER_VERSION>",
|
"version": "<RUNNER_VERSION>",
|
||||||
"downloadUrl": "https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz"
|
"downloadUrl": "https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz",
|
|
||||||
"platform": "linux-arm64",
|
|
||||||
"version": "<RUNNER_VERSION>",
|
|
||||||
"downloadUrl": "https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz",
|
|
||||||
"platform": "linux-arm",
|
|
||||||
"version": "<RUNNER_VERSION>",
|
|
||||||
"downloadUrl": "https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
stages:
|
stages:
|
||||||
- stage: Build
|
- stage: Build
|
||||||
jobs:
|
jobs:
|
||||||
################################################################################
|
################################################################################
|
||||||
- job: build_windows_agent_x64
|
- job: build_windows_agent_x64
|
||||||
@@ -11,14 +11,12 @@ stages:
|
|||||||
|
|
||||||
# Steps template for windows platform
|
# Steps template for windows platform
|
||||||
- template: windows.template.yml
|
- template: windows.template.yml
|
||||||
parameters:
|
|
||||||
targetRuntime: win-x64
|
|
||||||
|
|
||||||
# Package dotnet core windows dependency (VC++ Redistributable)
|
# Package dotnet core windows dependency (VC++ Redistributable)
|
||||||
- powershell: |
|
- powershell: |
|
||||||
Write-Host "Downloading 'VC++ Redistributable' package."
|
Write-Host "Downloading 'VC++ Redistributable' package."
|
||||||
$outDir = Join-Path -Path $env:TMP -ChildPath ([Guid]::NewGuid())
|
$outDir = Join-Path -Path $env:TMP -ChildPath ([Guid]::NewGuid())
|
||||||
New-Item -Path $outDir -ItemType directory
|
New-Item -Path $outDir -ItemType directory
|
||||||
$outFile = Join-Path -Path $outDir -ChildPath "ucrt.zip"
|
$outFile = Join-Path -Path $outDir -ChildPath "ucrt.zip"
|
||||||
Invoke-WebRequest -Uri https://vstsagenttools.blob.core.windows.net/tools/ucrt/ucrt_x64.zip -OutFile $outFile
|
Invoke-WebRequest -Uri https://vstsagenttools.blob.core.windows.net/tools/ucrt/ucrt_x64.zip -OutFile $outFile
|
||||||
Write-Host "Unzipping 'VC++ Redistributable' package to agent layout."
|
Write-Host "Unzipping 'VC++ Redistributable' package to agent layout."
|
||||||
@@ -30,13 +28,13 @@ stages:
|
|||||||
displayName: Package UCRT
|
displayName: Package UCRT
|
||||||
|
|
||||||
# Create agent package zip
|
# Create agent package zip
|
||||||
- script: dev.cmd package Release win-x64
|
- script: dev.cmd package Release
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Package Release
|
displayName: Package Release
|
||||||
|
|
||||||
# Upload agent package zip as build artifact
|
# Upload agent package zip as build artifact
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Publish Artifact (Windows x64)
|
displayName: Publish Artifact (Windows)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
@@ -52,76 +50,22 @@ stages:
|
|||||||
|
|
||||||
# Steps template for non-windows platform
|
# Steps template for non-windows platform
|
||||||
- template: nonwindows.template.yml
|
- template: nonwindows.template.yml
|
||||||
parameters:
|
|
||||||
targetRuntime: linux-x64
|
|
||||||
|
|
||||||
# Create agent package zip
|
# Create agent package zip
|
||||||
- script: ./dev.sh package Release linux-x64
|
- script: ./dev.sh package Release
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Package Release
|
displayName: Package Release
|
||||||
|
|
||||||
# Upload agent package zip as build artifact
|
# Upload agent package zip as build artifact
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Publish Artifact (Linux x64)
|
displayName: Publish Artifact (Linux)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
artifactType: container
|
artifactType: container
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
- job: build_linux_agent_arm64
|
- job: build_osx_agent
|
||||||
################################################################################
|
|
||||||
displayName: Linux Agent (arm64)
|
|
||||||
pool:
|
|
||||||
vmImage: ubuntu-16.04
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# Steps template for non-windows platform
|
|
||||||
- template: nonwindows.template.yml
|
|
||||||
parameters:
|
|
||||||
targetRuntime: linux-arm64
|
|
||||||
|
|
||||||
# Create agent package zip
|
|
||||||
- script: ./dev.sh package Release linux-arm64
|
|
||||||
workingDirectory: src
|
|
||||||
displayName: Package Release
|
|
||||||
|
|
||||||
# Upload agent package zip as build artifact
|
|
||||||
- task: PublishBuildArtifacts@1
|
|
||||||
displayName: Publish Artifact (Linux ARM64)
|
|
||||||
inputs:
|
|
||||||
pathToPublish: _package
|
|
||||||
artifactName: runners
|
|
||||||
artifactType: container
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
- job: build_linux_agent_arm
|
|
||||||
################################################################################
|
|
||||||
displayName: Linux Agent (arm)
|
|
||||||
pool:
|
|
||||||
vmImage: ubuntu-16.04
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# Steps template for non-windows platform
|
|
||||||
- template: nonwindows.template.yml
|
|
||||||
parameters:
|
|
||||||
targetRuntime: linux-arm
|
|
||||||
|
|
||||||
# Create agent package zip
|
|
||||||
- script: ./dev.sh package Release linux-arm
|
|
||||||
workingDirectory: src
|
|
||||||
displayName: Package Release
|
|
||||||
|
|
||||||
# Upload agent package zip as build artifact
|
|
||||||
- task: PublishBuildArtifacts@1
|
|
||||||
displayName: Publish Artifact (Linux ARM)
|
|
||||||
inputs:
|
|
||||||
pathToPublish: _package
|
|
||||||
artifactName: runners
|
|
||||||
artifactType: container
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
- job: build_osx_agent_x64
|
|
||||||
################################################################################
|
################################################################################
|
||||||
displayName: macOS Agent (x64)
|
displayName: macOS Agent (x64)
|
||||||
pool:
|
pool:
|
||||||
@@ -130,17 +74,15 @@ stages:
|
|||||||
|
|
||||||
# Steps template for non-windows platform
|
# Steps template for non-windows platform
|
||||||
- template: nonwindows.template.yml
|
- template: nonwindows.template.yml
|
||||||
parameters:
|
|
||||||
targetRuntime: osx-x64
|
|
||||||
|
|
||||||
# Create agent package zip
|
# Create agent package zip
|
||||||
- script: ./dev.sh package Release osx-x64
|
- script: ./dev.sh package Release
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Package Release
|
displayName: Package Release
|
||||||
|
|
||||||
# Upload agent package zip as build artifact
|
# Upload agent package zip as build artifact
|
||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Publish Artifact (OSX x64)
|
displayName: Publish Artifact (OSX)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
@@ -156,7 +98,7 @@ stages:
|
|||||||
pool:
|
pool:
|
||||||
name: ProductionRMAgents
|
name: ProductionRMAgents
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# Download all agent packages from all previous phases
|
# Download all agent packages from all previous phases
|
||||||
- task: DownloadBuildArtifacts@0
|
- task: DownloadBuildArtifacts@0
|
||||||
displayName: Download Agent Packages
|
displayName: Download Agent Packages
|
||||||
@@ -221,17 +163,15 @@ stages:
|
|||||||
$releaseCreated = Invoke-RestMethod @releaseParams
|
$releaseCreated = Invoke-RestMethod @releaseParams
|
||||||
Write-Host $releaseCreated
|
Write-Host $releaseCreated
|
||||||
$releaseId = $releaseCreated.id
|
$releaseId = $releaseCreated.id
|
||||||
Get-ChildItem -LiteralPath "$(System.ArtifactsDirectory)/runners" | ForEach-Object {
|
$assets = [System.IO.File]::ReadAllText("$(Build.SourcesDirectory)\assets.json").Replace("<RUNNER_VERSION>","$(ReleaseAgentVersion)")
|
||||||
Write-Host "Uploading $_ as GitHub release assets"
|
$assetsParams = @{
|
||||||
$assetsParams = @{
|
Uri = "https://uploads.github.com/repos/actions/runner/releases/$releaseId/assets?name=assets.json"
|
||||||
Uri = "https://uploads.github.com/repos/actions/runner/releases/$releaseId/assets?name=$($_.Name)"
|
Method = 'POST';
|
||||||
Method = 'POST';
|
Headers = @{
|
||||||
Headers = @{
|
Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("github:$(GithubToken)"));
|
||||||
Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("github:$(GithubToken)"));
|
}
|
||||||
}
|
ContentType = 'application/octet-stream';
|
||||||
ContentType = 'application/octet-stream';
|
Body = [system.Text.Encoding]::UTF8.GetBytes($assets)
|
||||||
Body = [System.IO.File]::ReadAllBytes($_.FullName)
|
|
||||||
}
|
|
||||||
Invoke-RestMethod @assetsParams
|
|
||||||
}
|
}
|
||||||
|
Invoke-RestMethod @assetsParams
|
||||||
displayName: Create agent release on Github
|
displayName: Create agent release on Github
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# Contribution guide for developers
|
# Contribute (Dev)
|
||||||
|
|
||||||
## Required Dev Dependencies
|
## Dev Dependencies
|
||||||
|
|
||||||
 Git for Windows [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
 Git for Windows [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
||||||
|
|
||||||
## To Build, Test, Layout
|
## Build, Test, Layout
|
||||||
|
|
||||||
Navigate to the `src` directory and run the following command:
|
From src:
|
||||||
|
|
||||||
 `dev {command}`
|
 `dev {command}`
|
||||||
|
|
||||||
@@ -14,12 +14,13 @@ Navigate to the `src` directory and run the following command:
|
|||||||
|
|
||||||
**Commands:**
|
**Commands:**
|
||||||
|
|
||||||
* `layout` (`l`): Run first time to create a full agent layout in `{root}/_layout`
|
`layout` (`l`): Run first time to create a full agent layout in {root}/_layout
|
||||||
* `build` (`b`): Build everything and update agent layout folder
|
|
||||||
* `test` (`t`): Build agent binaries and run unit tests
|
|
||||||
|
|
||||||
Sample developer flow:
|
`build` (`b`): build everything and update agent layout folder
|
||||||
|
|
||||||
|
`test` (`t`): build agent binaries and run unit tests
|
||||||
|
|
||||||
|
Normal dev flow:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/actions/runner
|
git clone https://github.com/actions/runner
|
||||||
cd ./src
|
cd ./src
|
||||||
@@ -36,5 +37,5 @@ cd ./src
|
|||||||
|
|
||||||
## Styling
|
## Styling
|
||||||
|
|
||||||
We use the .NET Foundation and CoreCLR style guidelines [located here](
|
We use the dotnet foundation and CoreCLR style guidelines [located here](
|
||||||
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md)
|
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
- macOS High Sierra (10.13) and later versions
|
- macOS Sierra (10.12) and later versions
|
||||||
|
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore2x)
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
- Windows 7 64-bit
|
- Windows 7 64-bit
|
||||||
- Windows 8.1 64-bit
|
- Windows 8.1 64-bit
|
||||||
- Windows 10 64-bit
|
- Windows 10 64-bit
|
||||||
|
- Windows Server 2008 R2 SP1 64-bit
|
||||||
- Windows Server 2012 R2 64-bit
|
- Windows Server 2012 R2 64-bit
|
||||||
- Windows Server 2016 64-bit
|
- Windows Server 2016 64-bit
|
||||||
- Windows Server 2019 64-bit
|
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
parameters:
|
|
||||||
targetRuntime: ''
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# Build agent layout
|
# Build agent layout
|
||||||
- script: ./dev.sh layout Release ${{ parameters.targetRuntime }}
|
- script: ./dev.sh layout Release
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Build & Layout Release ${{ parameters.targetRuntime }}
|
displayName: Build & Layout Release
|
||||||
|
|
||||||
# Run test
|
# Run test
|
||||||
- script: ./dev.sh test
|
- script: ./dev.sh test
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Test
|
displayName: Test
|
||||||
condition: and(ne('${{ parameters.targetRuntime }}', 'linux-arm64'), ne('${{ parameters.targetRuntime }}', 'linux-arm'))
|
|
||||||
|
|
||||||
# # Publish test results
|
# # Publish test results
|
||||||
# - task: PublishTestResults@2
|
# - task: PublishTestResults@2
|
||||||
|
|||||||
@@ -1,70 +1,43 @@
|
|||||||
## Features
|
## Features
|
||||||
- Added Proxy Support for self-hosted runner. (#206)
|
- Added commands to enable or disable echoing of commands (#139)
|
||||||
- Introduce `--name` configure argument for runner name. (#217)
|
|
||||||
- Better repo matching for issue file path (checkout v2 related) (#208)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- N/A
|
- Do not retry uploads on 4xx Errors for Artifact Upload Service (#131)
|
||||||
|
- Actions cache no longer incorrectly caches the action if the tag was updated for self hosted runners (#148)
|
||||||
|
- Disabled echoing of commands on add-mask, debug, warning and error commands (#158)
|
||||||
|
- HashFile now is correctly configured to only support basic globbing and globstar (#149)
|
||||||
|
- HashFile now sets a default root and handles Windows paths correctly (#151)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- Runner code cleanup (#197, #209, #214, #219)
|
- N/A
|
||||||
- Update node external to 12.13.1 (#215)
|
|
||||||
|
## Agent Downloads
|
||||||
|
|
||||||
|
| | Package |
|
||||||
|
| ------- | ----------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Windows x64 | [actions-runner-win-x64-<RUNNER_VERSION>.zip](https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip) |
|
||||||
|
| macOS | [actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz](https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz) |
|
||||||
|
| Linux x64 | [actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz](https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz) |
|
||||||
|
|
||||||
|
After Download:
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
We recommend configuring the runner under "<DRIVE>:\actions-runner". This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows
|
|
||||||
```
|
``` bash
|
||||||
// Create a folder under the drive root
|
C:\> mkdir myagent && cd myagent
|
||||||
mkdir \actions-runner ; cd \actions-runner
|
C:\myagent> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
||||||
// Download the latest runner package
|
|
||||||
Invoke-WebRequest -Uri https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
|
|
||||||
// Extract the installer
|
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
|
||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## OSX
|
## OSX
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
// Create a folder
|
~/$ mkdir myagent && cd myagent
|
||||||
mkdir actions-runner && cd actions-runner
|
~/myagent$ tar xzf ~/Downloads/actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
||||||
// Download the latest runner package
|
|
||||||
curl -O https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
|
||||||
// Extract the installer
|
|
||||||
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux x64
|
## Linux x64
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
// Create a folder
|
~/$ mkdir myagent && cd myagent
|
||||||
mkdir actions-runner && cd actions-runner
|
~/myagent$ tar xzf ~/Downloads/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
||||||
// Download the latest runner package
|
|
||||||
curl -O https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
|
||||||
// Extract the installer
|
|
||||||
tar xzf ./actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux arm64 (Pre-release)
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
// Create a folder
|
|
||||||
mkdir actions-runner && cd actions-runner
|
|
||||||
// Download the latest runner package
|
|
||||||
curl -O https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz
|
|
||||||
// Extract the installer
|
|
||||||
tar xzf ./actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux arm (Pre-release)
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
// Create a folder
|
|
||||||
mkdir actions-runner && cd actions-runner
|
|
||||||
// Download the latest runner package
|
|
||||||
curl -O https://githubassets.azureedge.net/runners/<RUNNER_VERSION>/actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz
|
|
||||||
// Extract the installer
|
|
||||||
tar xzf ./actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using your self hosted runner
|
|
||||||
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<!-- Detect OS for build -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">Windows</BUILD_OS>
|
|
||||||
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">OSX</BUILD_OS>
|
|
||||||
<BUILD_OS Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">Linux</BUILD_OS>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Set OS vars -->
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows'">
|
|
||||||
<DefineConstants>$(DefineConstants);OS_WINDOWS</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
|
|
||||||
<DefineConstants>$(DefineConstants);OS_OSX</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux'">
|
|
||||||
<DefineConstants>$(DefineConstants);OS_LINUX</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Set Platform/bitness vars -->
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND ('$(PackageRuntime)' == 'win-x64' OR '$(PackageRuntime)' == '')">
|
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
|
||||||
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
|
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
|
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'linux-arm'">
|
|
||||||
<DefineConstants>$(DefineConstants);ARM</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND '$(PackageRuntime)' == 'linux-arm64'">
|
|
||||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Set TRACE/DEBUG vars -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
|
||||||
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
27
src/Misc/dotnet-install.ps1
vendored
27
src/Misc/dotnet-install.ps1
vendored
@@ -167,7 +167,7 @@ function Get-CLIArchitecture-From-Architecture([string]$Architecture) {
|
|||||||
{ $_ -eq "x86" } { return "x86" }
|
{ $_ -eq "x86" } { return "x86" }
|
||||||
{ $_ -eq "arm" } { return "arm" }
|
{ $_ -eq "arm" } { return "arm" }
|
||||||
{ $_ -eq "arm64" } { return "arm64" }
|
{ $_ -eq "arm64" } { return "arm64" }
|
||||||
default { throw "Architecture not supported. If you think this is a bug, report it at https://github.com/dotnet/sdk/issues" }
|
default { throw "Architecture not supported. If you think this is a bug, report it at https://github.com/dotnet/cli/issues" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,12 +309,14 @@ function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
|||||||
|
|
||||||
If (-Not (Test-Path $JSonFile)) {
|
If (-Not (Test-Path $JSonFile)) {
|
||||||
throw "Unable to find '$JSonFile'"
|
throw "Unable to find '$JSonFile'"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throw "Json file unreadable: '$JSonFile'"
|
throw "Json file unreadable: '$JSonFile'"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
if ($JSonContent) {
|
if ($JSonContent) {
|
||||||
try {
|
try {
|
||||||
@@ -328,13 +330,16 @@ function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
|||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
throw "Unable to parse the SDK node in '$JSonFile'"
|
throw "Unable to parse the SDK node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw "Unable to find the SDK node in '$JSonFile'"
|
throw "Unable to find the SDK node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
If ($Version -eq $null) {
|
If ($Version -eq $null) {
|
||||||
throw "Unable to find the SDK:version node in '$JSonFile'"
|
throw "Unable to find the SDK:version node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
return $Version
|
return $Version
|
||||||
}
|
}
|
||||||
@@ -425,7 +430,7 @@ function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePath
|
|||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
$DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion
|
$DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion
|
||||||
Say-Verbose "Is-Dotnet-Package-Installed: DotnetPackagePath=$DotnetPackagePath"
|
Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath"
|
||||||
return Test-Path $DotnetPackagePath -PathType Container
|
return Test-Path $DotnetPackagePath -PathType Container
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -658,22 +663,8 @@ if ($DownloadFailed) {
|
|||||||
Say "Extracting zip from $DownloadLink"
|
Say "Extracting zip from $DownloadLink"
|
||||||
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
|
Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot
|
||||||
|
|
||||||
# Check if the SDK version is installed; if not, fail the installation.
|
# Check if the SDK version is now installed; if not, fail the installation.
|
||||||
$isAssetInstalled = $false
|
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
|
||||||
|
|
||||||
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
|
||||||
if ($SpecificVersion -Match "rtm" -or $SpecificVersion -Match "servicing") {
|
|
||||||
$ReleaseVersion = $SpecificVersion.Split("-")[0]
|
|
||||||
Say-Verbose "Checking installation: version = $ReleaseVersion"
|
|
||||||
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $ReleaseVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if the SDK version is installed.
|
|
||||||
if (!$isAssetInstalled) {
|
|
||||||
Say-Verbose "Checking installation: version = $SpecificVersion"
|
|
||||||
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$isAssetInstalled) {
|
if (!$isAssetInstalled) {
|
||||||
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error."
|
throw "`"$assetName`" with version = $SpecificVersion failed to install with an unknown error."
|
||||||
}
|
}
|
||||||
|
|||||||
70
src/Misc/dotnet-install.sh
vendored
70
src/Misc/dotnet-install.sh
vendored
@@ -144,7 +144,7 @@ get_linux_platform_name() {
|
|||||||
else
|
else
|
||||||
if [ -e /etc/os-release ]; then
|
if [ -e /etc/os-release ]; then
|
||||||
. /etc/os-release
|
. /etc/os-release
|
||||||
echo "$ID${VERSION_ID:+.${VERSION_ID}}"
|
echo "$ID.$VERSION_ID"
|
||||||
return 0
|
return 0
|
||||||
elif [ -e /etc/redhat-release ]; then
|
elif [ -e /etc/redhat-release ]; then
|
||||||
local redhatRelease=$(</etc/redhat-release)
|
local redhatRelease=$(</etc/redhat-release)
|
||||||
@@ -159,10 +159,6 @@ get_linux_platform_name() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
is_musl_based_distro() {
|
|
||||||
(ldd --version 2>&1 || true) | grep -q musl
|
|
||||||
}
|
|
||||||
|
|
||||||
get_current_os_name() {
|
get_current_os_name() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
@@ -177,10 +173,10 @@ get_current_os_name() {
|
|||||||
local linux_platform_name
|
local linux_platform_name
|
||||||
linux_platform_name="$(get_linux_platform_name)" || { echo "linux" && return 0 ; }
|
linux_platform_name="$(get_linux_platform_name)" || { echo "linux" && return 0 ; }
|
||||||
|
|
||||||
if [ "$linux_platform_name" = "rhel.6" ]; then
|
if [[ $linux_platform_name == "rhel.6" ]]; then
|
||||||
echo $linux_platform_name
|
echo $linux_platform_name
|
||||||
return 0
|
return 0
|
||||||
elif is_musl_based_distro; then
|
elif [[ $linux_platform_name == alpine* ]]; then
|
||||||
echo "linux-musl"
|
echo "linux-musl"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@@ -206,7 +202,7 @@ get_legacy_os_name() {
|
|||||||
else
|
else
|
||||||
if [ -e /etc/os-release ]; then
|
if [ -e /etc/os-release ]; then
|
||||||
. /etc/os-release
|
. /etc/os-release
|
||||||
os=$(get_legacy_os_name_from_platform "$ID${VERSION_ID:+.${VERSION_ID}}" || echo "")
|
os=$(get_legacy_os_name_from_platform "$ID.$VERSION_ID" || echo "")
|
||||||
if [ -n "$os" ]; then
|
if [ -n "$os" ]; then
|
||||||
echo "$os"
|
echo "$os"
|
||||||
return 0
|
return 0
|
||||||
@@ -249,29 +245,20 @@ check_pre_reqs() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(uname)" = "Linux" ]; then
|
if [ "$(uname)" = "Linux" ]; then
|
||||||
if is_musl_based_distro; then
|
if [ ! -x "$(command -v ldconfig)" ]; then
|
||||||
if ! command -v scanelf > /dev/null; then
|
echo "ldconfig is not in PATH, trying /sbin/ldconfig."
|
||||||
say_warning "scanelf not found, please install pax-utils package."
|
LDCONFIG_COMMAND="/sbin/ldconfig"
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
LDCONFIG_COMMAND="scanelf --ldpath -BF '%f'"
|
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libintl)" ] && say_warning "Unable to locate libintl. Probable prerequisite missing; install libintl (or gettext)."
|
|
||||||
else
|
else
|
||||||
if [ ! -x "$(command -v ldconfig)" ]; then
|
LDCONFIG_COMMAND="ldconfig"
|
||||||
say_verbose "ldconfig is not in PATH, trying /sbin/ldconfig."
|
|
||||||
LDCONFIG_COMMAND="/sbin/ldconfig"
|
|
||||||
else
|
|
||||||
LDCONFIG_COMMAND="ldconfig"
|
|
||||||
fi
|
|
||||||
local librarypath=${LD_LIBRARY_PATH:-}
|
|
||||||
LDCONFIG_COMMAND="$LDCONFIG_COMMAND -NXv ${librarypath//:/ }"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep zlib)" ] && say_warning "Unable to locate zlib. Probable prerequisite missing; install zlib."
|
local librarypath=${LD_LIBRARY_PATH:-}
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep ssl)" ] && say_warning "Unable to locate libssl. Probable prerequisite missing; install libssl."
|
LDCONFIG_COMMAND="$LDCONFIG_COMMAND -NXv ${librarypath//:/ }"
|
||||||
|
|
||||||
|
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libunwind)" ] && say_warning "Unable to locate libunwind. Probable prerequisite missing; install libunwind."
|
||||||
|
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libssl)" ] && say_warning "Unable to locate libssl. Probable prerequisite missing; install libssl."
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libicu)" ] && say_warning "Unable to locate libicu. Probable prerequisite missing; install libicu."
|
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libicu)" ] && say_warning "Unable to locate libicu. Probable prerequisite missing; install libicu."
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep lttng)" ] && say_warning "Unable to locate liblttng. Probable prerequisite missing; install libcurl."
|
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep -F libcurl.so)" ] && say_warning "Unable to locate libcurl. Probable prerequisite missing; install libcurl."
|
||||||
[ -z "$($LDCONFIG_COMMAND 2>/dev/null | grep libcurl)" ] && say_warning "Unable to locate libcurl. Probable prerequisite missing; install libcurl."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -373,7 +360,7 @@ get_normalized_architecture_from_architecture() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/sdk/issues"
|
say_err "Architecture \`$architecture\` not supported. If you think this is a bug, report it at https://github.com/dotnet/cli/issues"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +471,6 @@ parse_jsonfile_for_version() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
unset IFS;
|
|
||||||
echo "$version_info"
|
echo "$version_info"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -645,7 +631,7 @@ copy_files_or_dirs_from_list() {
|
|||||||
local osname="$(get_current_os_name)"
|
local osname="$(get_current_os_name)"
|
||||||
local override_switch=$(
|
local override_switch=$(
|
||||||
if [ "$override" = false ]; then
|
if [ "$override" = false ]; then
|
||||||
if [ "$osname" = "linux-musl" ]; then
|
if [[ "$osname" == "linux-musl" ]]; then
|
||||||
printf -- "-u";
|
printf -- "-u";
|
||||||
else
|
else
|
||||||
printf -- "-n";
|
printf -- "-n";
|
||||||
@@ -854,27 +840,13 @@ install_dotnet() {
|
|||||||
say "Extracting zip from $download_link"
|
say "Extracting zip from $download_link"
|
||||||
extract_dotnet_package "$zip_path" "$install_root"
|
extract_dotnet_package "$zip_path" "$install_root"
|
||||||
|
|
||||||
# Check if the SDK version is installed; if not, fail the installation.
|
# Check if the SDK version is now installed; if not, fail the installation.
|
||||||
# if the version contains "RTM" or "servicing"; check if a 'release-type' SDK version is installed.
|
if ! is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
|
||||||
if [[ $specific_version == *"rtm"* || $specific_version == *"servicing"* ]]; then
|
say_err "\`$asset_name\` with version = $specific_version failed to install with an unknown error."
|
||||||
IFS='-'
|
return 1
|
||||||
read -ra verArr <<< "$specific_version"
|
|
||||||
release_version="${verArr[0]}"
|
|
||||||
unset IFS;
|
|
||||||
say_verbose "Checking installation: version = $release_version"
|
|
||||||
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$release_version"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the standard SDK version is installed.
|
return 0
|
||||||
say_verbose "Checking installation: version = $specific_version"
|
|
||||||
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
say_err "\`$asset_name\` with version = $specific_version failed to install with an unknown error."
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args=("$@")
|
args=("$@")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ PACKAGERUNTIME=$1
|
|||||||
PRECACHE=$2
|
PRECACHE=$2
|
||||||
|
|
||||||
NODE_URL=https://nodejs.org/dist
|
NODE_URL=https://nodejs.org/dist
|
||||||
NODE12_VERSION="12.13.1"
|
NODE12_VERSION="12.4.0"
|
||||||
|
|
||||||
get_abs_path() {
|
get_abs_path() {
|
||||||
# exploits the fact that pwd will print abs path when no args
|
# exploits the fact that pwd will print abs path when no args
|
||||||
@@ -123,9 +123,9 @@ function acquireExternalTool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/win-x64/node.exe" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/win-x64/node.lib" node12/bin
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -136,14 +136,11 @@ if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
|||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
# Download the external tools common across Linux PACKAGERUNTIMEs (excluding OSX).
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-x64" || "$PACKAGERUNTIME" == "rhel.6-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
# TODO: Repath this blob to use a consistent version format (_ vs .)
|
||||||
fi
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12_4_0/alpine/node-v${NODE12_VERSION}-alpine.tar.gz" node12_alpine
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ varCheckList=(
|
|||||||
'GRADLE_HOME'
|
'GRADLE_HOME'
|
||||||
'NVM_BIN'
|
'NVM_BIN'
|
||||||
'NVM_PATH'
|
'NVM_PATH'
|
||||||
|
'VSTS_HTTP_PROXY'
|
||||||
|
'VSTS_HTTP_PROXY_USERNAME'
|
||||||
|
'VSTS_HTTP_PROXY_PASSWORD'
|
||||||
'LD_LIBRARY_PATH'
|
'LD_LIBRARY_PATH'
|
||||||
'PERL5LIB'
|
'PERL5LIB'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -15,12 +13,24 @@ namespace GitHub.Runner.Common
|
|||||||
[DataContract]
|
[DataContract]
|
||||||
public sealed class RunnerSettings
|
public sealed class RunnerSettings
|
||||||
{
|
{
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public bool AcceptTeeEula { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public int AgentId { get; set; }
|
public int AgentId { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public string NotificationPipeName { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public string NotificationSocketAddress { get; set; }
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public bool SkipCapabilitiesScan { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public bool SkipSessionRecover { get; set; }
|
public bool SkipSessionRecover { get; set; }
|
||||||
|
|
||||||
@@ -41,34 +51,6 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string MonitorSocketAddress { get; set; }
|
public string MonitorSocketAddress { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
// Computed property for convenience. Can either return:
|
|
||||||
// 1. If runner was configured at the repo level, returns something like: "myorg/myrepo"
|
|
||||||
// 2. If runner was configured at the org level, returns something like: "myorg"
|
|
||||||
/// </summary>
|
|
||||||
public string RepoOrOrgName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Uri accountUri = new Uri(this.ServerUrl);
|
|
||||||
string repoOrOrgName = string.Empty;
|
|
||||||
|
|
||||||
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Uri gitHubUrl = new Uri(this.GitHubUrl);
|
|
||||||
|
|
||||||
// Use the "NWO part" from the GitHub URL path
|
|
||||||
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
return repoOrOrgName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ namespace GitHub.Runner.Common
|
|||||||
Service,
|
Service,
|
||||||
CredentialStore,
|
CredentialStore,
|
||||||
Certificates,
|
Certificates,
|
||||||
|
Proxy,
|
||||||
|
ProxyCredentials,
|
||||||
|
ProxyBypass,
|
||||||
Options,
|
Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,28 +93,43 @@ namespace GitHub.Runner.Common
|
|||||||
//validArgs array as well present in the CommandSettings.cs
|
//validArgs array as well present in the CommandSettings.cs
|
||||||
public static class Args
|
public static class Args
|
||||||
{
|
{
|
||||||
|
public static readonly string Agent = "agent";
|
||||||
public static readonly string Auth = "auth";
|
public static readonly string Auth = "auth";
|
||||||
|
public static readonly string CollectionName = "collectionname";
|
||||||
|
public static readonly string DeploymentGroupName = "deploymentgroupname";
|
||||||
|
public static readonly string DeploymentPoolName = "deploymentpoolname";
|
||||||
|
public static readonly string DeploymentGroupTags = "deploymentgrouptags";
|
||||||
|
public static readonly string MachineGroupName = "machinegroupname";
|
||||||
|
public static readonly string MachineGroupTags = "machinegrouptags";
|
||||||
|
public static readonly string Matrix = "matrix";
|
||||||
public static readonly string MonitorSocketAddress = "monitorsocketaddress";
|
public static readonly string MonitorSocketAddress = "monitorsocketaddress";
|
||||||
public static readonly string Name = "name";
|
public static readonly string NotificationPipeName = "notificationpipename";
|
||||||
|
public static readonly string NotificationSocketAddress = "notificationsocketaddress";
|
||||||
public static readonly string Pool = "pool";
|
public static readonly string Pool = "pool";
|
||||||
|
public static readonly string ProjectName = "projectname";
|
||||||
|
public static readonly string ProxyUrl = "proxyurl";
|
||||||
|
public static readonly string ProxyUserName = "proxyusername";
|
||||||
public static readonly string SslCACert = "sslcacert";
|
public static readonly string SslCACert = "sslcacert";
|
||||||
public static readonly string SslClientCert = "sslclientcert";
|
public static readonly string SslClientCert = "sslclientcert";
|
||||||
public static readonly string SslClientCertKey = "sslclientcertkey";
|
public static readonly string SslClientCertKey = "sslclientcertkey";
|
||||||
public static readonly string SslClientCertArchive = "sslclientcertarchive";
|
public static readonly string SslClientCertArchive = "sslclientcertarchive";
|
||||||
|
public static readonly string SslClientCertPassword = "sslclientcertpassword";
|
||||||
public static readonly string StartupType = "startuptype";
|
public static readonly string StartupType = "startuptype";
|
||||||
public static readonly string Url = "url";
|
public static readonly string Url = "url";
|
||||||
public static readonly string UserName = "username";
|
public static readonly string UserName = "username";
|
||||||
public static readonly string WindowsLogonAccount = "windowslogonaccount";
|
public static readonly string WindowsLogonAccount = "windowslogonaccount";
|
||||||
public static readonly string Work = "work";
|
public static readonly string Work = "work";
|
||||||
|
public static readonly string Yml = "yml";
|
||||||
|
|
||||||
// Secret args. Must be added to the "Secrets" getter as well.
|
// Secret args. Must be added to the "Secrets" getter as well.
|
||||||
public static readonly string Password = "password";
|
public static readonly string Password = "password";
|
||||||
public static readonly string SslClientCertPassword = "sslclientcertpassword";
|
public static readonly string ProxyPassword = "proxypassword";
|
||||||
public static readonly string Token = "token";
|
public static readonly string Token = "token";
|
||||||
public static readonly string WindowsLogonPassword = "windowslogonpassword";
|
public static readonly string WindowsLogonPassword = "windowslogonpassword";
|
||||||
public static string[] Secrets => new[]
|
public static string[] Secrets => new[]
|
||||||
{
|
{
|
||||||
Password,
|
Password,
|
||||||
|
ProxyPassword,
|
||||||
SslClientCertPassword,
|
SslClientCertPassword,
|
||||||
Token,
|
Token,
|
||||||
WindowsLogonPassword,
|
WindowsLogonPassword,
|
||||||
@@ -121,6 +139,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static class Commands
|
public static class Commands
|
||||||
{
|
{
|
||||||
public static readonly string Configure = "configure";
|
public static readonly string Configure = "configure";
|
||||||
|
public static readonly string LocalRun = "localRun";
|
||||||
public static readonly string Remove = "remove";
|
public static readonly string Remove = "remove";
|
||||||
public static readonly string Run = "run";
|
public static readonly string Run = "run";
|
||||||
public static readonly string Warmup = "warmup";
|
public static readonly string Warmup = "warmup";
|
||||||
@@ -130,16 +149,26 @@ namespace GitHub.Runner.Common
|
|||||||
//validFlags array as well present in the CommandSettings.cs
|
//validFlags array as well present in the CommandSettings.cs
|
||||||
public static class Flags
|
public static class Flags
|
||||||
{
|
{
|
||||||
|
public static readonly string AcceptTeeEula = "acceptteeeula";
|
||||||
|
public static readonly string AddDeploymentGroupTags = "adddeploymentgrouptags";
|
||||||
|
public static readonly string AddMachineGroupTags = "addmachinegrouptags";
|
||||||
public static readonly string Commit = "commit";
|
public static readonly string Commit = "commit";
|
||||||
|
public static readonly string DeploymentGroup = "deploymentgroup";
|
||||||
|
public static readonly string DeploymentPool = "deploymentpool";
|
||||||
|
public static readonly string OverwriteAutoLogon = "overwriteautologon";
|
||||||
public static readonly string GitUseSChannel = "gituseschannel";
|
public static readonly string GitUseSChannel = "gituseschannel";
|
||||||
public static readonly string Help = "help";
|
public static readonly string Help = "help";
|
||||||
|
public static readonly string MachineGroup = "machinegroup";
|
||||||
public static readonly string Replace = "replace";
|
public static readonly string Replace = "replace";
|
||||||
|
public static readonly string NoRestart = "norestart";
|
||||||
public static readonly string LaunchBrowser = "launchbrowser";
|
public static readonly string LaunchBrowser = "launchbrowser";
|
||||||
public static readonly string Once = "once";
|
public static readonly string Once = "once";
|
||||||
|
public static readonly string RunAsAutoLogon = "runasautologon";
|
||||||
public static readonly string RunAsService = "runasservice";
|
public static readonly string RunAsService = "runasservice";
|
||||||
public static readonly string SslSkipCertValidation = "sslskipcertvalidation";
|
public static readonly string SslSkipCertValidation = "sslskipcertvalidation";
|
||||||
public static readonly string Unattended = "unattended";
|
public static readonly string Unattended = "unattended";
|
||||||
public static readonly string Version = "version";
|
public static readonly string Version = "version";
|
||||||
|
public static readonly string WhatIf = "whatif";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,9 +202,14 @@ namespace GitHub.Runner.Common
|
|||||||
public static class Expressions
|
public static class Expressions
|
||||||
{
|
{
|
||||||
public static readonly string Always = "always";
|
public static readonly string Always = "always";
|
||||||
|
public static readonly string Canceled = "canceled";
|
||||||
public static readonly string Cancelled = "cancelled";
|
public static readonly string Cancelled = "cancelled";
|
||||||
|
public static readonly string Failed = "failed";
|
||||||
public static readonly string Failure = "failure";
|
public static readonly string Failure = "failure";
|
||||||
public static readonly string Success = "success";
|
public static readonly string Success = "success";
|
||||||
|
public static readonly string Succeeded = "succeeded";
|
||||||
|
public static readonly string SucceededOrFailed = "succeededOrFailed";
|
||||||
|
public static readonly string Variables = "variables";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Path
|
public static class Path
|
||||||
@@ -187,7 +221,9 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string ExternalsDirectory = "externals";
|
public static readonly string ExternalsDirectory = "externals";
|
||||||
public static readonly string RunnerDiagnosticLogPrefix = "Runner_";
|
public static readonly string RunnerDiagnosticLogPrefix = "Runner_";
|
||||||
public static readonly string TempDirectory = "_temp";
|
public static readonly string TempDirectory = "_temp";
|
||||||
|
public static readonly string TeeDirectory = "tee";
|
||||||
public static readonly string ToolDirectory = "_tool";
|
public static readonly string ToolDirectory = "_tool";
|
||||||
|
public static readonly string TaskJsonFile = "task.json";
|
||||||
public static readonly string UpdateDirectory = "_update";
|
public static readonly string UpdateDirectory = "_update";
|
||||||
public static readonly string WorkDirectory = "_work";
|
public static readonly string WorkDirectory = "_work";
|
||||||
public static readonly string WorkerDiagnosticLogPrefix = "Worker_";
|
public static readonly string WorkerDiagnosticLogPrefix = "Worker_";
|
||||||
@@ -208,14 +244,99 @@ namespace GitHub.Runner.Common
|
|||||||
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Agent
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Keep alphabetical
|
||||||
|
//
|
||||||
|
public static readonly string AcceptTeeEula = "agent.acceptteeeula";
|
||||||
|
public static readonly string AllowAllEndpoints = "agent.allowAllEndpoints"; // remove after sprint 120 or so.
|
||||||
|
public static readonly string AllowAllSecureFiles = "agent.allowAllSecureFiles"; // remove after sprint 121 or so.
|
||||||
|
public static readonly string BuildDirectory = "agent.builddirectory";
|
||||||
|
public static readonly string ContainerId = "agent.containerid";
|
||||||
|
public static readonly string ContainerNetwork = "agent.containernetwork";
|
||||||
|
public static readonly string HomeDirectory = "agent.homedirectory";
|
||||||
|
public static readonly string Id = "agent.id";
|
||||||
|
public static readonly string GitUseSChannel = "agent.gituseschannel";
|
||||||
|
public static readonly string JobName = "agent.jobname";
|
||||||
|
public static readonly string MachineName = "agent.machinename";
|
||||||
|
public static readonly string Name = "agent.name";
|
||||||
|
public static readonly string OS = "agent.os";
|
||||||
|
public static readonly string OSArchitecture = "agent.osarchitecture";
|
||||||
|
public static readonly string OSVersion = "agent.osversion";
|
||||||
|
public static readonly string ProxyUrl = "agent.proxyurl";
|
||||||
|
public static readonly string ProxyUsername = "agent.proxyusername";
|
||||||
|
public static readonly string ProxyPassword = "agent.proxypassword";
|
||||||
|
public static readonly string ProxyBypassList = "agent.proxybypasslist";
|
||||||
|
public static readonly string RetainDefaultEncoding = "agent.retainDefaultEncoding";
|
||||||
|
public static readonly string RootDirectory = "agent.RootDirectory";
|
||||||
|
public static readonly string RunMode = "agent.runmode";
|
||||||
|
public static readonly string ServerOMDirectory = "agent.ServerOMDirectory";
|
||||||
|
public static readonly string ServicePortPrefix = "agent.services";
|
||||||
|
public static readonly string SslCAInfo = "agent.cainfo";
|
||||||
|
public static readonly string SslClientCert = "agent.clientcert";
|
||||||
|
public static readonly string SslClientCertKey = "agent.clientcertkey";
|
||||||
|
public static readonly string SslClientCertArchive = "agent.clientcertarchive";
|
||||||
|
public static readonly string SslClientCertPassword = "agent.clientcertpassword";
|
||||||
|
public static readonly string SslSkipCertValidation = "agent.skipcertvalidation";
|
||||||
|
public static readonly string TempDirectory = "agent.TempDirectory";
|
||||||
|
public static readonly string ToolsDirectory = "agent.ToolsDirectory";
|
||||||
|
public static readonly string Version = "agent.version";
|
||||||
|
public static readonly string WorkFolder = "agent.workfolder";
|
||||||
|
public static readonly string WorkingDirectory = "agent.WorkingDirectory";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Build
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Keep alphabetical
|
||||||
|
//
|
||||||
|
public static readonly string ArtifactStagingDirectory = "build.artifactstagingdirectory";
|
||||||
|
public static readonly string BinariesDirectory = "build.binariesdirectory";
|
||||||
|
public static readonly string Number = "build.buildNumber";
|
||||||
|
public static readonly string Clean = "build.clean";
|
||||||
|
public static readonly string DefinitionName = "build.definitionname";
|
||||||
|
public static readonly string GatedRunCI = "build.gated.runci";
|
||||||
|
public static readonly string GatedShelvesetName = "build.gated.shelvesetname";
|
||||||
|
public static readonly string RepoClean = "build.repository.clean";
|
||||||
|
public static readonly string RepoGitSubmoduleCheckout = "build.repository.git.submodulecheckout";
|
||||||
|
public static readonly string RepoId = "build.repository.id";
|
||||||
|
public static readonly string RepoLocalPath = "build.repository.localpath";
|
||||||
|
public static readonly string RepoName = "build.Repository.name";
|
||||||
|
public static readonly string RepoProvider = "build.repository.provider";
|
||||||
|
public static readonly string RepoTfvcWorkspace = "build.repository.tfvc.workspace";
|
||||||
|
public static readonly string RepoUri = "build.repository.uri";
|
||||||
|
public static readonly string SourceBranch = "build.sourcebranch";
|
||||||
|
public static readonly string SourceTfvcShelveset = "build.sourcetfvcshelveset";
|
||||||
|
public static readonly string SourceVersion = "build.sourceversion";
|
||||||
|
public static readonly string SourcesDirectory = "build.sourcesdirectory";
|
||||||
|
public static readonly string StagingDirectory = "build.stagingdirectory";
|
||||||
|
public static readonly string SyncSources = "build.syncSources";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class System
|
public static class System
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Keep alphabetical
|
// Keep alphabetical
|
||||||
//
|
//
|
||||||
public static readonly string AccessToken = "system.accessToken";
|
public static readonly string AccessToken = "system.accessToken";
|
||||||
|
public static readonly string ArtifactsDirectory = "system.artifactsdirectory";
|
||||||
|
public static readonly string CollectionId = "system.collectionid";
|
||||||
public static readonly string Culture = "system.culture";
|
public static readonly string Culture = "system.culture";
|
||||||
|
public static readonly string DefaultWorkingDirectory = "system.defaultworkingdirectory";
|
||||||
|
public static readonly string DefinitionId = "system.definitionid";
|
||||||
|
public static readonly string EnableAccessToken = "system.enableAccessToken";
|
||||||
|
public static readonly string HostType = "system.hosttype";
|
||||||
public static readonly string PhaseDisplayName = "system.phaseDisplayName";
|
public static readonly string PhaseDisplayName = "system.phaseDisplayName";
|
||||||
|
public static readonly string PreferGitFromPath = "system.prefergitfrompath";
|
||||||
|
public static readonly string PullRequestTargetBranchName = "system.pullrequest.targetbranch";
|
||||||
|
public static readonly string SelfManageGitCreds = "system.selfmanagegitcreds";
|
||||||
|
public static readonly string ServerType = "system.servertype";
|
||||||
|
public static readonly string TFServerUrl = "system.TeamFoundationServerUri"; // back compat variable, do not document
|
||||||
|
public static readonly string TeamProject = "system.teamproject";
|
||||||
|
public static readonly string TeamProjectId = "system.teamProjectId";
|
||||||
|
public static readonly string WorkFolder = "system.workfolder";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ namespace GitHub.Runner.Common
|
|||||||
ShutdownReason RunnerShutdownReason { get; }
|
ShutdownReason RunnerShutdownReason { get; }
|
||||||
ISecretMasker SecretMasker { get; }
|
ISecretMasker SecretMasker { get; }
|
||||||
ProductInfoHeaderValue UserAgent { get; }
|
ProductInfoHeaderValue UserAgent { get; }
|
||||||
RunnerWebProxy WebProxy { get; }
|
|
||||||
string GetDirectory(WellKnownDirectory directory);
|
string GetDirectory(WellKnownDirectory directory);
|
||||||
string GetConfigFile(WellKnownConfigFile configFile);
|
string GetConfigFile(WellKnownConfigFile configFile);
|
||||||
Tracing GetTrace(string name);
|
Tracing GetTrace(string name);
|
||||||
@@ -68,14 +67,12 @@ namespace GitHub.Runner.Common
|
|||||||
private IDisposable _diagListenerSubscription;
|
private IDisposable _diagListenerSubscription;
|
||||||
private StartupType _startupType;
|
private StartupType _startupType;
|
||||||
private string _perfFile;
|
private string _perfFile;
|
||||||
private RunnerWebProxy _webProxy = new RunnerWebProxy();
|
|
||||||
|
|
||||||
public event EventHandler Unloading;
|
public event EventHandler Unloading;
|
||||||
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
|
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource.Token;
|
||||||
public ShutdownReason RunnerShutdownReason { get; private set; }
|
public ShutdownReason RunnerShutdownReason { get; private set; }
|
||||||
public ISecretMasker SecretMasker => _secretMasker;
|
public ISecretMasker SecretMasker => _secretMasker;
|
||||||
public ProductInfoHeaderValue UserAgent => _userAgent;
|
public ProductInfoHeaderValue UserAgent => _userAgent;
|
||||||
public RunnerWebProxy WebProxy => _webProxy;
|
|
||||||
public HostContext(string hostType, string logFile = null)
|
public HostContext(string hostType, string logFile = null)
|
||||||
{
|
{
|
||||||
// Validate args.
|
// Validate args.
|
||||||
@@ -150,48 +147,6 @@ namespace GitHub.Runner.Common
|
|||||||
_trace.Error(ex);
|
_trace.Error(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and trace proxy info
|
|
||||||
if (!string.IsNullOrEmpty(WebProxy.HttpProxyAddress))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(WebProxy.HttpProxyUsername) && string.IsNullOrEmpty(WebProxy.HttpProxyPassword))
|
|
||||||
{
|
|
||||||
_trace.Info($"Configuring anonymous proxy {WebProxy.HttpProxyAddress} for all HTTP requests.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Register proxy password as secret
|
|
||||||
if (!string.IsNullOrEmpty(WebProxy.HttpProxyPassword))
|
|
||||||
{
|
|
||||||
this.SecretMasker.AddValue(WebProxy.HttpProxyPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
_trace.Info($"Configuring authenticated proxy {WebProxy.HttpProxyAddress} for all HTTP requests.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(WebProxy.HttpsProxyAddress))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(WebProxy.HttpsProxyUsername) && string.IsNullOrEmpty(WebProxy.HttpsProxyPassword))
|
|
||||||
{
|
|
||||||
_trace.Info($"Configuring anonymous proxy {WebProxy.HttpsProxyAddress} for all HTTPS requests.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Register proxy password as secret
|
|
||||||
if (!string.IsNullOrEmpty(WebProxy.HttpsProxyPassword))
|
|
||||||
{
|
|
||||||
this.SecretMasker.AddValue(WebProxy.HttpsProxyPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
_trace.Info($"Configuring authenticated proxy {WebProxy.HttpsProxyAddress} for all HTTPS requests.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(WebProxy.HttpProxyAddress) && string.IsNullOrEmpty(WebProxy.HttpsProxyAddress))
|
|
||||||
{
|
|
||||||
_trace.Info($"No proxy settings were found based on environmental variables (http_proxy/https_proxy/HTTP_PROXY/HTTPS_PROXY)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RunMode RunMode
|
public RunMode RunMode
|
||||||
@@ -246,8 +201,8 @@ namespace GitHub.Runner.Common
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WellKnownDirectory.Tools:
|
case WellKnownDirectory.Tools:
|
||||||
path = Environment.GetEnvironmentVariable("RUNNER_TOOL_CACHE");
|
// TODO: Coallesce to just check RUNNER_TOOL_CACHE when images stabilize
|
||||||
|
path = Environment.GetEnvironmentVariable("RUNNER_TOOL_CACHE") ?? Environment.GetEnvironmentVariable("RUNNER_TOOLSDIRECTORY") ?? Environment.GetEnvironmentVariable("AGENT_TOOLSDIRECTORY") ?? Environment.GetEnvironmentVariable(Constants.Variables.Agent.ToolsDirectory);
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
path = Path.Combine(
|
path = Path.Combine(
|
||||||
@@ -327,6 +282,24 @@ namespace GitHub.Runner.Common
|
|||||||
".certificates");
|
".certificates");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WellKnownConfigFile.Proxy:
|
||||||
|
path = Path.Combine(
|
||||||
|
GetDirectory(WellKnownDirectory.Root),
|
||||||
|
".proxy");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WellKnownConfigFile.ProxyCredentials:
|
||||||
|
path = Path.Combine(
|
||||||
|
GetDirectory(WellKnownDirectory.Root),
|
||||||
|
".proxycredentials");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WellKnownConfigFile.ProxyBypass:
|
||||||
|
path = Path.Combine(
|
||||||
|
GetDirectory(WellKnownDirectory.Root),
|
||||||
|
".proxybypass");
|
||||||
|
break;
|
||||||
|
|
||||||
case WellKnownConfigFile.Options:
|
case WellKnownConfigFile.Options:
|
||||||
path = Path.Combine(
|
path = Path.Combine(
|
||||||
GetDirectory(WellKnownDirectory.Root),
|
GetDirectory(WellKnownDirectory.Root),
|
||||||
@@ -607,7 +580,8 @@ namespace GitHub.Runner.Common
|
|||||||
public static HttpClientHandler CreateHttpClientHandler(this IHostContext context)
|
public static HttpClientHandler CreateHttpClientHandler(this IHostContext context)
|
||||||
{
|
{
|
||||||
HttpClientHandler clientHandler = new HttpClientHandler();
|
HttpClientHandler clientHandler = new HttpClientHandler();
|
||||||
clientHandler.Proxy = context.WebProxy;
|
var runnerWebProxy = context.GetService<IRunnerWebProxy>();
|
||||||
|
clientHandler.Proxy = runnerWebProxy.WebProxy;
|
||||||
return clientHandler;
|
return clientHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,21 +12,53 @@ namespace GitHub.Runner.Common
|
|||||||
[ServiceLocator(Default = typeof(JobNotification))]
|
[ServiceLocator(Default = typeof(JobNotification))]
|
||||||
public interface IJobNotification : IRunnerService, IDisposable
|
public interface IJobNotification : IRunnerService, IDisposable
|
||||||
{
|
{
|
||||||
void JobStarted(Guid jobId, string accessToken, Uri serverUrl);
|
Task JobStarted(Guid jobId, string accessToken, Uri serverUrl);
|
||||||
Task JobCompleted(Guid jobId);
|
Task JobCompleted(Guid jobId);
|
||||||
void StartClient(string monitorSocketAddress);
|
void StartClient(string pipeName, string monitorSocketAddress, CancellationToken cancellationToken);
|
||||||
|
void StartClient(string socketAddress, string monitorSocketAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class JobNotification : RunnerService, IJobNotification
|
public sealed class JobNotification : RunnerService, IJobNotification
|
||||||
{
|
{
|
||||||
|
private NamedPipeClientStream _outClient;
|
||||||
|
private StreamWriter _writeStream;
|
||||||
|
private Socket _socket;
|
||||||
private Socket _monitorSocket;
|
private Socket _monitorSocket;
|
||||||
|
private bool _configured = false;
|
||||||
|
private bool _useSockets = false;
|
||||||
private bool _isMonitorConfigured = false;
|
private bool _isMonitorConfigured = false;
|
||||||
|
|
||||||
public void JobStarted(Guid jobId, string accessToken, Uri serverUrl)
|
public async Task JobStarted(Guid jobId, string accessToken, Uri serverUrl)
|
||||||
{
|
{
|
||||||
Trace.Info("Entering JobStarted Notification");
|
Trace.Info("Entering JobStarted Notification");
|
||||||
|
|
||||||
StartMonitor(jobId, accessToken, serverUrl);
|
StartMonitor(jobId, accessToken, serverUrl);
|
||||||
|
|
||||||
|
if (_configured)
|
||||||
|
{
|
||||||
|
String message = $"Starting job: {jobId.ToString()}";
|
||||||
|
if (_useSockets)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trace.Info("Writing JobStarted to socket");
|
||||||
|
_socket.Send(Encoding.UTF8.GetBytes(message));
|
||||||
|
Trace.Info("Finished JobStarted writing to socket");
|
||||||
|
}
|
||||||
|
catch (SocketException e)
|
||||||
|
{
|
||||||
|
Trace.Error($"Failed sending message \"{message}\" on socket!");
|
||||||
|
Trace.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info("Writing JobStarted to pipe");
|
||||||
|
await _writeStream.WriteLineAsync(message);
|
||||||
|
await _writeStream.FlushAsync();
|
||||||
|
Trace.Info("Finished JobStarted writing to pipe");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task JobCompleted(Guid jobId)
|
public async Task JobCompleted(Guid jobId)
|
||||||
@@ -34,10 +66,95 @@ namespace GitHub.Runner.Common
|
|||||||
Trace.Info("Entering JobCompleted Notification");
|
Trace.Info("Entering JobCompleted Notification");
|
||||||
|
|
||||||
await EndMonitor();
|
await EndMonitor();
|
||||||
|
|
||||||
|
if (_configured)
|
||||||
|
{
|
||||||
|
String message = $"Finished job: {jobId.ToString()}";
|
||||||
|
if (_useSockets)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trace.Info("Writing JobCompleted to socket");
|
||||||
|
_socket.Send(Encoding.UTF8.GetBytes(message));
|
||||||
|
Trace.Info("Finished JobCompleted writing to socket");
|
||||||
|
}
|
||||||
|
catch (SocketException e)
|
||||||
|
{
|
||||||
|
Trace.Error($"Failed sending message \"{message}\" on socket!");
|
||||||
|
Trace.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info("Writing JobCompleted to pipe");
|
||||||
|
await _writeStream.WriteLineAsync(message);
|
||||||
|
await _writeStream.FlushAsync();
|
||||||
|
Trace.Info("Finished JobCompleted writing to pipe");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartClient(string monitorSocketAddress)
|
public async void StartClient(string pipeName, string monitorSocketAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (pipeName != null && !_configured)
|
||||||
|
{
|
||||||
|
Trace.Info("Connecting to named pipe {0}", pipeName);
|
||||||
|
_outClient = new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.Asynchronous);
|
||||||
|
await _outClient.ConnectAsync(cancellationToken);
|
||||||
|
_writeStream = new StreamWriter(_outClient, Encoding.UTF8);
|
||||||
|
_configured = true;
|
||||||
|
Trace.Info("Connection successful to named pipe {0}", pipeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectMonitor(monitorSocketAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartClient(string socketAddress, string monitorSocketAddress)
|
||||||
|
{
|
||||||
|
if (!_configured)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] splitAddress = socketAddress.Split(':');
|
||||||
|
if (splitAddress.Length != 2)
|
||||||
|
{
|
||||||
|
Trace.Error("Invalid socket address {0}. Job Notification will be disabled.", socketAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress address;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
address = IPAddress.Parse(splitAddress[0]);
|
||||||
|
}
|
||||||
|
catch (FormatException e)
|
||||||
|
{
|
||||||
|
Trace.Error("Invalid socket ip address {0}. Job Notification will be disabled",splitAddress[0]);
|
||||||
|
Trace.Error(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int port = -1;
|
||||||
|
Int32.TryParse(splitAddress[1], out port);
|
||||||
|
if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)
|
||||||
|
{
|
||||||
|
Trace.Error("Invalid tcp socket port {0}. Job Notification will be disabled.", splitAddress[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
_socket.Connect(address, port);
|
||||||
|
Trace.Info("Connection successful to socket {0}", socketAddress);
|
||||||
|
_useSockets = true;
|
||||||
|
_configured = true;
|
||||||
|
}
|
||||||
|
catch (SocketException e)
|
||||||
|
{
|
||||||
|
Trace.Error("Connection to socket {0} failed!", socketAddress);
|
||||||
|
Trace.Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConnectMonitor(monitorSocketAddress);
|
ConnectMonitor(monitorSocketAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +275,15 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
_outClient?.Dispose();
|
||||||
|
|
||||||
|
if (_socket != null)
|
||||||
|
{
|
||||||
|
_socket.Send(Encoding.UTF8.GetBytes("<EOF>"));
|
||||||
|
_socket.Shutdown(SocketShutdown.Both);
|
||||||
|
_socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (_monitorSocket != null)
|
if (_monitorSocket != null)
|
||||||
{
|
{
|
||||||
_monitorSocket.Send(Encoding.UTF8.GetBytes("<EOF>"));
|
_monitorSocket.Send(Encoding.UTF8.GetBytes("<EOF>"));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
@@ -27,5 +27,43 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
196
src/Runner.Common/RunnerWebProxy.cs
Normal file
196
src/Runner.Common/RunnerWebProxy.cs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
|
{
|
||||||
|
[ServiceLocator(Default = typeof(RunnerWebProxy))]
|
||||||
|
public interface IRunnerWebProxy : IRunnerService
|
||||||
|
{
|
||||||
|
string ProxyAddress { get; }
|
||||||
|
string ProxyUsername { get; }
|
||||||
|
string ProxyPassword { get; }
|
||||||
|
List<string> ProxyBypassList { get; }
|
||||||
|
IWebProxy WebProxy { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RunnerWebProxy : RunnerService, IRunnerWebProxy
|
||||||
|
{
|
||||||
|
private readonly List<Regex> _regExBypassList = new List<Regex>();
|
||||||
|
private readonly List<string> _bypassList = new List<string>();
|
||||||
|
private RunnerWebProxyCore _runnerWebProxy = new RunnerWebProxyCore();
|
||||||
|
|
||||||
|
public string ProxyAddress { get; private set; }
|
||||||
|
public string ProxyUsername { get; private set; }
|
||||||
|
public string ProxyPassword { get; private set; }
|
||||||
|
public List<string> ProxyBypassList => _bypassList;
|
||||||
|
public IWebProxy WebProxy => _runnerWebProxy;
|
||||||
|
|
||||||
|
public override void Initialize(IHostContext context)
|
||||||
|
{
|
||||||
|
base.Initialize(context);
|
||||||
|
LoadProxySetting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should only be called from config
|
||||||
|
public void SetupProxy(string proxyAddress, string proxyUsername, string proxyPassword)
|
||||||
|
{
|
||||||
|
ArgUtil.NotNullOrEmpty(proxyAddress, nameof(proxyAddress));
|
||||||
|
Trace.Info($"Update proxy setting from '{ProxyAddress ?? string.Empty}' to'{proxyAddress}'");
|
||||||
|
ProxyAddress = proxyAddress;
|
||||||
|
ProxyUsername = proxyUsername;
|
||||||
|
ProxyPassword = proxyPassword;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(ProxyUsername) || string.IsNullOrEmpty(ProxyPassword))
|
||||||
|
{
|
||||||
|
Trace.Info($"Config proxy use DefaultNetworkCredentials.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info($"Config authentication proxy as: {ProxyUsername}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_runnerWebProxy.Update(ProxyAddress, ProxyUsername, ProxyPassword, ProxyBypassList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should only be called from config
|
||||||
|
public void SaveProxySetting()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(ProxyAddress))
|
||||||
|
{
|
||||||
|
string proxyConfigFile = HostContext.GetConfigFile(WellKnownConfigFile.Proxy);
|
||||||
|
IOUtil.DeleteFile(proxyConfigFile);
|
||||||
|
Trace.Info($"Store proxy configuration to '{proxyConfigFile}' for proxy '{ProxyAddress}'");
|
||||||
|
File.WriteAllText(proxyConfigFile, ProxyAddress);
|
||||||
|
File.SetAttributes(proxyConfigFile, File.GetAttributes(proxyConfigFile) | FileAttributes.Hidden);
|
||||||
|
|
||||||
|
string proxyCredFile = HostContext.GetConfigFile(WellKnownConfigFile.ProxyCredentials);
|
||||||
|
IOUtil.DeleteFile(proxyCredFile);
|
||||||
|
if (!string.IsNullOrEmpty(ProxyUsername) && !string.IsNullOrEmpty(ProxyPassword))
|
||||||
|
{
|
||||||
|
string lookupKey = Guid.NewGuid().ToString("D").ToUpperInvariant();
|
||||||
|
Trace.Info($"Store proxy credential lookup key '{lookupKey}' to '{proxyCredFile}'");
|
||||||
|
File.WriteAllText(proxyCredFile, lookupKey);
|
||||||
|
File.SetAttributes(proxyCredFile, File.GetAttributes(proxyCredFile) | FileAttributes.Hidden);
|
||||||
|
|
||||||
|
var credStore = HostContext.GetService<IRunnerCredentialStore>();
|
||||||
|
credStore.Write($"GITHUB_ACTIONS_RUNNER_PROXY_{lookupKey}", ProxyUsername, ProxyPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info("No proxy configuration exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should only be called from unconfig
|
||||||
|
public void DeleteProxySetting()
|
||||||
|
{
|
||||||
|
string proxyCredFile = HostContext.GetConfigFile(WellKnownConfigFile.ProxyCredentials);
|
||||||
|
if (File.Exists(proxyCredFile))
|
||||||
|
{
|
||||||
|
Trace.Info("Delete proxy credential from credential store.");
|
||||||
|
string lookupKey = File.ReadAllLines(proxyCredFile).FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(lookupKey))
|
||||||
|
{
|
||||||
|
var credStore = HostContext.GetService<IRunnerCredentialStore>();
|
||||||
|
credStore.Delete($"GITHUB_ACTIONS_RUNNER_PROXY_{lookupKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace.Info($"Delete .proxycredentials file: {proxyCredFile}");
|
||||||
|
IOUtil.DeleteFile(proxyCredFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
string proxyBypassFile = HostContext.GetConfigFile(WellKnownConfigFile.ProxyBypass);
|
||||||
|
if (File.Exists(proxyBypassFile))
|
||||||
|
{
|
||||||
|
Trace.Info($"Delete .proxybypass file: {proxyBypassFile}");
|
||||||
|
IOUtil.DeleteFile(proxyBypassFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
string proxyConfigFile = HostContext.GetConfigFile(WellKnownConfigFile.Proxy);
|
||||||
|
Trace.Info($"Delete .proxy file: {proxyConfigFile}");
|
||||||
|
IOUtil.DeleteFile(proxyConfigFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadProxySetting()
|
||||||
|
{
|
||||||
|
string proxyConfigFile = HostContext.GetConfigFile(WellKnownConfigFile.Proxy);
|
||||||
|
if (File.Exists(proxyConfigFile))
|
||||||
|
{
|
||||||
|
// we expect the first line of the file is the proxy url
|
||||||
|
Trace.Verbose($"Try read proxy setting from file: {proxyConfigFile}.");
|
||||||
|
ProxyAddress = File.ReadLines(proxyConfigFile).FirstOrDefault() ?? string.Empty;
|
||||||
|
ProxyAddress = ProxyAddress.Trim();
|
||||||
|
Trace.Verbose($"{ProxyAddress}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(ProxyAddress) && !Uri.IsWellFormedUriString(ProxyAddress, UriKind.Absolute))
|
||||||
|
{
|
||||||
|
Trace.Info($"The proxy url is not a well formed absolute uri string: {ProxyAddress}.");
|
||||||
|
ProxyAddress = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(ProxyAddress))
|
||||||
|
{
|
||||||
|
Trace.Info($"Config proxy at: {ProxyAddress}.");
|
||||||
|
|
||||||
|
string proxyCredFile = HostContext.GetConfigFile(WellKnownConfigFile.ProxyCredentials);
|
||||||
|
if (File.Exists(proxyCredFile))
|
||||||
|
{
|
||||||
|
string lookupKey = File.ReadAllLines(proxyCredFile).FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(lookupKey))
|
||||||
|
{
|
||||||
|
var credStore = HostContext.GetService<IRunnerCredentialStore>();
|
||||||
|
var proxyCred = credStore.Read($"GITHUB_ACTIONS_RUNNER_PROXY_{lookupKey}");
|
||||||
|
ProxyUsername = proxyCred.UserName;
|
||||||
|
ProxyPassword = proxyCred.Password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(ProxyPassword))
|
||||||
|
{
|
||||||
|
HostContext.SecretMasker.AddValue(ProxyPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(ProxyUsername) || string.IsNullOrEmpty(ProxyPassword))
|
||||||
|
{
|
||||||
|
Trace.Info($"Config proxy use DefaultNetworkCredentials.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info($"Config authentication proxy as: {ProxyUsername}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string proxyBypassFile = HostContext.GetConfigFile(WellKnownConfigFile.ProxyBypass);
|
||||||
|
if (File.Exists(proxyBypassFile))
|
||||||
|
{
|
||||||
|
Trace.Verbose($"Try read proxy bypass list from file: {proxyBypassFile}.");
|
||||||
|
foreach (string bypass in File.ReadAllLines(proxyBypassFile))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(bypass))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info($"Bypass proxy for: {bypass}.");
|
||||||
|
ProxyBypassList.Add(bypass.Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_runnerWebProxy.Update(ProxyAddress, ProxyUsername, ProxyPassword, ProxyBypassList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Trace.Info($"No proxy setting found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,13 +50,6 @@ namespace GitHub.Runner.Common
|
|||||||
public void Error(Exception exception)
|
public void Error(Exception exception)
|
||||||
{
|
{
|
||||||
Trace(TraceEventType.Error, exception.ToString());
|
Trace(TraceEventType.Error, exception.ToString());
|
||||||
var innerEx = exception.InnerException;
|
|
||||||
while (innerEx != null)
|
|
||||||
{
|
|
||||||
Trace(TraceEventType.Error, "#####################################################");
|
|
||||||
Trace(TraceEventType.Error, innerEx.ToString());
|
|
||||||
innerEx = innerEx.InnerException;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not remove the non-format overload.
|
// Do not remove the non-format overload.
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ namespace GitHub.Runner.Common.Util
|
|||||||
return "X64";
|
return "X64";
|
||||||
case Constants.Architecture.Arm:
|
case Constants.Architecture.Arm:
|
||||||
return "ARM";
|
return "ARM";
|
||||||
case Constants.Architecture.Arm64:
|
|
||||||
return "ARM64";
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException(); // Should never reach here.
|
throw new NotSupportedException(); // Should never reach here.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var runnerWebProxy = HostContext.GetService<IRunnerWebProxy>();
|
||||||
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
||||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, HostContext.WebProxy, runnerCertManager.VssClientCertificateManager);
|
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, runnerWebProxy.WebProxy, runnerCertManager.VssClientCertificateManager);
|
||||||
|
|
||||||
_inConfigStage = true;
|
_inConfigStage = true;
|
||||||
_completedCommand.Reset();
|
_completedCommand.Reset();
|
||||||
@@ -190,6 +191,25 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !OS_WINDOWS
|
||||||
|
// Fix the work folder setting on Linux
|
||||||
|
if (settings.WorkFolder.Contains("vsts", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var workFolder = "/runner/work";
|
||||||
|
var unix = HostContext.GetService<IUnixUtil>();
|
||||||
|
|
||||||
|
// create new work folder /runner/work
|
||||||
|
await unix.ExecAsync(HostContext.GetDirectory(WellKnownDirectory.Root), "sh", $"-c \"sudo mkdir -p {workFolder}\"");
|
||||||
|
|
||||||
|
// fix permission
|
||||||
|
await unix.ExecAsync(HostContext.GetDirectory(WellKnownDirectory.Root), "sh", $"-c \"sudo chown -R $USER {workFolder}\"");
|
||||||
|
|
||||||
|
// update settings
|
||||||
|
settings.WorkFolder = workFolder;
|
||||||
|
store.SaveSettings(settings);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Trace.Info($"Set runner startup type - {startType}");
|
Trace.Info($"Set runner startup type - {startType}");
|
||||||
HostContext.StartupType = startType;
|
HostContext.StartupType = startType;
|
||||||
|
|
||||||
@@ -273,8 +293,14 @@ namespace GitHub.Runner.Listener
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var notification = HostContext.GetService<IJobNotification>();
|
var notification = HostContext.GetService<IJobNotification>();
|
||||||
|
if (!String.IsNullOrEmpty(settings.NotificationSocketAddress))
|
||||||
notification.StartClient(settings.MonitorSocketAddress);
|
{
|
||||||
|
notification.StartClient(settings.NotificationSocketAddress, settings.MonitorSocketAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notification.StartClient(settings.NotificationPipeName, settings.MonitorSocketAddress, HostContext.RunnerShutdownToken);
|
||||||
|
}
|
||||||
|
|
||||||
bool autoUpdateInProgress = false;
|
bool autoUpdateInProgress = false;
|
||||||
Task<bool> selfUpdateTask = null;
|
Task<bool> selfUpdateTask = null;
|
||||||
@@ -42,11 +42,15 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
private readonly string[] validArgs =
|
private readonly string[] validArgs =
|
||||||
{
|
{
|
||||||
|
Constants.Runner.CommandLine.Args.Agent,
|
||||||
Constants.Runner.CommandLine.Args.Auth,
|
Constants.Runner.CommandLine.Args.Auth,
|
||||||
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
||||||
Constants.Runner.CommandLine.Args.Name,
|
Constants.Runner.CommandLine.Args.NotificationPipeName,
|
||||||
Constants.Runner.CommandLine.Args.Password,
|
Constants.Runner.CommandLine.Args.Password,
|
||||||
Constants.Runner.CommandLine.Args.Pool,
|
Constants.Runner.CommandLine.Args.Pool,
|
||||||
|
Constants.Runner.CommandLine.Args.ProxyPassword,
|
||||||
|
Constants.Runner.CommandLine.Args.ProxyUrl,
|
||||||
|
Constants.Runner.CommandLine.Args.ProxyUserName,
|
||||||
Constants.Runner.CommandLine.Args.SslCACert,
|
Constants.Runner.CommandLine.Args.SslCACert,
|
||||||
Constants.Runner.CommandLine.Args.SslClientCert,
|
Constants.Runner.CommandLine.Args.SslClientCert,
|
||||||
Constants.Runner.CommandLine.Args.SslClientCertKey,
|
Constants.Runner.CommandLine.Args.SslClientCertKey,
|
||||||
@@ -170,6 +174,15 @@ namespace GitHub.Runner.Listener
|
|||||||
//
|
//
|
||||||
// Args.
|
// Args.
|
||||||
//
|
//
|
||||||
|
public string GetAgentName()
|
||||||
|
{
|
||||||
|
return GetArgOrPrompt(
|
||||||
|
name: Constants.Runner.CommandLine.Args.Agent,
|
||||||
|
description: "Enter the name of runner:",
|
||||||
|
defaultValue: Environment.MachineName ?? "myagent",
|
||||||
|
validator: Validators.NonEmptyValidator);
|
||||||
|
}
|
||||||
|
|
||||||
public string GetAuth(string defaultValue)
|
public string GetAuth(string defaultValue)
|
||||||
{
|
{
|
||||||
return GetArgOrPrompt(
|
return GetArgOrPrompt(
|
||||||
@@ -197,15 +210,6 @@ namespace GitHub.Runner.Listener
|
|||||||
validator: Validators.NonEmptyValidator);
|
validator: Validators.NonEmptyValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetRunnerName()
|
|
||||||
{
|
|
||||||
return GetArgOrPrompt(
|
|
||||||
name: Constants.Runner.CommandLine.Args.Name,
|
|
||||||
description: "Enter the name of runner:",
|
|
||||||
defaultValue: Environment.MachineName ?? "myrunner",
|
|
||||||
validator: Validators.NonEmptyValidator);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetToken()
|
public string GetToken()
|
||||||
{
|
{
|
||||||
return GetArgOrPrompt(
|
return GetArgOrPrompt(
|
||||||
@@ -281,12 +285,37 @@ namespace GitHub.Runner.Listener
|
|||||||
return GetArg(Constants.Runner.CommandLine.Args.MonitorSocketAddress);
|
return GetArg(Constants.Runner.CommandLine.Args.MonitorSocketAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetNotificationPipeName()
|
||||||
|
{
|
||||||
|
return GetArg(Constants.Runner.CommandLine.Args.NotificationPipeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetNotificationSocketAddress()
|
||||||
|
{
|
||||||
|
return GetArg(Constants.Runner.CommandLine.Args.NotificationSocketAddress);
|
||||||
|
}
|
||||||
|
|
||||||
// This is used to find out the source from where the Runner.Listener.exe was launched at the time of run
|
// This is used to find out the source from where the Runner.Listener.exe was launched at the time of run
|
||||||
public string GetStartupType()
|
public string GetStartupType()
|
||||||
{
|
{
|
||||||
return GetArg(Constants.Runner.CommandLine.Args.StartupType);
|
return GetArg(Constants.Runner.CommandLine.Args.StartupType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetProxyUrl()
|
||||||
|
{
|
||||||
|
return GetArg(Constants.Runner.CommandLine.Args.ProxyUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetProxyUserName()
|
||||||
|
{
|
||||||
|
return GetArg(Constants.Runner.CommandLine.Args.ProxyUserName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetProxyPassword()
|
||||||
|
{
|
||||||
|
return GetArg(Constants.Runner.CommandLine.Args.ProxyPassword);
|
||||||
|
}
|
||||||
|
|
||||||
public bool GetSkipCertificateValidation()
|
public bool GetSkipCertificateValidation()
|
||||||
{
|
{
|
||||||
return TestFlag(Constants.Runner.CommandLine.Flags.SslSkipCertValidation);
|
return TestFlag(Constants.Runner.CommandLine.Flags.SslSkipCertValidation);
|
||||||
|
|||||||
@@ -86,6 +86,24 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
throw new InvalidOperationException("Cannot configure the runner because it is already configured. To reconfigure the runner, run 'config.cmd remove' or './config.sh remove' first.");
|
throw new InvalidOperationException("Cannot configure the runner because it is already configured. To reconfigure the runner, run 'config.cmd remove' or './config.sh remove' first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate proxy setting from commandline args
|
||||||
|
var runnerProxy = HostContext.GetService<IRunnerWebProxy>();
|
||||||
|
bool saveProxySetting = false;
|
||||||
|
string proxyUrl = command.GetProxyUrl();
|
||||||
|
if (!string.IsNullOrEmpty(proxyUrl))
|
||||||
|
{
|
||||||
|
if (!Uri.IsWellFormedUriString(proxyUrl, UriKind.Absolute))
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(proxyUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
Trace.Info("Reset proxy base on commandline args.");
|
||||||
|
string proxyUserName = command.GetProxyUserName();
|
||||||
|
string proxyPassword = command.GetProxyPassword();
|
||||||
|
(runnerProxy as RunnerWebProxy).SetupProxy(proxyUrl, proxyUserName, proxyPassword);
|
||||||
|
saveProxySetting = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Populate cert setting from commandline args
|
// Populate cert setting from commandline args
|
||||||
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
||||||
bool saveCertSetting = false;
|
bool saveCertSetting = false;
|
||||||
@@ -214,7 +232,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
TaskAgent agent;
|
TaskAgent agent;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
runnerSettings.AgentName = command.GetRunnerName();
|
runnerSettings.AgentName = command.GetAgentName();
|
||||||
|
|
||||||
_term.WriteLine();
|
_term.WriteLine();
|
||||||
|
|
||||||
@@ -349,10 +367,21 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
// We will Combine() what's stored with root. Defaults to string a relative path
|
// We will Combine() what's stored with root. Defaults to string a relative path
|
||||||
runnerSettings.WorkFolder = command.GetWork();
|
runnerSettings.WorkFolder = command.GetWork();
|
||||||
|
|
||||||
|
// notificationPipeName for Hosted agent provisioner.
|
||||||
|
runnerSettings.NotificationPipeName = command.GetNotificationPipeName();
|
||||||
|
|
||||||
runnerSettings.MonitorSocketAddress = command.GetMonitorSocketAddress();
|
runnerSettings.MonitorSocketAddress = command.GetMonitorSocketAddress();
|
||||||
|
|
||||||
|
runnerSettings.NotificationSocketAddress = command.GetNotificationSocketAddress();
|
||||||
|
|
||||||
_store.SaveSettings(runnerSettings);
|
_store.SaveSettings(runnerSettings);
|
||||||
|
|
||||||
|
if (saveProxySetting)
|
||||||
|
{
|
||||||
|
Trace.Info("Save proxy setting to disk.");
|
||||||
|
(runnerProxy as RunnerWebProxy).SaveProxySetting();
|
||||||
|
}
|
||||||
|
|
||||||
if (saveCertSetting)
|
if (saveCertSetting)
|
||||||
{
|
{
|
||||||
Trace.Info("Save agent cert setting to disk.");
|
Trace.Info("Save agent cert setting to disk.");
|
||||||
@@ -491,6 +520,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
currentAction = "Removing .runner";
|
currentAction = "Removing .runner";
|
||||||
if (isConfigured)
|
if (isConfigured)
|
||||||
{
|
{
|
||||||
|
// delete proxy setting
|
||||||
|
(HostContext.GetService<IRunnerWebProxy>() as RunnerWebProxy).DeleteProxySetting();
|
||||||
|
|
||||||
// delete agent cert setting
|
// delete agent cert setting
|
||||||
(HostContext.GetService<IRunnerCertificateManager>() as RunnerCertificateManager).DeleteCertificateSetting();
|
(HostContext.GetService<IRunnerCertificateManager>() as RunnerCertificateManager).DeleteCertificateSetting();
|
||||||
@@ -543,7 +574,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
PublicKey = new TaskAgentPublicKey(publicKey.Exponent, publicKey.Modulus),
|
PublicKey = new TaskAgentPublicKey(publicKey.Exponent, publicKey.Modulus),
|
||||||
};
|
};
|
||||||
|
|
||||||
// update - update instead of delete so we don't lose labels etc...
|
// update - update instead of delete so we don't lose user capabilities etc...
|
||||||
agent.Version = BuildConstants.RunnerPackage.Version;
|
agent.Version = BuildConstants.RunnerPackage.Version;
|
||||||
agent.OSDescription = RuntimeInformation.OSDescription;
|
agent.OSDescription = RuntimeInformation.OSDescription;
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
public class OsxServiceControlManager : ServiceControlManager, ILinuxServiceControlManager
|
public class OsxServiceControlManager : ServiceControlManager, ILinuxServiceControlManager
|
||||||
{
|
{
|
||||||
// This is the name you would see when you do `systemctl list-units | grep runner`
|
// This is the name you would see when you do `systemctl list-units | grep runner`
|
||||||
private const string _svcNamePattern = "actions.runner.{0}.{1}";
|
private const string _svcNamePattern = "actions.runner.{0}.{1}.{2}";
|
||||||
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1})";
|
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
||||||
private const string _shTemplate = "darwin.svc.sh.template";
|
private const string _shTemplate = "darwin.svc.sh.template";
|
||||||
private const string _svcShName = "svc.sh";
|
private const string _svcShName = "svc.sh";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
@@ -38,38 +37,25 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
serviceName = string.Empty;
|
serviceName = string.Empty;
|
||||||
serviceDisplayName = string.Empty;
|
serviceDisplayName = string.Empty;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(settings.RepoOrOrgName))
|
Uri accountUri = new Uri(settings.ServerUrl);
|
||||||
|
string accountName = string.Empty;
|
||||||
|
|
||||||
|
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Cannot find GitHub repository/organization name from server url: '{settings.ServerUrl}'");
|
accountName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
accountName = accountUri.Host.Split('.').FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the service name, replace any characters outside of the alpha-numeric set and ".", "_", "-" with "-"
|
if (string.IsNullOrEmpty(accountName))
|
||||||
Regex regex = new Regex(@"[^0-9a-zA-Z._\-]");
|
|
||||||
string repoOrOrgName = regex.Replace(settings.RepoOrOrgName, "-");
|
|
||||||
|
|
||||||
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgName, settings.AgentName);
|
|
||||||
|
|
||||||
if (serviceName.Length > 80)
|
|
||||||
{
|
{
|
||||||
Trace.Verbose($"Calculated service name is too long (> 80 chars). Trying again by calculating a shorter name.");
|
throw new InvalidOperationException($"Cannot find GitHub organization name from server url: '{settings.ServerUrl}'");
|
||||||
|
|
||||||
int exceededCharLength = serviceName.Length - 80;
|
|
||||||
string repoOrOrgNameSubstring = StringUtil.SubstringPrefix(repoOrOrgName, 45);
|
|
||||||
|
|
||||||
exceededCharLength -= repoOrOrgName.Length - repoOrOrgNameSubstring.Length;
|
|
||||||
|
|
||||||
string runnerNameSubstring = settings.AgentName;
|
|
||||||
|
|
||||||
// Only trim runner name if it's really necessary
|
|
||||||
if (exceededCharLength > 0)
|
|
||||||
{
|
|
||||||
runnerNameSubstring = StringUtil.SubstringPrefix(settings.AgentName, settings.AgentName.Length - exceededCharLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceDisplayName = StringUtil.Format(serviceDisplayNamePattern, repoOrOrgName, settings.AgentName);
|
serviceName = StringUtil.Format(serviceNamePattern, accountName, settings.PoolName, settings.AgentName);
|
||||||
|
serviceDisplayName = StringUtil.Format(serviceDisplayNamePattern, accountName, settings.PoolName, settings.AgentName);
|
||||||
|
|
||||||
Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration.");
|
Trace.Info($"Service name '{serviceName}' display name '{serviceDisplayName}' will be used for service configuration.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
public class SystemDControlManager : ServiceControlManager, ILinuxServiceControlManager
|
public class SystemDControlManager : ServiceControlManager, ILinuxServiceControlManager
|
||||||
{
|
{
|
||||||
// This is the name you would see when you do `systemctl list-units | grep runner`
|
// This is the name you would see when you do `systemctl list-units | grep runner`
|
||||||
private const string _svcNamePattern = "actions.runner.{0}.{1}.service";
|
private const string _svcNamePattern = "actions.runner.{0}.{1}.{2}.service";
|
||||||
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1})";
|
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
||||||
private const string _shTemplate = "systemd.svc.sh.template";
|
private const string _shTemplate = "systemd.svc.sh.template";
|
||||||
private const string _shName = "svc.sh";
|
private const string _shName = "svc.sh";
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
{
|
{
|
||||||
public const string WindowsServiceControllerName = "RunnerService.exe";
|
public const string WindowsServiceControllerName = "RunnerService.exe";
|
||||||
|
|
||||||
private const string ServiceNamePattern = "actions.runner.{0}.{1}";
|
private const string ServiceNamePattern = "actionsrunner.{0}.{1}.{2}";
|
||||||
private const string ServiceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
private const string ServiceDisplayNamePattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
||||||
|
|
||||||
private INativeWindowsServiceHelper _windowsServiceHelper;
|
private INativeWindowsServiceHelper _windowsServiceHelper;
|
||||||
private ITerminal _term;
|
private ITerminal _term;
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ namespace GitHub.Runner.Listener
|
|||||||
// send notification to machine provisioner.
|
// send notification to machine provisioner.
|
||||||
var systemConnection = message.Resources.Endpoints.SingleOrDefault(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
var systemConnection = message.Resources.Endpoints.SingleOrDefault(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
var accessToken = systemConnection?.Authorization?.Parameters["AccessToken"];
|
var accessToken = systemConnection?.Authorization?.Parameters["AccessToken"];
|
||||||
notification.JobStarted(message.JobId, accessToken, systemConnection.Url);
|
await notification.JobStarted(message.JobId, accessToken, systemConnection.Url);
|
||||||
|
|
||||||
HostContext.WritePerfCounter($"SentJobToWorker_{requestId.ToString()}");
|
HostContext.WritePerfCounter($"SentJobToWorker_{requestId.ToString()}");
|
||||||
|
|
||||||
@@ -787,41 +787,38 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
var jobServer = HostContext.GetService<IJobServer>();
|
var jobServer = HostContext.GetService<IJobServer>();
|
||||||
VssCredentials jobServerCredential = VssUtil.GetVssCredential(systemConnection);
|
VssCredentials jobServerCredential = VssUtil.GetVssCredential(systemConnection);
|
||||||
VssConnection jobConnection = VssUtil.CreateConnection(systemConnection.Url, jobServerCredential);
|
Uri jobServerUrl = systemConnection.Url;
|
||||||
|
|
||||||
/* Below is the legacy 'OnPremises' code that is currently unused by the runner
|
// Make sure SystemConnection Url match Config Url base for OnPremises server
|
||||||
ToDo: re-implement code as appropriate once GHES support is added.
|
if (!message.Variables.ContainsKey(Constants.Variables.System.ServerType) ||
|
||||||
// Make sure SystemConnection Url match Config Url base for OnPremises server
|
string.Equals(message.Variables[Constants.Variables.System.ServerType]?.Value, "OnPremises", StringComparison.OrdinalIgnoreCase))
|
||||||
if (!message.Variables.ContainsKey(Constants.Variables.System.ServerType) ||
|
{
|
||||||
string.Equals(message.Variables[Constants.Variables.System.ServerType]?.Value, "OnPremises", StringComparison.OrdinalIgnoreCase))
|
try
|
||||||
{
|
{
|
||||||
try
|
Uri result = null;
|
||||||
{
|
Uri configUri = new Uri(_runnerSetting.ServerUrl);
|
||||||
Uri result = null;
|
if (Uri.TryCreate(new Uri(configUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped)), jobServerUrl.PathAndQuery, out result))
|
||||||
Uri configUri = new Uri(_runnerSetting.ServerUrl);
|
{
|
||||||
if (Uri.TryCreate(new Uri(configUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped)), jobServerUrl.PathAndQuery, out result))
|
//replace the schema and host portion of messageUri with the host from the
|
||||||
{
|
//server URI (which was set at config time)
|
||||||
//replace the schema and host portion of messageUri with the host from the
|
jobServerUrl = result;
|
||||||
//server URI (which was set at config time)
|
}
|
||||||
jobServerUrl = result;
|
}
|
||||||
}
|
catch (InvalidOperationException ex)
|
||||||
}
|
{
|
||||||
catch (InvalidOperationException ex)
|
//cannot parse the Uri - not a fatal error
|
||||||
{
|
Trace.Error(ex);
|
||||||
//cannot parse the Uri - not a fatal error
|
}
|
||||||
Trace.Error(ex);
|
catch (UriFormatException ex)
|
||||||
}
|
{
|
||||||
catch (UriFormatException ex)
|
//cannot parse the Uri - not a fatal error
|
||||||
{
|
Trace.Error(ex);
|
||||||
//cannot parse the Uri - not a fatal error
|
}
|
||||||
Trace.Error(ex);
|
}
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential);
|
||||||
await jobServer.ConnectAsync(jobConnection);
|
await jobServer.ConnectAsync(jobConnection);
|
||||||
|
|
||||||
var timeline = await jobServer.GetTimelineAsync(message.Plan.ScopeIdentifier, message.Plan.PlanType, message.Plan.PlanId, message.Timeline.Id, CancellationToken.None);
|
var timeline = await jobServer.GetTimelineAsync(message.Plan.ScopeIdentifier, message.Plan.PlanType, message.Plan.PlanId, message.Timeline.Id, CancellationToken.None);
|
||||||
|
|
||||||
ArgUtil.NotNull(timeline, nameof(timeline));
|
ArgUtil.NotNull(timeline, nameof(timeline));
|
||||||
TimelineRecord jobRecord = timeline.Records.FirstOrDefault(x => x.Id == message.JobId && x.RecordType == "Job");
|
TimelineRecord jobRecord = timeline.Records.FirstOrDefault(x => x.Id == message.JobId && x.RecordType == "Job");
|
||||||
ArgUtil.NotNull(jobRecord, nameof(jobRecord));
|
ArgUtil.NotNull(jobRecord, nameof(jobRecord));
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using GitHub.Runner.Sdk;
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -15,9 +14,6 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
public static int Main(string[] args)
|
public static int Main(string[] args)
|
||||||
{
|
{
|
||||||
// Add environment variables from .env file
|
|
||||||
LoadAndSetEnv();
|
|
||||||
|
|
||||||
using (HostContext context = new HostContext("Runner"))
|
using (HostContext context = new HostContext("Runner"))
|
||||||
{
|
{
|
||||||
return MainAsync(context, args).GetAwaiter().GetResult();
|
return MainAsync(context, args).GetAwaiter().GetResult();
|
||||||
@@ -29,7 +25,7 @@ namespace GitHub.Runner.Listener
|
|||||||
// 1: Terminate failure
|
// 1: Terminate failure
|
||||||
// 2: Retriable failure
|
// 2: Retriable failure
|
||||||
// 3: Exit for self update
|
// 3: Exit for self update
|
||||||
private async static Task<int> MainAsync(IHostContext context, string[] args)
|
public async static Task<int> MainAsync(IHostContext context, string[] args)
|
||||||
{
|
{
|
||||||
Tracing trace = context.GetTrace(nameof(GitHub.Runner.Listener));
|
Tracing trace = context.GetTrace(nameof(GitHub.Runner.Listener));
|
||||||
trace.Info($"Runner is built for {Constants.Runner.Platform} ({Constants.Runner.PlatformArchitecture}) - {BuildConstants.RunnerPackage.PackageName}.");
|
trace.Info($"Runner is built for {Constants.Runner.Platform} ({Constants.Runner.PlatformArchitecture}) - {BuildConstants.RunnerPackage.PackageName}.");
|
||||||
@@ -87,6 +83,22 @@ namespace GitHub.Runner.Listener
|
|||||||
return Constants.Runner.ReturnCode.TerminatedError;
|
return Constants.Runner.ReturnCode.TerminatedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add environment variables from .env file
|
||||||
|
string envFile = Path.Combine(context.GetDirectory(WellKnownDirectory.Root), ".env");
|
||||||
|
if (File.Exists(envFile))
|
||||||
|
{
|
||||||
|
var envContents = File.ReadAllLines(envFile);
|
||||||
|
foreach (var env in envContents)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(env) && env.IndexOf('=') > 0)
|
||||||
|
{
|
||||||
|
string envKey = env.Substring(0, env.IndexOf('='));
|
||||||
|
string envValue = env.Substring(env.IndexOf('=') + 1);
|
||||||
|
Environment.SetEnvironmentVariable(envKey, envValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the command line args.
|
// Parse the command line args.
|
||||||
var command = new CommandSettings(context, args);
|
var command = new CommandSettings(context, args);
|
||||||
trace.Info("Arguments parsed");
|
trace.Info("Arguments parsed");
|
||||||
@@ -124,34 +136,5 @@ namespace GitHub.Runner.Listener
|
|||||||
return Constants.Runner.ReturnCode.RetryableError;
|
return Constants.Runner.ReturnCode.RetryableError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LoadAndSetEnv()
|
|
||||||
{
|
|
||||||
var binDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
|
||||||
var rootDir = new DirectoryInfo(binDir).Parent.FullName;
|
|
||||||
string envFile = Path.Combine(rootDir, ".env");
|
|
||||||
if (File.Exists(envFile))
|
|
||||||
{
|
|
||||||
var envContents = File.ReadAllLines(envFile);
|
|
||||||
foreach (var env in envContents)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(env))
|
|
||||||
{
|
|
||||||
var separatorIndex = env.IndexOf('=');
|
|
||||||
if (separatorIndex > 0)
|
|
||||||
{
|
|
||||||
string envKey = env.Substring(0, separatorIndex);
|
|
||||||
string envValue = null;
|
|
||||||
if (env.Length > separatorIndex + 1)
|
|
||||||
{
|
|
||||||
envValue = env.Substring(separatorIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable(envKey, envValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
@@ -30,5 +30,43 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -24,4 +24,42 @@
|
|||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -50,62 +50,29 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
throw new ArgumentException($"Run Id is not an Int32: {buildIdStr}");
|
throw new ArgumentException($"Run Id is not an Int32: {buildIdStr}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether to call Pipelines or Build endpoint to publish artifact based on variable setting
|
context.Output($"Download artifact '{artifactName}' to: '{targetPath}'");
|
||||||
string usePipelinesArtifactEndpointVar = context.Variables.GetValueOrDefault("Runner.UseActionsArtifactsApis")?.Value;
|
|
||||||
bool.TryParse(usePipelinesArtifactEndpointVar, out bool usePipelinesArtifactEndpoint);
|
|
||||||
string containerPath;
|
|
||||||
long containerId;
|
|
||||||
|
|
||||||
context.Output($"Downloading artifact '{artifactName}' to: '{targetPath}'");
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
|
BuildArtifact buildArtifact = await buildHelper.GetArtifact(projectId, buildId, artifactName, token);
|
||||||
|
|
||||||
if (usePipelinesArtifactEndpoint)
|
if (string.Equals(buildArtifact.Resource.Type, "Container", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
context.Debug("Downloading artifact using v2 endpoint");
|
string containerUrl = buildArtifact.Resource.Data;
|
||||||
|
string[] parts = containerUrl.Split(new[] { '/' }, 3);
|
||||||
// Definition ID is a dummy value only used by HTTP client routing purposes
|
if (parts.Length < 3 || !long.TryParse(parts[1], out long containerId))
|
||||||
int definitionId = 1;
|
|
||||||
|
|
||||||
var pipelinesHelper = new PipelinesServer(context.VssConnection);
|
|
||||||
|
|
||||||
var actionsStorageArtifact = await pipelinesHelper.GetActionsStorageArtifact(definitionId, buildId, artifactName, token);
|
|
||||||
|
|
||||||
if (actionsStorageArtifact == null)
|
|
||||||
{
|
{
|
||||||
throw new Exception($"The actions storage artifact for '{artifactName}' could not be found, or is no longer available");
|
throw new ArgumentOutOfRangeException($"Invalid container url '{containerUrl}' for artifact '{buildArtifact.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
containerPath = actionsStorageArtifact.Name; // In actions storage artifacts, name equals the path
|
string containerPath = parts[2];
|
||||||
containerId = actionsStorageArtifact.ContainerId;
|
FileContainerServer fileContainerServer = new FileContainerServer(context.VssConnection, projectId, containerId, containerPath);
|
||||||
|
await fileContainerServer.DownloadFromContainerAsync(context, targetPath, token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Debug("Downloading artifact using v1 endpoint");
|
throw new NotSupportedException($"Invalid artifact type: {buildArtifact.Resource.Type}");
|
||||||
|
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
|
||||||
BuildArtifact buildArtifact = await buildHelper.GetArtifact(projectId, buildId, artifactName, token);
|
|
||||||
|
|
||||||
if (string.Equals(buildArtifact.Resource.Type, "Container", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
// Artifact was published by Pipelines endpoint, check new type here to handle rollback scenario
|
|
||||||
string.Equals(buildArtifact.Resource.Type, "Actions_Storage", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
string containerUrl = buildArtifact.Resource.Data;
|
|
||||||
string[] parts = containerUrl.Split(new[] { '/' }, 3);
|
|
||||||
if (parts.Length < 3 || !long.TryParse(parts[1], out containerId))
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException($"Invalid container url '{containerUrl}' for artifact '{buildArtifact.Name}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
containerPath = parts[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException($"Invalid artifact type: {buildArtifact.Resource.Type}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileContainerServer fileContainerServer = new FileContainerServer(context.VssConnection, projectId, containerId, containerPath);
|
|
||||||
await fileContainerServer.DownloadFromContainerAsync(context, targetPath, token);
|
|
||||||
|
|
||||||
context.Output("Artifact download finished.");
|
context.Output("Artifact download finished.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Actions.Pipelines.WebApi;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using Pipelines = GitHub.Actions.Pipelines.WebApi;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Plugins.Artifact
|
|
||||||
{
|
|
||||||
// A client wrapper interacting with Pipelines's Artifact API
|
|
||||||
public class PipelinesServer
|
|
||||||
{
|
|
||||||
private readonly PipelinesHttpClient _pipelinesHttpClient;
|
|
||||||
|
|
||||||
public PipelinesServer(VssConnection connection)
|
|
||||||
{
|
|
||||||
ArgUtil.NotNull(connection, nameof(connection));
|
|
||||||
_pipelinesHttpClient = connection.GetClient<PipelinesHttpClient>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Associate the specified Actions Storage artifact with a pipeline
|
|
||||||
public async Task<Pipelines.ActionsStorageArtifact> AssociateActionsStorageArtifactAsync(
|
|
||||||
int pipelineId,
|
|
||||||
int runId,
|
|
||||||
long containerId,
|
|
||||||
string name,
|
|
||||||
long size,
|
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
|
||||||
{
|
|
||||||
CreateArtifactParameters parameters = new CreateActionsStorageArtifactParameters()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
ContainerId = containerId,
|
|
||||||
Size = size
|
|
||||||
};
|
|
||||||
|
|
||||||
return await _pipelinesHttpClient.CreateArtifactAsync(
|
|
||||||
parameters,
|
|
||||||
pipelineId,
|
|
||||||
runId,
|
|
||||||
cancellationToken: cancellationToken) as Pipelines.ActionsStorageArtifact;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get named Actions Storage artifact for a pipeline
|
|
||||||
public async Task<Pipelines.ActionsStorageArtifact> GetActionsStorageArtifact(
|
|
||||||
int pipelineId,
|
|
||||||
int runId,
|
|
||||||
string name,
|
|
||||||
CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return await _pipelinesHttpClient.GetArtifactAsync(
|
|
||||||
pipelineId,
|
|
||||||
runId,
|
|
||||||
name,
|
|
||||||
cancellationToken: cancellationToken) as Pipelines.ActionsStorageArtifact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -68,59 +68,27 @@ namespace GitHub.Runner.Plugins.Artifact
|
|||||||
string containerIdStr = context.Variables.GetValueOrDefault(BuildVariables.ContainerId)?.Value ?? string.Empty;
|
string containerIdStr = context.Variables.GetValueOrDefault(BuildVariables.ContainerId)?.Value ?? string.Empty;
|
||||||
if (!long.TryParse(containerIdStr, out long containerId))
|
if (!long.TryParse(containerIdStr, out long containerId))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Container Id is not an Int64: {containerIdStr}");
|
throw new ArgumentException($"Container Id is not a Int64: {containerIdStr}");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
context.Output($"Uploading artifact '{artifactName}' from '{fullPath}' for run #{buildId}");
|
||||||
|
|
||||||
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
FileContainerServer fileContainerHelper = new FileContainerServer(context.VssConnection, projectId, containerId, artifactName);
|
||||||
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
var propertiesDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
long size = 0;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
||||||
|
|
||||||
propertiesDictionary.Add("artifactsize", size.ToString());
|
propertiesDictionary.Add("artifactsize", size.ToString());
|
||||||
|
|
||||||
context.Output($"Uploaded '{size}' bytes from '{fullPath}' to server");
|
context.Output($"Uploaded '{size}' bytes from '{fullPath}' to server");
|
||||||
}
|
}
|
||||||
// if any of the results were successful, make sure to attach them to the build
|
// if any of the results were successful, make sure to attach them to the build
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// Determine whether to call Pipelines or Build endpoint to publish artifact based on variable setting
|
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
||||||
string usePipelinesArtifactEndpointVar = context.Variables.GetValueOrDefault("Runner.UseActionsArtifactsApis")?.Value;
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
bool.TryParse(usePipelinesArtifactEndpointVar, out bool usePipelinesArtifactEndpoint);
|
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
||||||
|
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
||||||
if (usePipelinesArtifactEndpoint)
|
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
||||||
{
|
|
||||||
// Definition ID is a dummy value only used by HTTP client routing purposes
|
|
||||||
int definitionId = 1;
|
|
||||||
|
|
||||||
PipelinesServer pipelinesHelper = new PipelinesServer(context.VssConnection);
|
|
||||||
|
|
||||||
var artifact = await pipelinesHelper.AssociateActionsStorageArtifactAsync(
|
|
||||||
definitionId,
|
|
||||||
buildId,
|
|
||||||
containerId,
|
|
||||||
artifactName,
|
|
||||||
size,
|
|
||||||
token);
|
|
||||||
|
|
||||||
context.Output($"Associated artifact {artifactName} ({artifact.ContainerId}) with run #{buildId}");
|
|
||||||
context.Debug($"Associated artifact using v2 endpoint");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
|
||||||
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
|
||||||
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
|
||||||
|
|
||||||
context.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
|
||||||
context.Debug($"Associated artifact using v1 endpoint");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
{
|
{
|
||||||
// Validate args.
|
// Validate args.
|
||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
|
Uri proxyUrlWithCred = null;
|
||||||
|
string proxyUrlWithCredString = null;
|
||||||
bool useSelfSignedCACert = false;
|
bool useSelfSignedCACert = false;
|
||||||
bool useClientCert = false;
|
bool useClientCert = false;
|
||||||
string clientCertPrivateKeyAskPassFile = null;
|
string clientCertPrivateKeyAskPassFile = null;
|
||||||
@@ -162,6 +164,25 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
|
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
|
||||||
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
|
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
|
||||||
|
|
||||||
|
// prepare credentail embedded urls
|
||||||
|
var runnerProxy = executionContext.GetProxyConfiguration();
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
proxyUrlWithCred = UrlUtil.GetCredentialEmbeddedUrl(new Uri(runnerProxy.ProxyAddress), runnerProxy.ProxyUsername, runnerProxy.ProxyPassword);
|
||||||
|
|
||||||
|
// uri.absoluteuri will not contains port info if the scheme is http/https and the port is 80/443
|
||||||
|
// however, git.exe always require you provide port info, if nothing passed in, it will use 1080 as default
|
||||||
|
// as result, we need prefer the uri.originalstring when it's different than uri.absoluteuri.
|
||||||
|
if (string.Equals(proxyUrlWithCred.AbsoluteUri, proxyUrlWithCred.OriginalString, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
proxyUrlWithCredString = proxyUrlWithCred.AbsoluteUri;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proxyUrlWithCredString = proxyUrlWithCred.OriginalString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// prepare askpass for client cert private key, if the repository's endpoint url match the runner config url
|
// prepare askpass for client cert private key, if the repository's endpoint url match the runner config url
|
||||||
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
if (runnerCert != null && Uri.Compare(repositoryUrl, systemConnection.Url, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) == 0)
|
if (runnerCert != null && Uri.Compare(repositoryUrl, systemConnection.Url, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) == 0)
|
||||||
@@ -352,6 +373,13 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
|
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always remove any possible left proxy setting from git config, the proxy setting may contains credential
|
||||||
|
if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.proxy"))
|
||||||
|
{
|
||||||
|
executionContext.Debug("Remove any proxy setting from git config.");
|
||||||
|
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.proxy", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
List<string> additionalFetchArgs = new List<string>();
|
List<string> additionalFetchArgs = new List<string>();
|
||||||
List<string> additionalLfsFetchArgs = new List<string>();
|
List<string> additionalLfsFetchArgs = new List<string>();
|
||||||
|
|
||||||
@@ -361,6 +389,15 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
additionalFetchArgs.Add($"-c http.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
|
additionalFetchArgs.Add($"-c http.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare proxy config for fetch.
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
executionContext.Debug($"Config proxy server '{runnerProxy.ProxyAddress}' for git fetch.");
|
||||||
|
ArgUtil.NotNullOrEmpty(proxyUrlWithCredString, nameof(proxyUrlWithCredString));
|
||||||
|
additionalFetchArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
additionalLfsFetchArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare ignore ssl cert error config for fetch.
|
// Prepare ignore ssl cert error config for fetch.
|
||||||
if (acceptUntrustedCerts)
|
if (acceptUntrustedCerts)
|
||||||
{
|
{
|
||||||
@@ -502,6 +539,14 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
additionalSubmoduleUpdateArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
|
additionalSubmoduleUpdateArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare proxy config for submodule update.
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
executionContext.Debug($"Config proxy server '{runnerProxy.ProxyAddress}' for git submodule update.");
|
||||||
|
ArgUtil.NotNullOrEmpty(proxyUrlWithCredString, nameof(proxyUrlWithCredString));
|
||||||
|
additionalSubmoduleUpdateArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare ignore ssl cert error config for fetch.
|
// Prepare ignore ssl cert error config for fetch.
|
||||||
if (acceptUntrustedCerts)
|
if (acceptUntrustedCerts)
|
||||||
{
|
{
|
||||||
@@ -592,7 +637,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
int exitCode_configUnset = await gitCommandManager.GitConfigUnset(executionContext, targetPath, configKey);
|
int exitCode_configUnset = await gitCommandManager.GitConfigUnset(executionContext, targetPath, configKey);
|
||||||
if (exitCode_configUnset != 0)
|
if (exitCode_configUnset != 0)
|
||||||
{
|
{
|
||||||
// if unable to use git.exe unset http.extraheader or core.askpass, modify git config file on disk. make sure we don't left credential.
|
// if unable to use git.exe unset http.extraheader, http.proxy or core.askpass, modify git config file on disk. make sure we don't left credential.
|
||||||
if (!string.IsNullOrEmpty(configValue))
|
if (!string.IsNullOrEmpty(configValue))
|
||||||
{
|
{
|
||||||
executionContext.Warning("An unsuccessful attempt was made using git command line to remove \"http.extraheader\" from the git config. Attempting to modify the git config file directly to remove the credential.");
|
executionContext.Warning("An unsuccessful attempt was made using git command line to remove \"http.extraheader\" from the git config. Attempting to modify the git config file directly to remove the credential.");
|
||||||
@@ -605,6 +650,9 @@ namespace GitHub.Runner.Plugins.Repository.v1_0
|
|||||||
string setting = $"extraheader = {configValue}";
|
string setting = $"extraheader = {configValue}";
|
||||||
gitConfigContent = Regex.Replace(gitConfigContent, setting, string.Empty, RegexOptions.IgnoreCase);
|
gitConfigContent = Regex.Replace(gitConfigContent, setting, string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
setting = $"proxy = {configValue}";
|
||||||
|
gitConfigContent = Regex.Replace(gitConfigContent, setting, string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
setting = $"askpass = {configValue}";
|
setting = $"askpass = {configValue}";
|
||||||
gitConfigContent = Regex.Replace(gitConfigContent, setting, string.Empty, RegexOptions.IgnoreCase);
|
gitConfigContent = Regex.Replace(gitConfigContent, setting, string.Empty, RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
// Validate args.
|
// Validate args.
|
||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
Dictionary<string, string> configModifications = new Dictionary<string, string>();
|
Dictionary<string, string> configModifications = new Dictionary<string, string>();
|
||||||
|
Uri proxyUrlWithCred = null;
|
||||||
|
string proxyUrlWithCredString = null;
|
||||||
bool useSelfSignedCACert = false;
|
bool useSelfSignedCACert = false;
|
||||||
bool useClientCert = false;
|
bool useClientCert = false;
|
||||||
string clientCertPrivateKeyAskPassFile = null;
|
string clientCertPrivateKeyAskPassFile = null;
|
||||||
@@ -151,6 +153,18 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
|
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
|
||||||
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
|
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
|
||||||
|
|
||||||
|
// prepare credentail embedded urls
|
||||||
|
var runnerProxy = executionContext.GetProxyConfiguration();
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
proxyUrlWithCred = UrlUtil.GetCredentialEmbeddedUrl(new Uri(runnerProxy.ProxyAddress), runnerProxy.ProxyUsername, runnerProxy.ProxyPassword);
|
||||||
|
|
||||||
|
// uri.absoluteuri will not contains port info if the scheme is http/https and the port is 80/443
|
||||||
|
// however, git.exe always require you provide port info, if nothing passed in, it will use 1080 as default
|
||||||
|
// as result, we need prefer the uri.originalstring over uri.absoluteuri.
|
||||||
|
proxyUrlWithCredString = proxyUrlWithCred.OriginalString;
|
||||||
|
}
|
||||||
|
|
||||||
// prepare askpass for client cert private key, if the repository's endpoint url match the runner config url
|
// prepare askpass for client cert private key, if the repository's endpoint url match the runner config url
|
||||||
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
if (runnerCert != null && Uri.Compare(repositoryUrl, systemConnection.Url, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) == 0)
|
if (runnerCert != null && Uri.Compare(repositoryUrl, systemConnection.Url, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) == 0)
|
||||||
@@ -341,6 +355,13 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
|
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always remove any possible left proxy setting from git config, the proxy setting may contains credential
|
||||||
|
if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.proxy"))
|
||||||
|
{
|
||||||
|
executionContext.Debug("Remove any proxy setting from git config.");
|
||||||
|
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.proxy", string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
List<string> additionalFetchArgs = new List<string>();
|
List<string> additionalFetchArgs = new List<string>();
|
||||||
List<string> additionalLfsFetchArgs = new List<string>();
|
List<string> additionalLfsFetchArgs = new List<string>();
|
||||||
|
|
||||||
@@ -355,6 +376,15 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
throw new InvalidOperationException($"Git config failed with exit code: {exitCode_config}");
|
throw new InvalidOperationException($"Git config failed with exit code: {exitCode_config}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare proxy config for fetch.
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
executionContext.Debug($"Config proxy server '{runnerProxy.ProxyAddress}' for git fetch.");
|
||||||
|
ArgUtil.NotNullOrEmpty(proxyUrlWithCredString, nameof(proxyUrlWithCredString));
|
||||||
|
additionalFetchArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
additionalLfsFetchArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare ignore ssl cert error config for fetch.
|
// Prepare ignore ssl cert error config for fetch.
|
||||||
if (acceptUntrustedCerts)
|
if (acceptUntrustedCerts)
|
||||||
{
|
{
|
||||||
@@ -484,6 +514,14 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
|
|
||||||
List<string> additionalSubmoduleUpdateArgs = new List<string>();
|
List<string> additionalSubmoduleUpdateArgs = new List<string>();
|
||||||
|
|
||||||
|
// Prepare proxy config for submodule update.
|
||||||
|
if (runnerProxy != null && !string.IsNullOrEmpty(runnerProxy.ProxyAddress) && !runnerProxy.WebProxy.IsBypassed(repositoryUrl))
|
||||||
|
{
|
||||||
|
executionContext.Debug($"Config proxy server '{runnerProxy.ProxyAddress}' for git submodule update.");
|
||||||
|
ArgUtil.NotNullOrEmpty(proxyUrlWithCredString, nameof(proxyUrlWithCredString));
|
||||||
|
additionalSubmoduleUpdateArgs.Add($"-c http.proxy=\"{proxyUrlWithCredString}\"");
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare ignore ssl cert error config for fetch.
|
// Prepare ignore ssl cert error config for fetch.
|
||||||
if (acceptUntrustedCerts)
|
if (acceptUntrustedCerts)
|
||||||
{
|
{
|
||||||
@@ -554,7 +592,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
GitCliManager gitCommandManager = new GitCliManager();
|
GitCliManager gitCommandManager = new GitCliManager();
|
||||||
await gitCommandManager.LoadGitExecutionInfo(executionContext);
|
await gitCommandManager.LoadGitExecutionInfo(executionContext);
|
||||||
|
|
||||||
executionContext.Debug("Remove any extraheader setting from git config.");
|
executionContext.Debug("Remove any extraheader and proxy setting from git config.");
|
||||||
var configKeys = JsonUtility.FromString<List<string>>(Environment.GetEnvironmentVariable("STATE_modifiedgitconfig"));
|
var configKeys = JsonUtility.FromString<List<string>>(Environment.GetEnvironmentVariable("STATE_modifiedgitconfig"));
|
||||||
if (configKeys?.Count > 0)
|
if (configKeys?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -639,7 +677,7 @@ namespace GitHub.Runner.Plugins.Repository.v1_1
|
|||||||
int exitCode_configUnset = await gitCommandManager.GitConfigUnset(executionContext, targetPath, configKey);
|
int exitCode_configUnset = await gitCommandManager.GitConfigUnset(executionContext, targetPath, configKey);
|
||||||
if (exitCode_configUnset != 0)
|
if (exitCode_configUnset != 0)
|
||||||
{
|
{
|
||||||
// if unable to use git.exe unset http.extraheader or core.askpass, modify git config file on disk. make sure we don't left credential.
|
// if unable to use git.exe unset http.extraheader, http.proxy or core.askpass, modify git config file on disk. make sure we don't left credential.
|
||||||
if (!string.IsNullOrEmpty(configValue))
|
if (!string.IsNullOrEmpty(configValue))
|
||||||
{
|
{
|
||||||
executionContext.Warning("An unsuccessful attempt was made using git command line to remove \"http.extraheader\" from the git config. Attempting to modify the git config file directly to remove the credential.");
|
executionContext.Warning("An unsuccessful attempt was made using git command line to remove \"http.extraheader\" from the git config. Attempting to modify the git config file directly to remove the credential.");
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
@@ -19,5 +19,43 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace GitHub.Runner.Sdk
|
|||||||
{
|
{
|
||||||
private readonly string DebugEnvironmentalVariable = "ACTIONS_STEP_DEBUG";
|
private readonly string DebugEnvironmentalVariable = "ACTIONS_STEP_DEBUG";
|
||||||
private VssConnection _connection;
|
private VssConnection _connection;
|
||||||
private RunnerWebProxy _webProxy;
|
|
||||||
private readonly object _stdoutLock = new object();
|
private readonly object _stdoutLock = new object();
|
||||||
private readonly ITraceWriter _trace; // for unit tests
|
private readonly ITraceWriter _trace; // for unit tests
|
||||||
|
|
||||||
@@ -58,19 +57,6 @@ namespace GitHub.Runner.Sdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public RunnerWebProxy WebProxy
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_webProxy == null)
|
|
||||||
{
|
|
||||||
_webProxy = new RunnerWebProxy();
|
|
||||||
}
|
|
||||||
return _webProxy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public VssConnection InitializeVssConnection()
|
public VssConnection InitializeVssConnection()
|
||||||
{
|
{
|
||||||
var headerValues = new List<ProductInfoHeaderValue>();
|
var headerValues = new List<ProductInfoHeaderValue>();
|
||||||
@@ -98,7 +84,15 @@ namespace GitHub.Runner.Sdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VssHttpMessageHandler.DefaultWebProxy = this.WebProxy;
|
var proxySetting = GetProxyConfiguration();
|
||||||
|
if (proxySetting != null)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(proxySetting.ProxyAddress))
|
||||||
|
{
|
||||||
|
VssHttpMessageHandler.DefaultWebProxy = new RunnerWebProxyCore(proxySetting.ProxyAddress, proxySetting.ProxyUsername, proxySetting.ProxyPassword, proxySetting.ProxyBypassList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ServiceEndpoint systemConnection = this.Endpoints.FirstOrDefault(e => string.Equals(e.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
ServiceEndpoint systemConnection = this.Endpoints.FirstOrDefault(e => string.Equals(e.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
|
||||||
ArgUtil.NotNull(systemConnection, nameof(systemConnection));
|
ArgUtil.NotNull(systemConnection, nameof(systemConnection));
|
||||||
ArgUtil.NotNull(systemConnection.Url, nameof(systemConnection.Url));
|
ArgUtil.NotNull(systemConnection.Url, nameof(systemConnection.Url));
|
||||||
@@ -261,6 +255,29 @@ namespace GitHub.Runner.Sdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RunnerWebProxySettings GetProxyConfiguration()
|
||||||
|
{
|
||||||
|
string proxyUrl = GetRunnerContext("ProxyUrl");
|
||||||
|
if (!string.IsNullOrEmpty(proxyUrl))
|
||||||
|
{
|
||||||
|
string proxyUsername = GetRunnerContext("ProxyUsername");
|
||||||
|
string proxyPassword = GetRunnerContext("ProxyPassword");
|
||||||
|
List<string> proxyBypassHosts = StringUtil.ConvertFromJson<List<string>>(GetRunnerContext("ProxyBypassList") ?? "[]");
|
||||||
|
return new RunnerWebProxySettings()
|
||||||
|
{
|
||||||
|
ProxyAddress = proxyUrl,
|
||||||
|
ProxyUsername = proxyUsername,
|
||||||
|
ProxyPassword = proxyPassword,
|
||||||
|
ProxyBypassList = proxyBypassHosts,
|
||||||
|
WebProxy = new RunnerWebProxyCore(proxyUrl, proxyUsername, proxyPassword, proxyBypassHosts)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string Escape(string input)
|
private string Escape(string input)
|
||||||
{
|
{
|
||||||
foreach (var mapping in _commandEscapeMappings)
|
foreach (var mapping in _commandEscapeMappings)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
@@ -24,5 +24,43 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,224 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Sdk
|
|
||||||
{
|
|
||||||
public struct ByPassInfo
|
|
||||||
{
|
|
||||||
public string Host { get; set; }
|
|
||||||
|
|
||||||
public string Port { get; set; }
|
|
||||||
};
|
|
||||||
|
|
||||||
public class RunnerWebProxy : IWebProxy
|
|
||||||
{
|
|
||||||
private string _httpProxyAddress;
|
|
||||||
private string _httpProxyUsername;
|
|
||||||
private string _httpProxyPassword;
|
|
||||||
|
|
||||||
private string _httpsProxyAddress;
|
|
||||||
private string _httpsProxyUsername;
|
|
||||||
private string _httpsProxyPassword;
|
|
||||||
|
|
||||||
private readonly List<ByPassInfo> _noProxyList = new List<ByPassInfo>();
|
|
||||||
private readonly HashSet<string> _noProxyUnique = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
private readonly Regex _validIpRegex = new Regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", RegexOptions.Compiled);
|
|
||||||
|
|
||||||
public string HttpProxyAddress => _httpProxyAddress;
|
|
||||||
public string HttpProxyUsername => _httpProxyUsername;
|
|
||||||
public string HttpProxyPassword => _httpProxyPassword;
|
|
||||||
|
|
||||||
public string HttpsProxyAddress => _httpsProxyAddress;
|
|
||||||
public string HttpsProxyUsername => _httpsProxyUsername;
|
|
||||||
public string HttpsProxyPassword => _httpsProxyPassword;
|
|
||||||
|
|
||||||
public List<ByPassInfo> NoProxyList => _noProxyList;
|
|
||||||
|
|
||||||
public ICredentials Credentials { get; set; }
|
|
||||||
|
|
||||||
public RunnerWebProxy()
|
|
||||||
{
|
|
||||||
Credentials = new CredentialCache();
|
|
||||||
|
|
||||||
var httpProxyAddress = Environment.GetEnvironmentVariable("http_proxy");
|
|
||||||
if (string.IsNullOrEmpty(httpProxyAddress))
|
|
||||||
{
|
|
||||||
httpProxyAddress = Environment.GetEnvironmentVariable("HTTP_PROXY");
|
|
||||||
}
|
|
||||||
httpProxyAddress = httpProxyAddress?.Trim();
|
|
||||||
|
|
||||||
var httpsProxyAddress = Environment.GetEnvironmentVariable("https_proxy");
|
|
||||||
if (string.IsNullOrEmpty(httpsProxyAddress))
|
|
||||||
{
|
|
||||||
httpsProxyAddress = Environment.GetEnvironmentVariable("HTTPS_PROXY");
|
|
||||||
}
|
|
||||||
httpsProxyAddress = httpsProxyAddress?.Trim();
|
|
||||||
|
|
||||||
var noProxyList = Environment.GetEnvironmentVariable("no_proxy");
|
|
||||||
if (string.IsNullOrEmpty(noProxyList))
|
|
||||||
{
|
|
||||||
noProxyList = Environment.GetEnvironmentVariable("NO_PROXY");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(httpProxyAddress) && string.IsNullOrEmpty(httpsProxyAddress))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(httpProxyAddress) && Uri.TryCreate(httpProxyAddress, UriKind.Absolute, out var proxyHttpUri))
|
|
||||||
{
|
|
||||||
_httpProxyAddress = proxyHttpUri.AbsoluteUri;
|
|
||||||
|
|
||||||
// the proxy url looks like http://[user:pass@]127.0.0.1:8888
|
|
||||||
var userInfo = Uri.UnescapeDataString(proxyHttpUri.UserInfo).Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (userInfo.Length == 2)
|
|
||||||
{
|
|
||||||
_httpProxyUsername = userInfo[0];
|
|
||||||
_httpProxyPassword = userInfo[1];
|
|
||||||
}
|
|
||||||
else if (userInfo.Length == 1)
|
|
||||||
{
|
|
||||||
_httpProxyUsername = userInfo[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_httpProxyUsername) || !string.IsNullOrEmpty(_httpProxyPassword))
|
|
||||||
{
|
|
||||||
var credentials = new NetworkCredential(_httpProxyUsername, _httpProxyPassword);
|
|
||||||
|
|
||||||
// Replace the entry in the credential cache if it exists
|
|
||||||
(Credentials as CredentialCache).Remove(proxyHttpUri, "Basic");
|
|
||||||
(Credentials as CredentialCache).Add(proxyHttpUri, "Basic", credentials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(httpsProxyAddress) && Uri.TryCreate(httpsProxyAddress, UriKind.Absolute, out var proxyHttpsUri))
|
|
||||||
{
|
|
||||||
_httpsProxyAddress = proxyHttpsUri.AbsoluteUri;
|
|
||||||
|
|
||||||
// the proxy url looks like http://[user:pass@]127.0.0.1:8888
|
|
||||||
var userInfo = Uri.UnescapeDataString(proxyHttpsUri.UserInfo).Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (userInfo.Length == 2)
|
|
||||||
{
|
|
||||||
_httpsProxyUsername = userInfo[0];
|
|
||||||
_httpsProxyPassword = userInfo[1];
|
|
||||||
}
|
|
||||||
else if (userInfo.Length == 1)
|
|
||||||
{
|
|
||||||
_httpsProxyUsername = userInfo[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_httpsProxyUsername) || !string.IsNullOrEmpty(_httpsProxyPassword))
|
|
||||||
{
|
|
||||||
var credentials = new NetworkCredential(_httpsProxyUsername, _httpsProxyPassword);
|
|
||||||
|
|
||||||
// Replace the entry in the credential cache if it exists
|
|
||||||
(Credentials as CredentialCache).Remove(proxyHttpsUri, "Basic");
|
|
||||||
(Credentials as CredentialCache).Add(proxyHttpsUri, "Basic", credentials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(noProxyList))
|
|
||||||
{
|
|
||||||
var noProxyListSplit = noProxyList.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
foreach (string noProxy in noProxyListSplit)
|
|
||||||
{
|
|
||||||
var noProxyTrim = noProxy.Trim();
|
|
||||||
if (string.IsNullOrEmpty(noProxyTrim))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (_noProxyUnique.Add(noProxyTrim))
|
|
||||||
{
|
|
||||||
var noProxyInfo = new ByPassInfo();
|
|
||||||
var noProxyHostPort = noProxyTrim.Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
if (noProxyHostPort.Length == 1)
|
|
||||||
{
|
|
||||||
noProxyInfo.Host = noProxyHostPort[0];
|
|
||||||
}
|
|
||||||
else if (noProxyHostPort.Length == 2)
|
|
||||||
{
|
|
||||||
noProxyInfo.Host = noProxyHostPort[0];
|
|
||||||
noProxyInfo.Port = noProxyHostPort[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't support IP address for no_proxy
|
|
||||||
if (_validIpRegex.IsMatch(noProxyInfo.Host))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_noProxyList.Add(noProxyInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri GetProxy(Uri destination)
|
|
||||||
{
|
|
||||||
if (IsBypassed(destination))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (destination.Scheme == Uri.UriSchemeHttps)
|
|
||||||
{
|
|
||||||
return new Uri(_httpsProxyAddress);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new Uri(_httpProxyAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsBypassed(Uri uri)
|
|
||||||
{
|
|
||||||
if (uri.Scheme == Uri.UriSchemeHttps && string.IsNullOrEmpty(_httpsProxyAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uri.Scheme == Uri.UriSchemeHttp && string.IsNullOrEmpty(_httpProxyAddress))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return uri.IsLoopback || IsUriInBypassList(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsUriInBypassList(Uri input)
|
|
||||||
{
|
|
||||||
foreach (var noProxy in _noProxyList)
|
|
||||||
{
|
|
||||||
var matchHost = false;
|
|
||||||
var matchPort = false;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(noProxy.Port))
|
|
||||||
{
|
|
||||||
matchPort = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matchPort = string.Equals(noProxy.Port, input.Port.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noProxy.Host.StartsWith('.'))
|
|
||||||
{
|
|
||||||
matchHost = input.Host.EndsWith(noProxy.Host, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matchHost = string.Equals(input.Host, noProxy.Host, StringComparison.OrdinalIgnoreCase) || input.Host.EndsWith($".{noProxy.Host}", StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchHost && matchPort)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
104
src/Runner.Sdk/RunnerWebProxyCore.cs
Normal file
104
src/Runner.Sdk/RunnerWebProxyCore.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Sdk
|
||||||
|
{
|
||||||
|
public class RunnerWebProxySettings
|
||||||
|
{
|
||||||
|
public string ProxyAddress { get; set; }
|
||||||
|
public string ProxyUsername { get; set; }
|
||||||
|
public string ProxyPassword { get; set; }
|
||||||
|
public List<string> ProxyBypassList { get; set; }
|
||||||
|
public IWebProxy WebProxy { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RunnerWebProxyCore : IWebProxy
|
||||||
|
{
|
||||||
|
private string _proxyAddress;
|
||||||
|
private readonly List<Regex> _regExBypassList = new List<Regex>();
|
||||||
|
|
||||||
|
public ICredentials Credentials { get; set; }
|
||||||
|
|
||||||
|
public RunnerWebProxyCore()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public RunnerWebProxyCore(string proxyAddress, string proxyUsername, string proxyPassword, List<string> proxyBypassList)
|
||||||
|
{
|
||||||
|
Update(proxyAddress, proxyUsername, proxyPassword, proxyBypassList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(string proxyAddress, string proxyUsername, string proxyPassword, List<string> proxyBypassList)
|
||||||
|
{
|
||||||
|
_proxyAddress = proxyAddress?.Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(proxyUsername) || string.IsNullOrEmpty(proxyPassword))
|
||||||
|
{
|
||||||
|
Credentials = CredentialCache.DefaultNetworkCredentials;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Credentials = new NetworkCredential(proxyUsername, proxyPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyBypassList != null)
|
||||||
|
{
|
||||||
|
foreach (string bypass in proxyBypassList)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(bypass))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Regex bypassRegex = new Regex(bypass.Trim(), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.ECMAScript);
|
||||||
|
_regExBypassList.Add(bypassRegex);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// eat all exceptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri GetProxy(Uri destination)
|
||||||
|
{
|
||||||
|
if (IsBypassed(destination))
|
||||||
|
{
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new Uri(_proxyAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsBypassed(Uri uri)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(_proxyAddress) || uri.IsLoopback || IsMatchInBypassList(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsMatchInBypassList(Uri input)
|
||||||
|
{
|
||||||
|
string matchUriString = input.IsDefaultPort ?
|
||||||
|
input.Scheme + "://" + input.Host :
|
||||||
|
input.Scheme + "://" + input.Host + ":" + input.Port.ToString();
|
||||||
|
|
||||||
|
foreach (Regex r in _regExBypassList)
|
||||||
|
{
|
||||||
|
if (r.IsMatch(matchUriString))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -122,10 +122,5 @@ namespace GitHub.Runner.Sdk
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string SubstringPrefix(string value, int count)
|
|
||||||
{
|
|
||||||
return value?.Substring(0, Math.Min(value.Length, count));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/Runner.Service/Windows/FinalPublicKey.snk
Normal file
BIN
src/Runner.Service/Windows/FinalPublicKey.snk
Normal file
Binary file not shown.
@@ -9,8 +9,9 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>RunnerService</RootNamespace>
|
<RootNamespace>RunnerService</RootNamespace>
|
||||||
<AssemblyName>RunnerService</AssemblyName>
|
<AssemblyName>RunnerService</AssemblyName>
|
||||||
<SignAssembly>false</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
<DelaySign>false</DelaySign>
|
<AssemblyOriginatorKeyFile>FinalPublicKey.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<DelaySign>true</DelaySign>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
|
<None Include="FinalPublicKey.snk" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Resource.resx">
|
<EmbeddedResource Include="Resource.resx">
|
||||||
|
|||||||
@@ -547,6 +547,7 @@ namespace GitHub.Runner.Worker
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception($"Invalid echo command value. Possible values can be: 'on', 'off'. Current value is: '{command.Data}'.");
|
throw new Exception($"Invalid echo command value. Possible values can be: 'on', 'off'. Current value is: '{command.Data}'.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,9 +276,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
return await ExecuteDockerCommandAsync(context, "exec", $"{options} {containerId} {command}", context.CancellationToken);
|
return await ExecuteDockerCommandAsync(context, "exec", $"{options} {containerId} {command}", context.CancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
|
|
||||||
public async Task<int> DockerExec(IExecutionContext context, string containerId, string options, string command, List<string> output)
|
public async Task<int> DockerExec(IExecutionContext context, string containerId, string options, string command, List<string> output)
|
||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
|
||||||
{
|
{
|
||||||
ArgUtil.NotNull(output, nameof(output));
|
ArgUtil.NotNull(output, nameof(output));
|
||||||
|
|
||||||
@@ -339,9 +337,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
return ExecuteDockerCommandAsync(context, command, options, null, cancellationToken);
|
return ExecuteDockerCommandAsync(context, command, options, null, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
|
|
||||||
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary<string, string> environment, EventHandler<ProcessDataReceivedEventArgs> stdoutDataReceived, EventHandler<ProcessDataReceivedEventArgs> stderrDataReceived, CancellationToken cancellationToken = default(CancellationToken))
|
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary<string, string> environment, EventHandler<ProcessDataReceivedEventArgs> stdoutDataReceived, EventHandler<ProcessDataReceivedEventArgs> stderrDataReceived, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
|
||||||
{
|
{
|
||||||
string arg = $"{command} {options}".Trim();
|
string arg = $"{command} {options}".Trim();
|
||||||
context.Command($"{DockerPath} {arg}");
|
context.Command($"{DockerPath} {arg}");
|
||||||
@@ -366,9 +362,7 @@ namespace GitHub.Runner.Worker.Container
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
|
|
||||||
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, string workingDirectory, CancellationToken cancellationToken = default(CancellationToken))
|
private async Task<int> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, string workingDirectory, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
|
||||||
{
|
{
|
||||||
string arg = $"{command} {options}".Trim();
|
string arg = $"{command} {options}".Trim();
|
||||||
context.Command($"{DockerPath} {arg}");
|
context.Command($"{DockerPath} {arg}");
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
||||||
}
|
}
|
||||||
|
#elif OS_RHEL6
|
||||||
|
// Red Hat and CentOS 6 do not support the container feature
|
||||||
|
throw new NotSupportedException("Runner does not support the container feature on Red Hat Enterprise Linux 6 or CentOS 6.");
|
||||||
#else
|
#else
|
||||||
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
||||||
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace GitHub.Runner.Worker
|
|||||||
[ServiceLocator(Default = typeof(DiagnosticLogManager))]
|
[ServiceLocator(Default = typeof(DiagnosticLogManager))]
|
||||||
public interface IDiagnosticLogManager : IRunnerService
|
public interface IDiagnosticLogManager : IRunnerService
|
||||||
{
|
{
|
||||||
void UploadDiagnosticLogs(IExecutionContext executionContext,
|
Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
|
||||||
IExecutionContext parentContext,
|
IExecutionContext parentContext,
|
||||||
Pipelines.AgentJobRequestMessage message,
|
Pipelines.AgentJobRequestMessage message,
|
||||||
DateTime jobStartTimeUtc);
|
DateTime jobStartTimeUtc);
|
||||||
@@ -31,10 +31,10 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class DiagnosticLogManager : RunnerService, IDiagnosticLogManager
|
public sealed class DiagnosticLogManager : RunnerService, IDiagnosticLogManager
|
||||||
{
|
{
|
||||||
private static string DateTimeFormat = "yyyyMMdd-HHmmss";
|
private static string DateTimeFormat = "yyyyMMdd-HHmmss";
|
||||||
public void UploadDiagnosticLogs(IExecutionContext executionContext,
|
public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
|
||||||
IExecutionContext parentContext,
|
IExecutionContext parentContext,
|
||||||
Pipelines.AgentJobRequestMessage message,
|
Pipelines.AgentJobRequestMessage message,
|
||||||
DateTime jobStartTimeUtc)
|
DateTime jobStartTimeUtc)
|
||||||
{
|
{
|
||||||
executionContext.Debug("Starting diagnostic file upload.");
|
executionContext.Debug("Starting diagnostic file upload.");
|
||||||
|
|
||||||
|
|||||||
@@ -616,6 +616,29 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// PostJobSteps for job ExecutionContext
|
// PostJobSteps for job ExecutionContext
|
||||||
PostJobSteps = new Stack<IStep>();
|
PostJobSteps = new Stack<IStep>();
|
||||||
|
// Proxy variables
|
||||||
|
// var agentWebProxy = HostContext.GetService<IRunnerWebProxy>();
|
||||||
|
// if (!string.IsNullOrEmpty(agentWebProxy.ProxyAddress))
|
||||||
|
// {
|
||||||
|
// SetRunnerContext("proxyurl", agentWebProxy.ProxyAddress);
|
||||||
|
|
||||||
|
// if (!string.IsNullOrEmpty(agentWebProxy.ProxyUsername))
|
||||||
|
// {
|
||||||
|
// SetRunnerContext("proxyusername", agentWebProxy.ProxyUsername);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!string.IsNullOrEmpty(agentWebProxy.ProxyPassword))
|
||||||
|
// {
|
||||||
|
// HostContext.SecretMasker.AddValue(agentWebProxy.ProxyPassword);
|
||||||
|
// SetRunnerContext("proxypassword", agentWebProxy.ProxyPassword);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (agentWebProxy.ProxyBypassList.Count > 0)
|
||||||
|
// {
|
||||||
|
// SetRunnerContext("proxybypasslist", JsonUtility.ToString(agentWebProxy.ProxyBypassList));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// // Certificate variables
|
// // Certificate variables
|
||||||
// var agentCert = HostContext.GetService<IRunnerCertificateManager>();
|
// var agentCert = HostContext.GetService<IRunnerCertificateManager>();
|
||||||
// if (agentCert.SkipServerCertificateValidation)
|
// if (agentCert.SkipServerCertificateValidation)
|
||||||
@@ -851,6 +874,33 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
this.Warning(string.Format("The job is currently being throttled by the server. You may experience delays in console line output, job status reporting, and action log uploads."));
|
this.Warning(string.Format("The job is currently being throttled by the server. You may experience delays in console line output, job status reporting, and action log uploads."));
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(this.Variables.System_TFCollectionUrl))
|
||||||
|
{
|
||||||
|
// Construct a URL to the resource utilization page, to aid the user debug throttling issues
|
||||||
|
UriBuilder uriBuilder = new UriBuilder(Variables.System_TFCollectionUrl);
|
||||||
|
NameValueCollection query = HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||||
|
DateTime endTime = DateTime.UtcNow;
|
||||||
|
string queryDate = endTime.AddHours(-1).ToString("s") + "," + endTime.ToString("s");
|
||||||
|
|
||||||
|
uriBuilder.Path += (Variables.System_TFCollectionUrl.EndsWith("/") ? "" : "/") + "_usersSettings/usage";
|
||||||
|
query["tab"] = "pipelines";
|
||||||
|
query["queryDate"] = queryDate;
|
||||||
|
|
||||||
|
// Global RU link
|
||||||
|
uriBuilder.Query = query.ToString();
|
||||||
|
string global = $"Link to resource utilization page (global 1-hour view): {uriBuilder.ToString()}.";
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(this.Variables.Build_DefinitionName))
|
||||||
|
{
|
||||||
|
query["keywords"] = this.Variables.Build_Number;
|
||||||
|
query["definition"] = this.Variables.Build_DefinitionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RU link scoped for the build/release
|
||||||
|
uriBuilder.Query = query.ToString();
|
||||||
|
this.Warning($"{global}\nLink to resource utilization page (1-hour view by pipeline): {uriBuilder.ToString()}.");
|
||||||
|
}
|
||||||
|
|
||||||
_throttlingReported = true;
|
_throttlingReported = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
{
|
{
|
||||||
public ContainerActionExecutionData Data { get; set; }
|
public ContainerActionExecutionData Data { get; set; }
|
||||||
|
|
||||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
|
|
||||||
public async Task RunAsync(ActionRunStage stage)
|
public async Task RunAsync(ActionRunStage stage)
|
||||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
|
||||||
{
|
{
|
||||||
// Validate args.
|
// Validate args.
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
|
|||||||
@@ -18,46 +18,44 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
private static readonly Regex _colorCodeRegex = new Regex(@"\x0033\[[0-9;]*m?", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
private static readonly Regex _colorCodeRegex = new Regex(@"\x0033\[[0-9;]*m?", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
||||||
private readonly IActionCommandManager _commandManager;
|
private readonly IActionCommandManager _commandManager;
|
||||||
private readonly IExecutionContext _executionContext;
|
private readonly IExecutionContext _executionContext;
|
||||||
private readonly int _failsafe = 50;
|
|
||||||
private readonly object _matchersLock = new object();
|
private readonly object _matchersLock = new object();
|
||||||
private readonly TimeSpan _timeout;
|
private readonly TimeSpan _timeout;
|
||||||
private IssueMatcher[] _matchers = Array.Empty<IssueMatcher>();
|
private IssueMatcher[] _matchers = Array.Empty<IssueMatcher>();
|
||||||
// Mapping that indicates whether a directory belongs to the workflow repository
|
|
||||||
private readonly Dictionary<string, string> _directoryMap = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
public OutputManager(IExecutionContext executionContext, IActionCommandManager commandManager)
|
public OutputManager(IExecutionContext executionContext, IActionCommandManager commandManager)
|
||||||
{
|
{
|
||||||
|
//executionContext.Debug("ENTERING OutputManager ctor");
|
||||||
_executionContext = executionContext;
|
_executionContext = executionContext;
|
||||||
_commandManager = commandManager;
|
_commandManager = commandManager;
|
||||||
|
|
||||||
// Recursion failsafe (test override)
|
//_executionContext.Debug("OutputManager ctor - determine timeout from variable");
|
||||||
var failsafeString = Environment.GetEnvironmentVariable("RUNNER_TEST_GET_REPOSITORY_PATH_FAILSAFE");
|
|
||||||
if (!string.IsNullOrEmpty(failsafeString))
|
|
||||||
{
|
|
||||||
_failsafe = int.Parse(failsafeString, NumberStyles.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the timeout
|
// Determine the timeout
|
||||||
var timeoutStr = _executionContext.Variables.Get(_timeoutKey);
|
var timeoutStr = _executionContext.Variables.Get(_timeoutKey);
|
||||||
if (string.IsNullOrEmpty(timeoutStr) ||
|
if (string.IsNullOrEmpty(timeoutStr) ||
|
||||||
!TimeSpan.TryParse(timeoutStr, CultureInfo.InvariantCulture, out _timeout) ||
|
!TimeSpan.TryParse(timeoutStr, CultureInfo.InvariantCulture, out _timeout) ||
|
||||||
_timeout <= TimeSpan.Zero)
|
_timeout <= TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
|
//_executionContext.Debug("OutputManager ctor - determine timeout from env var");
|
||||||
timeoutStr = Environment.GetEnvironmentVariable(_timeoutKey);
|
timeoutStr = Environment.GetEnvironmentVariable(_timeoutKey);
|
||||||
if (string.IsNullOrEmpty(timeoutStr) ||
|
if (string.IsNullOrEmpty(timeoutStr) ||
|
||||||
!TimeSpan.TryParse(timeoutStr, CultureInfo.InvariantCulture, out _timeout) ||
|
!TimeSpan.TryParse(timeoutStr, CultureInfo.InvariantCulture, out _timeout) ||
|
||||||
_timeout <= TimeSpan.Zero)
|
_timeout <= TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
|
//_executionContext.Debug("OutputManager ctor - set timeout to default");
|
||||||
_timeout = TimeSpan.FromSeconds(1);
|
_timeout = TimeSpan.FromSeconds(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//_executionContext.Debug("OutputManager ctor - adding matchers");
|
||||||
// Lock
|
// Lock
|
||||||
lock (_matchersLock)
|
lock (_matchersLock)
|
||||||
{
|
{
|
||||||
|
//_executionContext.Debug("OutputManager ctor - adding OnMatcherChanged");
|
||||||
_executionContext.Add(OnMatcherChanged);
|
_executionContext.Add(OnMatcherChanged);
|
||||||
|
//_executionContext.Debug("OutputManager ctor - getting matchers");
|
||||||
_matchers = _executionContext.GetMatchers().Select(x => new IssueMatcher(x, _timeout)).ToArray();
|
_matchers = _executionContext.GetMatchers().Select(x => new IssueMatcher(x, _timeout)).ToArray();
|
||||||
}
|
}
|
||||||
|
//_executionContext.Debug("LEAVING OutputManager ctor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -73,6 +71,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
|
|
||||||
public void OnDataReceived(object sender, ProcessDataReceivedEventArgs e)
|
public void OnDataReceived(object sender, ProcessDataReceivedEventArgs e)
|
||||||
{
|
{
|
||||||
|
//_executionContext.Debug("ENTERING OutputManager OnDataReceived");
|
||||||
var line = e.Data;
|
var line = e.Data;
|
||||||
|
|
||||||
// ## commands
|
// ## commands
|
||||||
@@ -83,6 +82,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// The logging queues and command handlers are thread-safe.
|
// The logging queues and command handlers are thread-safe.
|
||||||
if (_commandManager.TryProcessCommand(_executionContext, line))
|
if (_commandManager.TryProcessCommand(_executionContext, line))
|
||||||
{
|
{
|
||||||
|
//_executionContext.Debug("LEAVING OutputManager OnDataReceived - command processed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +142,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Log issue
|
// Log issue
|
||||||
_executionContext.AddIssue(issue, stripped);
|
_executionContext.AddIssue(issue, stripped);
|
||||||
|
|
||||||
|
//_executionContext.Debug("LEAVING OutputManager OnDataReceived - issue logged");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +151,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
|
|
||||||
// Regular output
|
// Regular output
|
||||||
_executionContext.Output(line);
|
_executionContext.Output(line);
|
||||||
|
//_executionContext.Debug("LEAVING OutputManager OnDataReceived");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMatcherChanged(object sender, MatcherChangedEventArgs e)
|
private void OnMatcherChanged(object sender, MatcherChangedEventArgs e)
|
||||||
@@ -259,45 +261,47 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
var file = match.File;
|
var file = match.File;
|
||||||
|
|
||||||
// Root using fromPath
|
// Root using fromPath
|
||||||
if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathFullyQualified(file))
|
if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file))
|
||||||
{
|
{
|
||||||
var fromDirectory = Path.GetDirectoryName(match.FromPath);
|
file = Path.Combine(match.FromPath, file);
|
||||||
if (!string.IsNullOrWhiteSpace(fromDirectory))
|
|
||||||
{
|
|
||||||
file = Path.Combine(fromDirectory, file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root using workspace
|
// Root using system.defaultWorkingDirectory
|
||||||
if (!Path.IsPathFullyQualified(file))
|
if (!Path.IsPathRooted(file))
|
||||||
{
|
{
|
||||||
var workspace = _executionContext.GetGitHubContext("workspace");
|
var githubContext = _executionContext.ExpressionValues["github"] as GitHubContext;
|
||||||
|
ArgUtil.NotNull(githubContext, nameof(githubContext));
|
||||||
|
var workspace = githubContext["workspace"].ToString();
|
||||||
ArgUtil.NotNullOrEmpty(workspace, "workspace");
|
ArgUtil.NotNullOrEmpty(workspace, "workspace");
|
||||||
|
|
||||||
file = Path.Combine(workspace, file);
|
file = Path.Combine(workspace, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove relative pathing and normalize slashes
|
// Normalize slashes
|
||||||
file = Path.GetFullPath(file);
|
file = file.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||||
|
|
||||||
// Check whether the file exists
|
// File exists
|
||||||
if (File.Exists(file))
|
if (File.Exists(file))
|
||||||
{
|
{
|
||||||
// Check whether the file is under the workflow repository
|
// Repository path
|
||||||
var repositoryPath = GetRepositoryPath(file);
|
var repositoryPath = _executionContext.GetGitHubContext("workspace");
|
||||||
if (!string.IsNullOrEmpty(repositoryPath))
|
ArgUtil.NotNullOrEmpty(repositoryPath, nameof(repositoryPath));
|
||||||
{
|
|
||||||
// Get the relative file path
|
|
||||||
var relativePath = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar);
|
|
||||||
|
|
||||||
// Prefer `/` on all platforms
|
// Normalize slashes
|
||||||
issue.Data["file"] = relativePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
repositoryPath = repositoryPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
if (!file.StartsWith(repositoryPath, IOUtil.FilePathStringComparison))
|
||||||
|
{
|
||||||
|
// File is not under repo
|
||||||
|
_executionContext.Debug($"Dropping file value '{file}'. Path is not under the repo.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_executionContext.Debug($"Dropping file value '{file}'. Path is not under the workflow repo.");
|
// prefer `/` on all platforms
|
||||||
|
issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// File does not exist
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_executionContext.Debug($"Dropping file value '{file}'. Path does not exist");
|
_executionContext.Debug($"Dropping file value '{file}'. Path does not exist");
|
||||||
@@ -311,60 +315,5 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
|
|
||||||
return issue;
|
return issue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetRepositoryPath(string filePath, int recursion = 0)
|
|
||||||
{
|
|
||||||
// Prevent the cache from growing too much
|
|
||||||
if (_directoryMap.Count > 100)
|
|
||||||
{
|
|
||||||
_directoryMap.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty directory means we hit the root of the drive
|
|
||||||
var directoryPath = Path.GetDirectoryName(filePath);
|
|
||||||
if (string.IsNullOrEmpty(directoryPath) || recursion > _failsafe)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the cache
|
|
||||||
if (_directoryMap.TryGetValue(directoryPath, out string repositoryPath))
|
|
||||||
{
|
|
||||||
return repositoryPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Check if .git/config exists
|
|
||||||
var gitConfigPath = Path.Combine(directoryPath, ".git", "config");
|
|
||||||
if (File.Exists(gitConfigPath))
|
|
||||||
{
|
|
||||||
// Check if the config contains the workflow repository url
|
|
||||||
var qualifiedRepository = _executionContext.GetGitHubContext("repository");
|
|
||||||
var configMatch = $"url = https://github.com/{qualifiedRepository}";
|
|
||||||
var content = File.ReadAllText(gitConfigPath);
|
|
||||||
foreach (var line in content.Split("\n").Select(x => x.Trim()))
|
|
||||||
{
|
|
||||||
if (String.Equals(line, configMatch, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
repositoryPath = directoryPath;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Recursive call
|
|
||||||
repositoryPath = GetRepositoryPath(directoryPath, recursion + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_executionContext.Debug($"Error when attempting to determine whether the path '{filePath}' is under the workflow repository: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_directoryMap[directoryPath] = repositoryPath;
|
|
||||||
return repositoryPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public sealed class IssueMatcher
|
public sealed class IssueMatcher
|
||||||
{
|
{
|
||||||
private string _defaultSeverity;
|
|
||||||
private string _owner;
|
private string _owner;
|
||||||
private IssuePattern[] _patterns;
|
private IssuePattern[] _patterns;
|
||||||
private IssueMatch[] _state;
|
private IssueMatch[] _state;
|
||||||
@@ -28,7 +27,6 @@ namespace GitHub.Runner.Worker
|
|||||||
public IssueMatcher(IssueMatcherConfig config, TimeSpan timeout)
|
public IssueMatcher(IssueMatcherConfig config, TimeSpan timeout)
|
||||||
{
|
{
|
||||||
_owner = config.Owner;
|
_owner = config.Owner;
|
||||||
_defaultSeverity = config.Severity;
|
|
||||||
_patterns = config.Patterns.Select(x => new IssuePattern(x , timeout)).ToArray();
|
_patterns = config.Patterns.Select(x => new IssuePattern(x , timeout)).ToArray();
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
@@ -39,26 +37,13 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
if (_owner == null)
|
if (_owner == null)
|
||||||
{
|
{
|
||||||
_owner = string.Empty;
|
_owner = String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _owner;
|
return _owner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DefaultSeverity
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_defaultSeverity == null)
|
|
||||||
{
|
|
||||||
_defaultSeverity = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _defaultSeverity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IssueMatch Match(string line)
|
public IssueMatch Match(string line)
|
||||||
{
|
{
|
||||||
// Single pattern
|
// Single pattern
|
||||||
@@ -69,7 +54,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
return new IssueMatch(null, pattern, regexMatch.Groups, DefaultSeverity);
|
return new IssueMatch(null, pattern, regexMatch.Groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -110,7 +95,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return new IssueMatch(runningMatch, pattern, regexMatch.Groups, DefaultSeverity);
|
return new IssueMatch(runningMatch, pattern, regexMatch.Groups);
|
||||||
}
|
}
|
||||||
// Not the last pattern
|
// Not the last pattern
|
||||||
else
|
else
|
||||||
@@ -184,7 +169,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public sealed class IssueMatch
|
public sealed class IssueMatch
|
||||||
{
|
{
|
||||||
public IssueMatch(IssueMatch runningMatch, IssuePattern pattern, GroupCollection groups, string defaultSeverity = null)
|
public IssueMatch(IssueMatch runningMatch, IssuePattern pattern, GroupCollection groups)
|
||||||
{
|
{
|
||||||
File = runningMatch?.File ?? GetValue(groups, pattern.File);
|
File = runningMatch?.File ?? GetValue(groups, pattern.File);
|
||||||
Line = runningMatch?.Line ?? GetValue(groups, pattern.Line);
|
Line = runningMatch?.Line ?? GetValue(groups, pattern.Line);
|
||||||
@@ -193,11 +178,6 @@ namespace GitHub.Runner.Worker
|
|||||||
Code = runningMatch?.Code ?? GetValue(groups, pattern.Code);
|
Code = runningMatch?.Code ?? GetValue(groups, pattern.Code);
|
||||||
Message = runningMatch?.Message ?? GetValue(groups, pattern.Message);
|
Message = runningMatch?.Message ?? GetValue(groups, pattern.Message);
|
||||||
FromPath = runningMatch?.FromPath ?? GetValue(groups, pattern.FromPath);
|
FromPath = runningMatch?.FromPath ?? GetValue(groups, pattern.FromPath);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Severity) && !string.IsNullOrEmpty(defaultSeverity))
|
|
||||||
{
|
|
||||||
Severity = defaultSeverity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string File { get; }
|
public string File { get; }
|
||||||
@@ -276,9 +256,6 @@ namespace GitHub.Runner.Worker
|
|||||||
[DataMember(Name = "owner")]
|
[DataMember(Name = "owner")]
|
||||||
private string _owner;
|
private string _owner;
|
||||||
|
|
||||||
[DataMember(Name = "severity")]
|
|
||||||
private string _severity;
|
|
||||||
|
|
||||||
[DataMember(Name = "pattern")]
|
[DataMember(Name = "pattern")]
|
||||||
private IssuePatternConfig[] _patterns;
|
private IssuePatternConfig[] _patterns;
|
||||||
|
|
||||||
@@ -288,7 +265,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
if (_owner == null)
|
if (_owner == null)
|
||||||
{
|
{
|
||||||
_owner = string.Empty;
|
_owner = String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _owner;
|
return _owner;
|
||||||
@@ -300,24 +277,6 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Severity
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_severity == null)
|
|
||||||
{
|
|
||||||
_severity = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _severity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_severity = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IssuePatternConfig[] Patterns
|
public IssuePatternConfig[] Patterns
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -344,17 +303,6 @@ namespace GitHub.Runner.Worker
|
|||||||
throw new ArgumentException("Owner must not be empty");
|
throw new ArgumentException("Owner must not be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate severity
|
|
||||||
switch ((_severity ?? string.Empty).ToUpperInvariant())
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
case "ERROR":
|
|
||||||
case "WARNING":
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException($"Matcher '{_owner}' contains unexpected default severity '{_severity}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate at least one pattern
|
// Validate at least one pattern
|
||||||
if (_patterns == null || _patterns.Length == 0)
|
if (_patterns == null || _patterns.Length == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public interface IJobExtension : IRunnerService
|
public interface IJobExtension : IRunnerService
|
||||||
{
|
{
|
||||||
Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message);
|
Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message);
|
||||||
void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
|
Task FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class JobExtension : RunnerService, IJobExtension
|
public sealed class JobExtension : RunnerService, IJobExtension
|
||||||
@@ -42,6 +42,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
List<IStep> preJobSteps = new List<IStep>();
|
List<IStep> preJobSteps = new List<IStep>();
|
||||||
List<IStep> jobSteps = new List<IStep>();
|
List<IStep> jobSteps = new List<IStep>();
|
||||||
|
List<IStep> postJobSteps = new List<IStep>();
|
||||||
using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); }))
|
using (var register = jobContext.CancellationToken.Register(() => { context.CancelToken(); }))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -54,13 +55,10 @@ namespace GitHub.Runner.Worker
|
|||||||
context.Debug($"Primary repository: {repoFullName}");
|
context.Debug($"Primary repository: {repoFullName}");
|
||||||
|
|
||||||
// Print proxy setting information for better diagnostic experience
|
// Print proxy setting information for better diagnostic experience
|
||||||
if (!string.IsNullOrEmpty(HostContext.WebProxy.HttpProxyAddress))
|
var runnerWebProxy = HostContext.GetService<IRunnerWebProxy>();
|
||||||
|
if (!string.IsNullOrEmpty(runnerWebProxy.ProxyAddress))
|
||||||
{
|
{
|
||||||
context.Output($"Runner is running behind proxy server '{HostContext.WebProxy.HttpProxyAddress}' for all HTTP requests.");
|
context.Output($"Runner is running behind proxy server: '{runnerWebProxy.ProxyAddress}'");
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(HostContext.WebProxy.HttpsProxyAddress))
|
|
||||||
{
|
|
||||||
context.Output($"Runner is running behind proxy server '{HostContext.WebProxy.HttpsProxyAddress}' for all HTTPS requests.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the workflow directory
|
// Prepare the workflow directory
|
||||||
@@ -230,7 +228,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
|
public async Task FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
ArgUtil.NotNull(jobContext, nameof(jobContext));
|
||||||
@@ -244,6 +242,19 @@ namespace GitHub.Runner.Worker
|
|||||||
context.Start();
|
context.Start();
|
||||||
context.Debug("Starting: Complete job");
|
context.Debug("Starting: Complete job");
|
||||||
|
|
||||||
|
// Wait for agent log plugin process exits
|
||||||
|
// var logPlugin = HostContext.GetService<IAgentLogPlugin>();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// await logPlugin.WaitAsync(context);
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// // Log and ignore the error from log plugin finalization.
|
||||||
|
// Trace.Error($"Caught exception from log plugin finalization: {ex}");
|
||||||
|
// context.Output(ex.Message);
|
||||||
|
// }
|
||||||
|
|
||||||
if (context.Variables.GetBoolean(Constants.Variables.Actions.RunnerDebug) ?? false)
|
if (context.Variables.GetBoolean(Constants.Variables.Actions.RunnerDebug) ?? false)
|
||||||
{
|
{
|
||||||
Trace.Info("Support log upload starting.");
|
Trace.Info("Support log upload starting.");
|
||||||
@@ -253,7 +264,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
diagnosticLogManager.UploadDiagnosticLogs(executionContext: context, parentContext: jobContext, message: message, jobStartTimeUtc: jobStartTimeUtc);
|
await diagnosticLogManager.UploadDiagnosticLogsAsync(executionContext: context, parentContext: jobContext, message: message, jobStartTimeUtc: jobStartTimeUtc);
|
||||||
|
|
||||||
Trace.Info("Support log upload complete.");
|
Trace.Info("Support log upload complete.");
|
||||||
context.Output("Completed runner diagnostic log upload");
|
context.Output("Completed runner diagnostic log upload");
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ namespace GitHub.Runner.Worker
|
|||||||
Directory.CreateDirectory(toolsDirectory);
|
Directory.CreateDirectory(toolsDirectory);
|
||||||
jobContext.SetRunnerContext("tool_cache", toolsDirectory);
|
jobContext.SetRunnerContext("tool_cache", toolsDirectory);
|
||||||
|
|
||||||
|
// remove variable from env
|
||||||
|
Environment.SetEnvironmentVariable("AGENT_TOOLSDIRECTORY", null);
|
||||||
|
Environment.SetEnvironmentVariable(Constants.Variables.Agent.ToolsDirectory, null);
|
||||||
|
|
||||||
// Setup TEMP directories
|
// Setup TEMP directories
|
||||||
_tempDirectoryManager = HostContext.GetService<ITempDirectoryManager>();
|
_tempDirectoryManager = HostContext.GetService<ITempDirectoryManager>();
|
||||||
_tempDirectoryManager.InitializeTempDirectory(jobContext);
|
_tempDirectoryManager.InitializeTempDirectory(jobContext);
|
||||||
@@ -179,7 +183,7 @@ namespace GitHub.Runner.Worker
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Trace.Info("Finalize job.");
|
Trace.Info("Finalize job.");
|
||||||
jobExtension.FinalizeJob(jobContext, message, jobStartTimeUtc);
|
await jobExtension.FinalizeJob(jobContext, message, jobStartTimeUtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Info($"Job result after all job steps finish: {jobContext.Result ?? TaskResult.Succeeded}");
|
Trace.Info($"Job result after all job steps finish: {jobContext.Result ?? TaskResult.Succeeded}");
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603</NoWarn>
|
<NoWarn>NU1701;NU1603</NoWarn>
|
||||||
<Version>$(Version)</Version>
|
<Version>$(Version)</Version>
|
||||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||||
<PublishReadyToRun>true</PublishReadyToRun>
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -35,4 +35,42 @@
|
|||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x64'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
|
<DefineConstants>OS_WINDOWS;X86;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">
|
||||||
|
<DefineConstants>OS_OSX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' AND '$(Configuration)' == 'Debug'">
|
||||||
|
<DefineConstants>OS_OSX;DEBUG;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'rhel.6-x64'">
|
||||||
|
<DefineConstants>OS_LINUX;OS_RHEL6;X64;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' AND '$(Configuration)' == 'Debug' AND '$(PackageRuntime)' == 'linux-arm'">
|
||||||
|
<DefineConstants>OS_LINUX;ARM;DEBUG;TRACE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using System;
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using GitHub.Build.WebApi;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.DistributedTask.Logging;
|
using GitHub.DistributedTask.Logging;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Common.Util;
|
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
@@ -63,7 +62,10 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// DO NOT add file path variable to here.
|
// DO NOT add file path variable to here.
|
||||||
// All file path variables needs to be retrive and set through ExecutionContext, so it can handle container file path translation.
|
// All file path variables needs to be retrive and set through ExecutionContext, so it can handle container file path translation.
|
||||||
public string Build_Number => Get(BuildVariables.BuildNumber);
|
|
||||||
|
public string Build_DefinitionName => Get(Constants.Variables.Build.DefinitionName);
|
||||||
|
|
||||||
|
public string Build_Number => Get(Constants.Variables.Build.Number);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
public bool Retain_Default_Encoding => false;
|
public bool Retain_Default_Encoding => false;
|
||||||
@@ -71,10 +73,44 @@ namespace GitHub.Runner.Worker
|
|||||||
public bool Retain_Default_Encoding => true;
|
public bool Retain_Default_Encoding => true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public string System_CollectionId => Get(Constants.Variables.System.CollectionId);
|
||||||
|
|
||||||
public bool? Step_Debug => GetBoolean(Constants.Variables.Actions.StepDebug);
|
public bool? Step_Debug => GetBoolean(Constants.Variables.Actions.StepDebug);
|
||||||
|
|
||||||
|
public string System_DefinitionId => Get(Constants.Variables.System.DefinitionId);
|
||||||
|
|
||||||
public string System_PhaseDisplayName => Get(Constants.Variables.System.PhaseDisplayName);
|
public string System_PhaseDisplayName => Get(Constants.Variables.System.PhaseDisplayName);
|
||||||
|
|
||||||
|
public string System_TFCollectionUrl => Get(WellKnownDistributedTaskVariables.TFCollectionUrl);
|
||||||
|
|
||||||
|
public static readonly HashSet<string> PiiVariables = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
"Build.AuthorizeAs",
|
||||||
|
"Build.QueuedBy",
|
||||||
|
"Build.RequestedFor",
|
||||||
|
"Build.RequestedForEmail",
|
||||||
|
"Build.SourceBranch",
|
||||||
|
"Build.SourceBranchName",
|
||||||
|
"Build.SourceTfvcShelveset",
|
||||||
|
"Build.SourceVersion",
|
||||||
|
"Build.SourceVersionAuthor",
|
||||||
|
"Job.AuthorizeAs",
|
||||||
|
"Release.Deployment.RequestedFor",
|
||||||
|
"Release.Deployment.RequestedForEmail",
|
||||||
|
"Release.RequestedFor",
|
||||||
|
"Release.RequestedForEmail",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly string PiiArtifactVariablePrefix = "Release.Artifacts";
|
||||||
|
|
||||||
|
public static readonly List<string> PiiArtifactVariableSuffixes = new List<string>()
|
||||||
|
{
|
||||||
|
"SourceBranch",
|
||||||
|
"SourceBranchName",
|
||||||
|
"SourceVersion",
|
||||||
|
"RequestedFor"
|
||||||
|
};
|
||||||
|
|
||||||
public string Get(string name)
|
public string Get(string name)
|
||||||
{
|
{
|
||||||
Variable variable;
|
Variable variable;
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ namespace GitHub.Runner.Worker
|
|||||||
// Validate args.
|
// Validate args.
|
||||||
ArgUtil.NotNullOrEmpty(pipeIn, nameof(pipeIn));
|
ArgUtil.NotNullOrEmpty(pipeIn, nameof(pipeIn));
|
||||||
ArgUtil.NotNullOrEmpty(pipeOut, nameof(pipeOut));
|
ArgUtil.NotNullOrEmpty(pipeOut, nameof(pipeOut));
|
||||||
|
var runnerWebProxy = HostContext.GetService<IRunnerWebProxy>();
|
||||||
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
var runnerCertManager = HostContext.GetService<IRunnerCertificateManager>();
|
||||||
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, HostContext.WebProxy, runnerCertManager.VssClientCertificateManager);
|
VssUtil.InitializeVssClientSettings(HostContext.UserAgent, runnerWebProxy.WebProxy, runnerCertManager.VssClientCertificateManager);
|
||||||
var jobRunner = HostContext.CreateService<IJobRunner>();
|
var jobRunner = HostContext.CreateService<IJobRunner>();
|
||||||
|
|
||||||
using (var channel = HostContext.CreateService<IProcessChannel>())
|
using (var channel = HostContext.CreateService<IProcessChannel>())
|
||||||
@@ -73,7 +74,7 @@ namespace GitHub.Runner.Worker
|
|||||||
SetCulture(jobMessage);
|
SetCulture(jobMessage);
|
||||||
|
|
||||||
// Start the job.
|
// Start the job.
|
||||||
Trace.Info($"Job message:{Environment.NewLine} {StringUtil.ConvertToJson(jobMessage)}");
|
Trace.Info($"Job message:{Environment.NewLine} {StringUtil.ConvertToJson(WorkerUtilities.ScrubPiiData(jobMessage))}");
|
||||||
Task<TaskResult> jobRunnerTask = jobRunner.RunAsync(jobMessage, jobRequestCancellationToken.Token);
|
Task<TaskResult> jobRunnerTask = jobRunner.RunAsync(jobMessage, jobRequestCancellationToken.Token);
|
||||||
|
|
||||||
// Start listening for a cancel message from the channel.
|
// Start listening for a cancel message from the channel.
|
||||||
|
|||||||
92
src/Runner.Worker/WorkerUtilties.cs
Normal file
92
src/Runner.Worker/WorkerUtilties.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Worker
|
||||||
|
{
|
||||||
|
public class WorkerUtilities
|
||||||
|
{
|
||||||
|
public static Pipelines.AgentJobRequestMessage ScrubPiiData(Pipelines.AgentJobRequestMessage message)
|
||||||
|
{
|
||||||
|
ArgUtil.NotNull(message, nameof(message));
|
||||||
|
|
||||||
|
var scrubbedVariables = new Dictionary<string, VariableValue>();
|
||||||
|
|
||||||
|
// Scrub the known PII variables
|
||||||
|
foreach (var variable in message.Variables)
|
||||||
|
{
|
||||||
|
if (Variables.PiiVariables.Contains(variable.Key) ||
|
||||||
|
(variable.Key.StartsWith(Variables.PiiArtifactVariablePrefix, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& Variables.PiiArtifactVariableSuffixes.Any(varSuffix => variable.Key.EndsWith(varSuffix, StringComparison.OrdinalIgnoreCase))))
|
||||||
|
{
|
||||||
|
scrubbedVariables[variable.Key] = "[PII]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scrubbedVariables[variable.Key] = variable.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var scrubbedRepositories = new List<Pipelines.RepositoryResource>();
|
||||||
|
|
||||||
|
// Scrub the repository resources
|
||||||
|
foreach (var repository in message.Resources.Repositories)
|
||||||
|
{
|
||||||
|
Pipelines.RepositoryResource scrubbedRepository = repository.Clone();
|
||||||
|
|
||||||
|
var versionInfo = repository.Properties.Get<Pipelines.VersionInfo>(Pipelines.RepositoryPropertyNames.VersionInfo);
|
||||||
|
|
||||||
|
if (versionInfo != null)
|
||||||
|
{
|
||||||
|
scrubbedRepository.Properties.Set(
|
||||||
|
Pipelines.RepositoryPropertyNames.VersionInfo,
|
||||||
|
new Pipelines.VersionInfo()
|
||||||
|
{
|
||||||
|
Author = "[PII]",
|
||||||
|
Message = versionInfo.Message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scrubbedRepositories.Add(scrubbedRepository);
|
||||||
|
}
|
||||||
|
|
||||||
|
var scrubbedJobResources = new Pipelines.JobResources();
|
||||||
|
|
||||||
|
scrubbedJobResources.Containers.AddRange(message.Resources.Containers);
|
||||||
|
scrubbedJobResources.Endpoints.AddRange(message.Resources.Endpoints);
|
||||||
|
scrubbedJobResources.Repositories.AddRange(scrubbedRepositories);
|
||||||
|
scrubbedJobResources.SecureFiles.AddRange(message.Resources.SecureFiles);
|
||||||
|
|
||||||
|
var contextData = new DictionaryContextData();
|
||||||
|
if (message.ContextData?.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var pair in message.ContextData)
|
||||||
|
{
|
||||||
|
contextData[pair.Key] = pair.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstitute a new agent job request message from the scrubbed parts
|
||||||
|
return new Pipelines.AgentJobRequestMessage(
|
||||||
|
plan: message.Plan,
|
||||||
|
timeline: message.Timeline,
|
||||||
|
jobId: message.JobId,
|
||||||
|
jobDisplayName: message.JobDisplayName,
|
||||||
|
jobName: message.JobName,
|
||||||
|
jobContainer: message.JobContainer,
|
||||||
|
jobServiceContainers: message.JobServiceContainers,
|
||||||
|
environmentVariables: message.EnvironmentVariables,
|
||||||
|
variables: scrubbedVariables,
|
||||||
|
maskHints: message.MaskHints,
|
||||||
|
jobResources: scrubbedJobResources,
|
||||||
|
contextData: contextData,
|
||||||
|
workspaceOptions: message.Workspace,
|
||||||
|
steps: message.Steps,
|
||||||
|
scopes: message.Scopes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Sdk/BuildWebApi/Api/AgentTargetExecutionType.cs
Normal file
12
src/Sdk/BuildWebApi/Api/AgentTargetExecutionType.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi {
|
||||||
|
|
||||||
|
[GenerateAllConstants]
|
||||||
|
public static class AgentTargetExecutionType {
|
||||||
|
public const Int32 Normal = 0;
|
||||||
|
public const Int32 VariableMultipliers = 1;
|
||||||
|
public const Int32 MultipleAgents = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,76 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
namespace GitHub.Build.WebApi
|
namespace GitHub.Build.WebApi
|
||||||
{
|
{
|
||||||
|
[Obsolete("Use ArtifactResourceTypes instead.")]
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public static class WellKnownArtifactResourceTypes
|
||||||
|
{
|
||||||
|
public const String FilePath = ArtifactResourceTypes.FilePath;
|
||||||
|
public const String SymbolStore = ArtifactResourceTypes.SymbolStore;
|
||||||
|
public const String VersionControl = ArtifactResourceTypes.VersionControl;
|
||||||
|
public const String Container = ArtifactResourceTypes.Container;
|
||||||
|
public const String GitRef = ArtifactResourceTypes.GitRef;
|
||||||
|
public const String TfvcLabel = ArtifactResourceTypes.TfvcLabel;
|
||||||
|
public const String SymbolRequest = ArtifactResourceTypes.SymbolRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GenerateAllConstants]
|
||||||
public static class ArtifactResourceTypes
|
public static class ArtifactResourceTypes
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UNC or local folder path
|
||||||
|
/// E.g. \\vscsstor\CIDrops\CloudU.Gated\140317.115955 or file://vscsstor/CIDrops/CloudU.Gated/140317.115955
|
||||||
|
/// </summary>
|
||||||
|
public const String FilePath = "FilePath";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Symbol store UNC path
|
||||||
|
/// E.g. \\symbolstore
|
||||||
|
/// </summary>
|
||||||
|
public const String SymbolStore = "SymbolStore";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TF VC server folder path
|
||||||
|
/// E.g. $/Dev1/Drops/CloudU.Gated/140317.115955
|
||||||
|
/// </summary>
|
||||||
|
public const String VersionControl = "VersionControl";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Build container reference
|
/// Build container reference
|
||||||
/// E.g. #/2121/drop
|
/// E.g. #/2121/drop
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const String Container = "Container";
|
public const String Container = "Container";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Git ref
|
||||||
|
/// E.g. refs/tags/MyCIDefinition.Buildable
|
||||||
|
/// </summary>
|
||||||
|
public const String GitRef = "GitRef";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TFVC label
|
||||||
|
/// </summary>
|
||||||
|
public const String TfvcLabel = "TfvcLabel";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Symbol store URL
|
||||||
|
/// E.g. https://mseng.artifacts.visualstudio.com/...
|
||||||
|
/// </summary>
|
||||||
|
public const String SymbolRequest = "SymbolRequest";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dedup Drop (old name fo PipelineArtifact)
|
||||||
|
/// E.g. drop1
|
||||||
|
/// </summary>
|
||||||
|
public const String Drop = "Drop";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dedup'ed pipeline artifact
|
||||||
|
/// E.g. artifact1
|
||||||
|
/// </summary>
|
||||||
|
public const String PipelineArtifact = "PipelineArtifact";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/Sdk/BuildWebApi/Api/BuildDefinitionExtensions.cs
Normal file
17
src/Sdk/BuildWebApi/Api/BuildDefinitionExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
public static class BuildDefinitionExtensions
|
||||||
|
{
|
||||||
|
public static T GetProcess<T>(
|
||||||
|
this BuildDefinition definition) where T : BuildProcess
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(definition, nameof(definition));
|
||||||
|
ArgumentUtility.CheckForNull(definition.Process, nameof(definition.Process));
|
||||||
|
ArgumentUtility.CheckType<T>(definition.Process, nameof(definition.Process), nameof(T));
|
||||||
|
|
||||||
|
return definition.Process as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/Sdk/BuildWebApi/Api/BuildDefinitionHelpers.cs
Normal file
44
src/Sdk/BuildWebApi/Api/BuildDefinitionHelpers.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using GitHub.Build.WebApi.Internals;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
public static class BuildDefinitionHelpers
|
||||||
|
{
|
||||||
|
public static BuildDefinition Deserialize(
|
||||||
|
String definitionString)
|
||||||
|
{
|
||||||
|
var definition = JsonUtility.FromString<BuildDefinition>(definitionString);
|
||||||
|
if (definition?.Process == null)
|
||||||
|
{
|
||||||
|
var legacyDefinition = JsonConvert.DeserializeObject<BuildDefinition3_2>(definitionString);
|
||||||
|
definition = legacyDefinition.ToBuildDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BuildDefinitionTemplate GetTemplateFromStream(
|
||||||
|
Stream stream)
|
||||||
|
{
|
||||||
|
String templateString;
|
||||||
|
using (var reader = new StreamReader(stream, Encoding.UTF8, false, 1024, true))
|
||||||
|
{
|
||||||
|
templateString = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
var template = JsonConvert.DeserializeObject<BuildDefinitionTemplate>(templateString);
|
||||||
|
if (template?.Template?.Process == null)
|
||||||
|
{
|
||||||
|
var legacyTemplate = JsonConvert.DeserializeObject<BuildDefinitionTemplate3_2>(templateString);
|
||||||
|
template = legacyTemplate.ToBuildDefinitionTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
2463
src/Sdk/BuildWebApi/Api/BuildHttpClientCompatBase.cs
Normal file
2463
src/Sdk/BuildWebApi/Api/BuildHttpClientCompatBase.cs
Normal file
File diff suppressed because it is too large
Load Diff
21
src/Sdk/BuildWebApi/Api/BuildIssueKeys.cs
Normal file
21
src/Sdk/BuildWebApi/Api/BuildIssueKeys.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
public static class BuildIssueKeys
|
||||||
|
{
|
||||||
|
public const String CodeCategory = "code";
|
||||||
|
public const String SourcePath = "sourcePath";
|
||||||
|
public const String LineNumber = "lineNumber";
|
||||||
|
public const String Message = "message";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use BuildIssueKeys instead.")]
|
||||||
|
public static class WellKnownBuildKeys
|
||||||
|
{
|
||||||
|
public const String BuildIssueCodeCategory = BuildIssueKeys.CodeCategory;
|
||||||
|
public const String BuildIssueFileKey = BuildIssueKeys.SourcePath;
|
||||||
|
public const String BuildIssueLineNumberKey = BuildIssueKeys.LineNumber;
|
||||||
|
public const String BuildIssueMessageKey = BuildIssueKeys.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Sdk/BuildWebApi/Api/BuildOrchestrationType.cs
Normal file
12
src/Sdk/BuildWebApi/Api/BuildOrchestrationType.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
[GenerateAllConstants]
|
||||||
|
public static class BuildOrchestrationType
|
||||||
|
{
|
||||||
|
public const Int32 Build = 1;
|
||||||
|
public const Int32 Cleanup = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/Sdk/BuildWebApi/Api/BuildPermissions.cs
Normal file
40
src/Sdk/BuildWebApi/Api/BuildPermissions.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
public static class BuildPermissions
|
||||||
|
{
|
||||||
|
public static readonly Int32 ViewBuilds = 1;
|
||||||
|
public static readonly Int32 EditBuildQuality = 2;
|
||||||
|
public static readonly Int32 RetainIndefinitely = 4;
|
||||||
|
public static readonly Int32 DeleteBuilds = 8;
|
||||||
|
public static readonly Int32 ManageBuildQualities = 16;
|
||||||
|
public static readonly Int32 DestroyBuilds = 32;
|
||||||
|
public static readonly Int32 UpdateBuildInformation = 64;
|
||||||
|
public static readonly Int32 QueueBuilds = 128;
|
||||||
|
public static readonly Int32 ManageBuildQueue = 256;
|
||||||
|
public static readonly Int32 StopBuilds = 512;
|
||||||
|
public static readonly Int32 ViewBuildDefinition = 1024;
|
||||||
|
public static readonly Int32 EditBuildDefinition = 2048;
|
||||||
|
public static readonly Int32 DeleteBuildDefinition = 4096;
|
||||||
|
public static readonly Int32 OverrideBuildCheckInValidation = 8192;
|
||||||
|
public static readonly Int32 AdministerBuildPermissions = 16384;
|
||||||
|
|
||||||
|
public static readonly Int32 AllPermissions =
|
||||||
|
ViewBuilds |
|
||||||
|
EditBuildQuality |
|
||||||
|
RetainIndefinitely |
|
||||||
|
DeleteBuilds |
|
||||||
|
ManageBuildQualities |
|
||||||
|
DestroyBuilds |
|
||||||
|
UpdateBuildInformation |
|
||||||
|
QueueBuilds |
|
||||||
|
ManageBuildQueue |
|
||||||
|
StopBuilds |
|
||||||
|
ViewBuildDefinition |
|
||||||
|
EditBuildDefinition |
|
||||||
|
DeleteBuildDefinition |
|
||||||
|
OverrideBuildCheckInValidation |
|
||||||
|
AdministerBuildPermissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,165 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
namespace GitHub.Build.WebApi
|
namespace GitHub.Build.WebApi
|
||||||
{
|
{
|
||||||
|
[GenerateAllConstants(alternateName: "Build2ResourceIds")]
|
||||||
public static class BuildResourceIds
|
public static class BuildResourceIds
|
||||||
{
|
{
|
||||||
|
// keep these sorted
|
||||||
|
|
||||||
public const String AreaId = "5D6898BB-45EC-463F-95F9-54D49C71752E";
|
public const String AreaId = "5D6898BB-45EC-463F-95F9-54D49C71752E";
|
||||||
public const String AreaName = "build";
|
public const String AreaName = "build";
|
||||||
|
|
||||||
|
public static readonly Guid Artifacts = new Guid("{1DB06C96-014E-44E1-AC91-90B2D4B3E984}");
|
||||||
|
public const String ArtifactsResource = "artifacts";
|
||||||
|
|
||||||
|
public const String AttachmentLocation = "AF5122D3-3438-485E-A25A-2DBBFDE84EE6";
|
||||||
|
public static readonly Guid Attachment = new Guid(AttachmentLocation);
|
||||||
|
|
||||||
|
public const String AttachmentsLocation = "F2192269-89FA-4F94-BAF6-8FB128C55159";
|
||||||
|
public static readonly Guid Attachments = new Guid(AttachmentsLocation);
|
||||||
|
public const String AttachmentsResource = "attachments";
|
||||||
|
|
||||||
|
public static readonly Guid BuildBadge = new Guid("21b3b9ce-fad5-4567-9ad0-80679794e003");
|
||||||
|
public const String BuildBadgeResource = "buildbadge";
|
||||||
|
|
||||||
|
public const String BuildChangesLocationId = "54572C7B-BBD3-45D4-80DC-28BE08941620";
|
||||||
|
public static readonly Guid BuildChangesBetweenBuilds = new Guid("{F10F0EA5-18A1-43EC-A8FB-2042C7BE9B43}");
|
||||||
|
public static readonly Guid BuildChanges = new Guid(BuildChangesLocationId);
|
||||||
|
public const String BuildChangesResource = "changes";
|
||||||
|
|
||||||
|
public static readonly Guid BuildDefinitionBadge = new Guid("de6a4df8-22cd-44ee-af2d-39f6aa7a4261");
|
||||||
|
public const String BuildDefinitionBadgeResource = "badge";
|
||||||
|
|
||||||
|
public static readonly Guid BuildDeployments = new Guid("{F275BE9A-556A-4EE9-B72F-F9C8370CCAEE}");
|
||||||
|
public const String BuildDeploymentsResource = "deployments";
|
||||||
|
|
||||||
|
public static readonly Guid BuildLogs = new Guid("{35A80DAF-7F30-45FC-86E8-6B813D9C90DF}");
|
||||||
|
public const String BuildLogsResource = "logs";
|
||||||
|
|
||||||
|
public const String BuildPropertiesLocationString = "0A6312E9-0627-49B7-8083-7D74A64849C9";
|
||||||
|
public static readonly Guid BuildProperties = new Guid(BuildPropertiesLocationString);
|
||||||
|
|
||||||
|
public static readonly Guid BuildReport = new Guid("{45BCAA88-67E1-4042-A035-56D3B4A7D44C}");
|
||||||
|
public const String BuildReportResource = "report";
|
||||||
|
|
||||||
|
public static readonly Guid Builds = new Guid("{0CD358E1-9217-4D94-8269-1C1EE6F93DCF}");
|
||||||
|
public const String BuildsResource = "builds";
|
||||||
|
|
||||||
|
public const String BuildTagsLocationIdString = "6E6114B2-8161-44C8-8F6C-C5505782427F";
|
||||||
|
public static readonly Guid BuildTags = new Guid(BuildTagsLocationIdString);
|
||||||
|
public const String BuildTagsResource = "tags";
|
||||||
|
|
||||||
|
public const String BuildWorkItemsLocationId = "5A21F5D2-5642-47E4-A0BD-1356E6731BEE";
|
||||||
|
public static readonly Guid BuildWorkItemsBetweenBuilds = new Guid("{52BA8915-5518-42E3-A4BB-B0182D159E2D}");
|
||||||
|
public static readonly Guid BuildWorkItems = new Guid(BuildWorkItemsLocationId);
|
||||||
|
public const String BuildWorkItemsResource = "workitems";
|
||||||
|
|
||||||
|
public const String ControllersLocationString = "{FCAC1932-2EE1-437F-9B6F-7F696BE858F6}";
|
||||||
|
public static readonly Guid Controllers = new Guid(ControllersLocationString);
|
||||||
|
public const String ControllersResource = "Controllers";
|
||||||
|
|
||||||
|
public const String DefinitionMetricsLocationString = "D973B939-0CE0-4FEC-91D8-DA3940FA1827";
|
||||||
|
public static readonly Guid DefinitionMetrics = new Guid(DefinitionMetricsLocationString);
|
||||||
|
public const String DefinitionMetricsResource = "metrics";
|
||||||
|
|
||||||
|
public const String DefinitionPropertiesLocationString = "D9826AD7-2A68-46A9-A6E9-677698777895";
|
||||||
|
public static readonly Guid DefinitionProperties = new Guid(DefinitionPropertiesLocationString);
|
||||||
|
|
||||||
|
public static readonly Guid DefinitionResources = new Guid("ea623316-1967-45eb-89ab-e9e6110cf2d6");
|
||||||
|
public const String DefinitionResourcesResource = "resources";
|
||||||
|
|
||||||
|
public static readonly Guid DefinitionRevisions = new Guid("{7C116775-52E5-453E-8C5D-914D9762D8C4}");
|
||||||
|
public const String DefinitionRevisionsResource = "revisions";
|
||||||
|
|
||||||
|
public static readonly Guid Definitions = new Guid("{DBEAF647-6167-421A-BDA9-C9327B25E2E6}");
|
||||||
|
public const String DefinitionsResource = "definitions";
|
||||||
|
|
||||||
|
public const String DefinitionTagsLocationIdString = "CB894432-134A-4D31-A839-83BECEAACE4B";
|
||||||
|
public static readonly Guid DefinitionTags = new Guid(DefinitionTagsLocationIdString);
|
||||||
|
|
||||||
|
public static readonly Guid Folders = new Guid("{A906531B-D2DA-4F55-BDA7-F3E676CC50D9}");
|
||||||
|
public const String FoldersResource = "folders";
|
||||||
|
|
||||||
|
// information nodes for XAML builds
|
||||||
|
public static readonly Guid InformationNodes = new Guid("9F094D42-B41C-4920-95AA-597581A79821");
|
||||||
|
|
||||||
|
public static readonly Guid InputValuesQuery = new Guid("{2182A7F0-B363-4B2D-B89E-ED0A0B721E95}");
|
||||||
|
public const String InputValuesQueryResource = "InputValuesQuery";
|
||||||
|
|
||||||
|
public static readonly Guid LatestBuildLocationId = new Guid("54481611-01F4-47F3-998F-160DA0F0C229");
|
||||||
|
public const String LatestBuildResource = "latest";
|
||||||
|
|
||||||
|
public static readonly Guid Metrics = new Guid("104AD424-B758-4699-97B7-7E7DA427F9C2");
|
||||||
|
public const String MetricsResource = "Metrics";
|
||||||
|
|
||||||
|
public static readonly Guid Options = new Guid("{591CB5A4-2D46-4F3A-A697-5CD42B6BD332}");
|
||||||
|
public const String OptionsResource = "options";
|
||||||
|
|
||||||
|
public const String ProjectMetricsLocationString = "7433FAE7-A6BC-41DC-A6E2-EEF9005CE41A";
|
||||||
|
public static readonly Guid ProjectMetrics = new Guid(ProjectMetricsLocationString);
|
||||||
|
|
||||||
|
public static readonly Guid ProjectAuthorizedResources = new Guid("398c85bc-81aa-4822-947c-a194a05f0fef");
|
||||||
|
public const String ProjectAuthorizedResourcesResource = "authorizedresources";
|
||||||
|
|
||||||
|
public const String PropertiesResource = "properties";
|
||||||
|
|
||||||
|
public static readonly Guid Queues = new Guid("{09F2A4B8-08C9-4991-85C3-D698937568BE}");
|
||||||
|
public const String QueuesResource = "queues";
|
||||||
|
|
||||||
|
public static readonly Guid Settings = new Guid("{AA8C1C9C-EF8B-474A-B8C4-785C7B191D0D}");
|
||||||
|
public const String SettingsResource = "settings";
|
||||||
|
|
||||||
|
public const String SourceProviderBranchesResource = "branches";
|
||||||
|
public const String SourceProviderBranchesLocationIdString = "E05D4403-9B81-4244-8763-20FDE28D1976";
|
||||||
|
public static readonly Guid SourceProviderBranchesLocationId = new Guid(SourceProviderBranchesLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderFileContentsResource = "fileContents";
|
||||||
|
public const String SourceProviderFileContentsLocationIdString = "29D12225-B1D9-425F-B668-6C594A981313";
|
||||||
|
public static readonly Guid SourceProviderFileContentsLocationId = new Guid(SourceProviderFileContentsLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderPathContentsResource = "pathContents";
|
||||||
|
public const String SourceProviderPathContentsLocationIdString = "7944D6FB-DF01-4709-920A-7A189AA34037";
|
||||||
|
public static readonly Guid SourceProviderPathContentsLocationId = new Guid(SourceProviderPathContentsLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderPullRequestsResource = "pullRequests";
|
||||||
|
public const String SourceProviderPullRequestsLocationIdString = "D8763EC7-9FF0-4FB4-B2B2-9D757906FF14";
|
||||||
|
public static readonly Guid SourceProviderPullRequestsLocationId = new Guid(SourceProviderPullRequestsLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderRepositoriesResource = "repositories";
|
||||||
|
public const String SourceProviderRepositoriesLocationIdString = "D44D1680-F978-4834-9B93-8C6E132329C9";
|
||||||
|
public static readonly Guid SourceProviderRepositoriesLocationId = new Guid(SourceProviderRepositoriesLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderRestoreWebhooksLocationIdString = "793BCEB8-9736-4030-BD2F-FB3CE6D6B478";
|
||||||
|
public static readonly Guid SourceProviderRestoreWebhooksLocationId = new Guid(SourceProviderRestoreWebhooksLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProvidersResource = "sourceProviders";
|
||||||
|
public const String SourceProvidersLocationIdString = "3CE81729-954F-423D-A581-9FEA01D25186";
|
||||||
|
public static readonly Guid SourceProviders = new Guid(SourceProvidersLocationIdString);
|
||||||
|
|
||||||
|
public const String SourceProviderWebhooksResource = "webhooks";
|
||||||
|
public const String SourceProviderWebhooksLocationIdString = "8F20FF82-9498-4812-9F6E-9C01BDC50E99";
|
||||||
|
public static readonly Guid SourceProviderWebhooksLocationId = new Guid(SourceProviderWebhooksLocationIdString);
|
||||||
|
|
||||||
|
public const String SourcesLocationId = "56EFDCDC-CF90-4028-9D2F-D41000682202";
|
||||||
|
public static readonly Guid Sources = new Guid(SourcesLocationId);
|
||||||
|
public const String SourcesResource = "sources";
|
||||||
|
|
||||||
|
public const String StatusBadgeLocationIdString = "07ACFDCE-4757-4439-B422-DDD13A2FCC10";
|
||||||
|
public static readonly Guid StatusBadgeLocationId = new Guid(StatusBadgeLocationIdString);
|
||||||
|
public const String StatusBadgeResource = "status";
|
||||||
|
|
||||||
|
public const String TagsLocationIdString = "D84AC5C6-EDC7-43D5-ADC9-1B34BE5DEA09";
|
||||||
|
public static readonly Guid Tags = new Guid(TagsLocationIdString);
|
||||||
|
|
||||||
|
public static readonly Guid Templates = new Guid("{E884571E-7F92-4D6A-9274-3F5649900835}");
|
||||||
|
public const String TemplatesResource = "templates";
|
||||||
|
|
||||||
|
public static readonly Guid Timelines = new Guid("8baac422-4c6e-4de5-8532-db96d92acffa");
|
||||||
|
public const String TimelinesResource = "Timeline";
|
||||||
|
|
||||||
|
public static readonly Guid Usage = new Guid("3813d06c-9e36-4ea1-aac3-61a485d60e3d");
|
||||||
|
public const String UsageResource = "ResourceUsage";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/Sdk/BuildWebApi/Api/BuildTemplateCategories.cs
Normal file
29
src/Sdk/BuildWebApi/Api/BuildTemplateCategories.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
[GenerateAllConstants]
|
||||||
|
public static class BuildTemplateCategories
|
||||||
|
{
|
||||||
|
public static readonly String All = "All";
|
||||||
|
public static readonly String Build = "Build";
|
||||||
|
public static readonly String Utility = "Utility";
|
||||||
|
public static readonly String Test = "Test";
|
||||||
|
public static readonly String Package = "Package";
|
||||||
|
public static readonly String Deploy = "Deploy";
|
||||||
|
public static readonly String Tool = "Tool";
|
||||||
|
public static readonly String Custom = "Custom";
|
||||||
|
|
||||||
|
public static readonly String[] AllCategories = new String[] {
|
||||||
|
All,
|
||||||
|
Build,
|
||||||
|
Utility,
|
||||||
|
Test,
|
||||||
|
Package,
|
||||||
|
Deploy,
|
||||||
|
Tool,
|
||||||
|
Custom
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,87 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
namespace GitHub.Build.WebApi
|
namespace GitHub.Build.WebApi
|
||||||
{
|
{
|
||||||
|
/* IMPORTANT NOTE: if you're adding a new build variable that's designed to hold PII data
|
||||||
|
(e.g. names, addresses, phone numbers, IP addresses, emails), please add a corresponding reference to `PiiVariables` at
|
||||||
|
https://github.com/Microsoft/azure-pipelines-agent/blob/master/src/Agent.Worker/Variables.cs
|
||||||
|
This is so the agent can scrub the variable value from the diagnostics log. */
|
||||||
|
[GenerateAllConstants]
|
||||||
public static class BuildVariables
|
public static class BuildVariables
|
||||||
{
|
{
|
||||||
|
public const String CollectionId = "system.collectionId";
|
||||||
|
public const String DefinitionId = "system.definitionId";
|
||||||
|
public const String HostType = "system.hosttype";
|
||||||
|
public const String IsFork = "system.pullRequest.isFork";
|
||||||
|
public const String ForkSecretsRemoved= "system.pullRequest.forkSecretsRemoved";
|
||||||
|
public const String PullRequestId = "system.pullRequest.pullRequestId";
|
||||||
|
public const String PullRequestNumber = "system.pullRequest.pullRequestNumber";
|
||||||
|
public const String PullRequestIterationId = "system.pullRequest.pullRequestIteration";
|
||||||
|
public const String PullRequestSourceBranch = "system.pullRequest.sourceBranch";
|
||||||
|
public const String PullRequestTargetBranch = "system.pullRequest.targetBranch";
|
||||||
|
public const String PullRequestSourceRepositoryUri = "system.pullRequest.sourceRepositoryUri";
|
||||||
|
public const String PullRequestSourceCommitId = "system.pullRequest.sourceCommitId";
|
||||||
|
public const String PullRequestMergedAt = "system.pullRequest.mergedAt";
|
||||||
|
public const String System = "system";
|
||||||
|
public const String TeamProject = "system.teamProject";
|
||||||
public const String TeamProjectId = "system.teamProjectId";
|
public const String TeamProjectId = "system.teamProjectId";
|
||||||
|
|
||||||
public const String BuildId = "build.buildId";
|
public const String BuildId = "build.buildId";
|
||||||
public const String BuildNumber = "build.buildNumber";
|
public const String BuildNumber = "build.buildNumber";
|
||||||
|
public const String BuildUri = "build.buildUri";
|
||||||
public const String ContainerId = "build.containerId";
|
public const String ContainerId = "build.containerId";
|
||||||
|
public const String DefinitionName = "build.definitionName";
|
||||||
|
public const String DefinitionVersion = "build.definitionVersion";
|
||||||
|
public const String JobAuthorizeAs = "Job.AuthorizeAs";
|
||||||
|
public const String JobAuthorizeAsId = "Job.AuthorizeAsId";
|
||||||
|
public const String QueuedBy = "build.queuedBy";
|
||||||
|
public const String QueuedById = "build.queuedById";
|
||||||
|
public const String Reason = "build.reason";
|
||||||
|
public const String RepoUri = "build.repository.uri";
|
||||||
|
public const String RequestedFor = "build.requestedFor";
|
||||||
|
public const String RequestedForEmail = "build.requestedForEmail";
|
||||||
|
public const String RequestedForId = "build.requestedForId";
|
||||||
|
public const String SourceBranch = "build.sourceBranch";
|
||||||
|
public const String SourceBranchName = "build.sourceBranchName";
|
||||||
|
public const String SourceTfvcShelveset = "build.sourceTfvcShelveset";
|
||||||
|
public const String SourceVersion = "build.sourceVersion";
|
||||||
|
public const String SourceVersionAuthor = "build.sourceVersionAuthor";
|
||||||
|
public const String SourceVersionMessage = "build.sourceVersionMessage";
|
||||||
|
public const String SyncSources = "build.syncSources";
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use BuildVariables instead.")]
|
||||||
|
public static class WellKnownBuildVariables
|
||||||
|
{
|
||||||
|
public const String System = BuildVariables.System;
|
||||||
|
public const String CollectionId = BuildVariables.CollectionId;
|
||||||
|
public const String TeamProject = BuildVariables.TeamProject;
|
||||||
|
public const String TeamProjectId = BuildVariables.TeamProjectId;
|
||||||
|
public const String DefinitionId = BuildVariables.DefinitionId;
|
||||||
|
public const String HostType = BuildVariables.HostType;
|
||||||
|
public const String IsFork = BuildVariables.IsFork;
|
||||||
|
public const String DefinitionName = BuildVariables.DefinitionName;
|
||||||
|
public const String DefinitionVersion = BuildVariables.DefinitionVersion;
|
||||||
|
public const String QueuedBy = BuildVariables.QueuedBy;
|
||||||
|
public const String QueuedById = BuildVariables.QueuedById;
|
||||||
|
public const String Reason = BuildVariables.Reason;
|
||||||
|
public const String RequestedFor = BuildVariables.RequestedFor;
|
||||||
|
public const String RequestedForId = BuildVariables.RequestedForId;
|
||||||
|
public const String RequestedForEmail = BuildVariables.RequestedForEmail;
|
||||||
|
public const String SourceBranch = BuildVariables.SourceBranch;
|
||||||
|
public const String SourceBranchName = BuildVariables.SourceBranchName;
|
||||||
|
public const String SourceVersion = BuildVariables.SourceVersion;
|
||||||
|
public const String SourceVersionAuthor = BuildVariables.SourceVersionAuthor;
|
||||||
|
public const String SourceVersionMessage = BuildVariables.SourceVersionMessage;
|
||||||
|
public const String SourceTfvcShelveset = BuildVariables.SourceTfvcShelveset;
|
||||||
|
public const String BuildId = BuildVariables.BuildId;
|
||||||
|
public const String BuildUri = BuildVariables.BuildUri;
|
||||||
|
public const String BuildNumber = BuildVariables.BuildNumber;
|
||||||
|
public const String ContainerId = BuildVariables.ContainerId;
|
||||||
|
public const String SyncSources = BuildVariables.SyncSources;
|
||||||
|
public const String JobAuthorizeAs = BuildVariables.JobAuthorizeAs;
|
||||||
|
public const String JobAuthorizeAsId = BuildVariables.JobAuthorizeAsId;
|
||||||
|
public const String RepoUri = BuildVariables.RepoUri;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
134
src/Sdk/BuildWebApi/Api/Contracts/AgentPoolQueue.cs
Normal file
134
src/Sdk/BuildWebApi/Api/Contracts/AgentPoolQueue.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a queue for running builds.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
#pragma warning disable 618
|
||||||
|
public class AgentPoolQueue : ShallowReference, ISecuredObject
|
||||||
|
#pragma warning restore 618
|
||||||
|
{
|
||||||
|
public AgentPoolQueue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AgentPoolQueue(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
{
|
||||||
|
this.m_securedObject = securedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public new Int32 Id
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Id;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Id = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public new String Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Name;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Name = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full http link to the resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public new String Url
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Url;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Url = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The pool used by this queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public TaskAgentPoolReference Pool
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The links to other objects related to this object.
|
||||||
|
/// </summary>
|
||||||
|
public ReferenceLinks Links
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_links == null)
|
||||||
|
{
|
||||||
|
m_links = new ReferenceLinks();
|
||||||
|
}
|
||||||
|
return m_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "_links", EmitDefaultValue = false)]
|
||||||
|
private ReferenceLinks m_links;
|
||||||
|
|
||||||
|
#region ISecuredObject implementation
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
Guid ISecuredObject.NamespaceId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject));
|
||||||
|
return m_securedObject.NamespaceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
Int32 ISecuredObject.RequiredPermissions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject));
|
||||||
|
return m_securedObject.RequiredPermissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String ISecuredObject.GetToken()
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject));
|
||||||
|
return m_securedObject.GetToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ISecuredObject m_securedObject;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
102
src/Sdk/BuildWebApi/Api/Contracts/AgentPoolQueueTarget.cs
Normal file
102
src/Sdk/BuildWebApi/Api/Contracts/AgentPoolQueueTarget.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes how a phase should run against an agent queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class AgentPoolQueueTarget : PhaseTarget
|
||||||
|
{
|
||||||
|
public AgentPoolQueueTarget()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AgentPoolQueueTarget(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(PhaseTargetType.Agent, securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AgentPoolQueue Queue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Agent specification of the target.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AgentSpecification AgentSpecification
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of demands required for the queue.
|
||||||
|
/// </summary>
|
||||||
|
public List<Demand> Demands
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_demands == null)
|
||||||
|
{
|
||||||
|
m_demands = new List<Demand>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_demands;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_demands = new List<Demand>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The execution options.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public AgentTargetExecutionOptions ExecutionOptions
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables scripts and other processes launched while executing phase to access the OAuth token
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public Boolean AllowScriptsAuthAccessOption
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnDeserialized]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_serializedDemands, ref m_demands, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerializing]
|
||||||
|
private void OnSerializing(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_demands, ref m_serializedDemands);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Demands", EmitDefaultValue = false)]
|
||||||
|
private List<Demand> m_serializedDemands;
|
||||||
|
|
||||||
|
private List<Demand> m_demands;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Sdk/BuildWebApi/Api/Contracts/AgentSpecification.cs
Normal file
28
src/Sdk/BuildWebApi/Api/Contracts/AgentSpecification.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specification of the agent defined by the pool provider.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class AgentSpecification: BaseSecuredObject
|
||||||
|
{
|
||||||
|
public AgentSpecification()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgentSpecification(ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Agent specification unique identifier.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Identifier { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Additional options for running phases against an agent queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
[KnownType(typeof(MultipleAgentExecutionOptions))]
|
||||||
|
[KnownType(typeof(VariableMultipliersAgentExecutionOptions))]
|
||||||
|
[JsonConverter(typeof(AgentTargetExecutionOptionsJsonConverter))]
|
||||||
|
public class AgentTargetExecutionOptions : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public AgentTargetExecutionOptions()
|
||||||
|
: this(AgentTargetExecutionType.Normal)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AgentTargetExecutionOptions(Int32 type)
|
||||||
|
: this(type, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AgentTargetExecutionOptions(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: this(AgentTargetExecutionType.Normal, securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AgentTargetExecutionOptions(
|
||||||
|
Int32 type,
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
this.Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of execution options.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Int32 Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
internal sealed class AgentTargetExecutionOptionsJsonConverter : TypePropertyJsonConverter<AgentTargetExecutionOptions>
|
||||||
|
{
|
||||||
|
protected override AgentTargetExecutionOptions GetInstance(Type objectType)
|
||||||
|
{
|
||||||
|
if (objectType == typeof(AgentTargetExecutionType))
|
||||||
|
{
|
||||||
|
return new AgentTargetExecutionOptions();
|
||||||
|
}
|
||||||
|
else if (objectType == typeof(VariableMultipliersAgentExecutionOptions))
|
||||||
|
{
|
||||||
|
return new VariableMultipliersAgentExecutionOptions();
|
||||||
|
}
|
||||||
|
else if (objectType == typeof(MultipleAgentExecutionOptions))
|
||||||
|
{
|
||||||
|
return new MultipleAgentExecutionOptions();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return base.GetInstance(objectType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override AgentTargetExecutionOptions GetInstance(Int32 targetType)
|
||||||
|
{
|
||||||
|
switch (targetType)
|
||||||
|
{
|
||||||
|
case AgentTargetExecutionType.Normal:
|
||||||
|
return new AgentTargetExecutionOptions();
|
||||||
|
case AgentTargetExecutionType.VariableMultipliers:
|
||||||
|
return new VariableMultipliersAgentExecutionOptions();
|
||||||
|
case AgentTargetExecutionType.MultipleAgents:
|
||||||
|
return new MultipleAgentExecutionOptions();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,5 +50,46 @@ namespace GitHub.Build.WebApi
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full http link to the resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public String Url
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A link to download the resource.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This might include things like query parameters to download as a zip file.
|
||||||
|
/// </remarks>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public String DownloadUrl
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The links to other objects related to this object.
|
||||||
|
/// </summary>
|
||||||
|
public ReferenceLinks Links
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_links == null)
|
||||||
|
{
|
||||||
|
m_links = new ReferenceLinks();
|
||||||
|
}
|
||||||
|
return m_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "_links", EmitDefaultValue = false)]
|
||||||
|
private ReferenceLinks m_links;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
src/Sdk/BuildWebApi/Api/Contracts/Attachment.cs
Normal file
51
src/Sdk/BuildWebApi/Api/Contracts/Attachment.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an attachment to a build.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class Attachment : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public Attachment()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Attachment(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the attachment.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The links to other objects related to this object.
|
||||||
|
/// </summary>
|
||||||
|
public ReferenceLinks Links
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_links == null)
|
||||||
|
{
|
||||||
|
m_links = new ReferenceLinks();
|
||||||
|
}
|
||||||
|
return m_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "_links", EmitDefaultValue = false)]
|
||||||
|
private ReferenceLinks m_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
605
src/Sdk/BuildWebApi/Api/Contracts/Build.cs
Normal file
605
src/Sdk/BuildWebApi/Api/Contracts/Build.cs
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Core.WebApi;
|
||||||
|
//using GitHub.Core.WebApi;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Data representation of a build.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class Build : ISecuredObject
|
||||||
|
{
|
||||||
|
public Build()
|
||||||
|
{
|
||||||
|
Reason = BuildReason.Manual;
|
||||||
|
Priority = QueuePriority.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region BuildReference members
|
||||||
|
// these are also present in BuildReference. ideally this class would inherit from that.
|
||||||
|
// however, moving them to a base class changes the order in which they are serialized to xml
|
||||||
|
// which breaks compat with subscribers (like RM) who may not be on the same milestone
|
||||||
|
// TODO: remove these when we figure out how to version service bus events
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
[Key]
|
||||||
|
public Int32 Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build number/name of the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String BuildNumber
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The status of the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildStatus? Status
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build result.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildResult? Result
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time that the build was queued.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? QueueTime
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time that the build was started.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? StartTime
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time that the build was completed.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? FinishTime
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The links to other objects related to this object.
|
||||||
|
/// </summary>
|
||||||
|
public ReferenceLinks Links
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_links == null)
|
||||||
|
{
|
||||||
|
m_links = new ReferenceLinks();
|
||||||
|
}
|
||||||
|
return m_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "_links", EmitDefaultValue = false)]
|
||||||
|
private ReferenceLinks m_links;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The REST URL of the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Url
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The definition associated with the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DefinitionReference Definition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build number revision.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32? BuildNumberRevision
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The team project.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public TeamProjectReference Project
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The URI of the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Uri Uri
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source branch.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String SourceBranch
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source version.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String SourceVersion
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The queue. This is only set if the definition type is Build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AgentPoolQueue Queue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The agent specification for the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AgentSpecification AgentSpecification
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current position of the build in the queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32? QueuePosition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build's priority.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public QueuePriority Priority
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The reason that the build was created.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildReason Reason
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identity on whose behalf the build was queued.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IdentityRef RequestedFor
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identity that queued the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IdentityRef RequestedBy
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date the build was last changed.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime LastChangedDate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identity representing the process or person that last changed the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IdentityRef LastChangedBy
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date the build was deleted.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? DeletedDate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identity of the process or person that deleted the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IdentityRef DeletedBy
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The description of how the build was deleted.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DeletedReason
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The parameters for the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Parameters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of demands that represents the agent capabilities required by this build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public List<Demand> Demands
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The orchestration plan for the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public TaskOrchestrationPlanReference OrchestrationPlan
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of Orchestration plans associated with the build.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The build may have plans in addition to the main plan. For example, the cleanup job may have an orchestration plan associated with it.
|
||||||
|
/// </remarks>
|
||||||
|
public List<TaskOrchestrationPlanReference> Plans
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_plans == null)
|
||||||
|
{
|
||||||
|
m_plans = new List<TaskOrchestrationPlanReference>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_plans;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_plans = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information about the build logs.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildLogReference Logs
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The repository.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildRepository Repository
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional options for queueing the build.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public QueueOptions QueueOptions
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the build has been deleted.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean Deleted
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of properties which may be used to extend the storage fields available
|
||||||
|
/// for a given build.
|
||||||
|
/// </summary>
|
||||||
|
public PropertiesCollection Properties
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_properties == null)
|
||||||
|
{
|
||||||
|
m_properties = new PropertiesCollection();
|
||||||
|
}
|
||||||
|
return m_properties;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_properties = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of tags associated with the build.
|
||||||
|
/// </summary>
|
||||||
|
public List<String> Tags
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_tags == null)
|
||||||
|
{
|
||||||
|
m_tags = new List<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_tags;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_tags = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of validation errors and warnings.
|
||||||
|
/// </summary>
|
||||||
|
public List<BuildRequestValidationResult> ValidationResults
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_validationResults == null)
|
||||||
|
{
|
||||||
|
m_validationResults = new List<BuildRequestValidationResult>();
|
||||||
|
}
|
||||||
|
return m_validationResults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the build should be skipped by retention policies.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean? KeepForever
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The quality of the xaml build (good, bad, etc.)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is only used for XAML builds.
|
||||||
|
/// </remarks>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public String Quality
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the build is retained by a release.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean? RetainedByRelease
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build that triggered this build via a Build completion trigger.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public Build TriggeredByBuild { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Trigger-specific information about the build.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<String, String> TriggerInfo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_triggerInfo == null)
|
||||||
|
{
|
||||||
|
m_triggerInfo = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_triggerInfo;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
m_triggerInfo = new Dictionary<String, String>(value, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Properties")]
|
||||||
|
private PropertiesCollection m_properties;
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Tags")]
|
||||||
|
private List<String> m_tags;
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "ValidationResults")]
|
||||||
|
private List<BuildRequestValidationResult> m_validationResults;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Orchestration plans associated with the build (build, cleanup)
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Plans")]
|
||||||
|
private List<TaskOrchestrationPlanReference> m_plans;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sourceprovider-specific information about what triggered the build
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Added in 3.2-preview.3</remarks>
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "TriggerInfo")]
|
||||||
|
private Dictionary<String, String> m_triggerInfo;
|
||||||
|
|
||||||
|
#region ISecuredObject implementation
|
||||||
|
|
||||||
|
Guid ISecuredObject.NamespaceId => Security.BuildNamespaceId;
|
||||||
|
|
||||||
|
Int32 ISecuredObject.RequiredPermissions => BuildPermissions.ViewBuilds;
|
||||||
|
|
||||||
|
String ISecuredObject.GetToken()
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(m_nestingToken))
|
||||||
|
{
|
||||||
|
return m_nestingToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((ISecuredObject)this.Definition)?.GetToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetNestingSecurityToken(String tokenValue)
|
||||||
|
{
|
||||||
|
// Spike: investigate imposing restrictions on the amount of information being returned
|
||||||
|
// when a nesting security token is being used.
|
||||||
|
m_nestingToken = tokenValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String m_nestingToken = String.Empty;
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/Sdk/BuildWebApi/Api/Contracts/BuildBadge.cs
Normal file
36
src/Sdk/BuildWebApi/Api/Contracts/BuildBadge.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a build badge.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildBadge
|
||||||
|
{
|
||||||
|
public BuildBadge()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the build represented by this badge.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 BuildId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A link to the SVG resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String ImageUrl
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
365
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinition.cs
Normal file
365
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinition.cs
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.DistributedTask.Common.Contracts;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinition : BuildDefinitionReference
|
||||||
|
{
|
||||||
|
public BuildDefinition()
|
||||||
|
{
|
||||||
|
this.JobAuthorizationScope = BuildAuthorizationScope.ProjectCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build number format.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String BuildNumberFormat
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A save-time comment for the definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Comment
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The description.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Description
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The drop location for the definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DropLocation
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The job authorization scope for builds queued against this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public BuildAuthorizationScope JobAuthorizationScope
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The job execution timeout (in minutes) for builds queued against this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 JobTimeoutInMinutes
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The job cancel timeout (in minutes) for builds cancelled by user for this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 JobCancelTimeoutInMinutes
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether badges are enabled for this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean BadgeEnabled
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of steps for this definition.
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete]
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public List<BuildDefinitionStep> Steps
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The build process.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildProcess Process
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of build options used by this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<BuildOption> Options
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_options == null)
|
||||||
|
{
|
||||||
|
m_options = new List<BuildOption>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_options;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_options = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The repository.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildRepository Repository
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The process parameters for this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public ProcessParameters ProcessParameters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of triggers for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<BuildTrigger> Triggers
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_triggers == null)
|
||||||
|
{
|
||||||
|
m_triggers = new List<BuildTrigger>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_triggers;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_triggers = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The variables used by this definition.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<String, BuildDefinitionVariable> Variables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_variables == null)
|
||||||
|
{
|
||||||
|
m_variables = new Dictionary<String, BuildDefinitionVariable>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_variables;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_variables = new Dictionary<String, BuildDefinitionVariable>(value, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The variable groups used by this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<VariableGroup> VariableGroups
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_variableGroups == null)
|
||||||
|
{
|
||||||
|
m_variableGroups = new List<VariableGroup>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_variableGroups;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_variableGroups = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of demands that represents the capabilities required by all agents for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<Demand> Demands
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_demands == null)
|
||||||
|
{
|
||||||
|
m_demands = new List<Demand>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_demands;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_demands = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of retention policies for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<RetentionPolicy> RetentionRules
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_retentionRules == null)
|
||||||
|
{
|
||||||
|
m_retentionRules = new List<RetentionPolicy>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_retentionRules;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_retentionRules = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of properties which may be used to extend the storage fields available
|
||||||
|
/// for a given definition.
|
||||||
|
/// </summary>
|
||||||
|
public PropertiesCollection Properties
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_properties == null)
|
||||||
|
{
|
||||||
|
m_properties = new PropertiesCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_properties;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_properties = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of tags associated with the build definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<String> Tags
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_tags == null)
|
||||||
|
{
|
||||||
|
m_tags = new List<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_tags;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_tags = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnDeserialized]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_serializedOptions, ref m_options, true);
|
||||||
|
SerializationHelper.Copy(ref m_serializedTriggers, ref m_triggers, true);
|
||||||
|
SerializationHelper.Copy(ref m_serializedVariables, ref m_variables, StringComparer.OrdinalIgnoreCase, true);
|
||||||
|
SerializationHelper.Copy(ref m_serializedVariableGroups, ref m_variableGroups, true);
|
||||||
|
SerializationHelper.Copy(ref m_serializedDemands, ref m_demands, true);
|
||||||
|
SerializationHelper.Copy(ref m_serializedRetentionRules, ref m_retentionRules, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerializing]
|
||||||
|
private void OnSerializing(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_options, ref m_serializedOptions);
|
||||||
|
SerializationHelper.Copy(ref m_triggers, ref m_serializedTriggers);
|
||||||
|
SerializationHelper.Copy(ref m_variables, ref m_serializedVariables, StringComparer.OrdinalIgnoreCase);
|
||||||
|
SerializationHelper.Copy(ref m_variableGroups, ref m_serializedVariableGroups);
|
||||||
|
SerializationHelper.Copy(ref m_demands, ref m_serializedDemands);
|
||||||
|
SerializationHelper.Copy(ref m_retentionRules, ref m_serializedRetentionRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerialized]
|
||||||
|
private void OnSerialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
m_serializedOptions = null;
|
||||||
|
m_serializedTriggers = null;
|
||||||
|
m_serializedVariables = null;
|
||||||
|
m_serializedVariableGroups = null;
|
||||||
|
m_serializedRetentionRules = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Options", EmitDefaultValue = false)]
|
||||||
|
private List<BuildOption> m_serializedOptions;
|
||||||
|
|
||||||
|
[DataMember(Name = "Triggers", EmitDefaultValue = false)]
|
||||||
|
private List<BuildTrigger> m_serializedTriggers;
|
||||||
|
|
||||||
|
[DataMember(Name = "Variables", EmitDefaultValue = false)]
|
||||||
|
private IDictionary<String, BuildDefinitionVariable> m_serializedVariables;
|
||||||
|
|
||||||
|
[DataMember(Name = "VariableGroups", EmitDefaultValue = false)]
|
||||||
|
private List<VariableGroup> m_serializedVariableGroups;
|
||||||
|
|
||||||
|
[DataMember(Name = "Demands", EmitDefaultValue = false)]
|
||||||
|
private List<Demand> m_serializedDemands;
|
||||||
|
|
||||||
|
[DataMember(Name = "RetentionRules", EmitDefaultValue = false)]
|
||||||
|
private List<RetentionPolicy> m_serializedRetentionRules;
|
||||||
|
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Properties")]
|
||||||
|
private PropertiesCollection m_properties;
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Tags")]
|
||||||
|
private List<String> m_tags;
|
||||||
|
|
||||||
|
private List<Demand> m_demands;
|
||||||
|
private List<BuildOption> m_options;
|
||||||
|
private List<BuildTrigger> m_triggers;
|
||||||
|
private List<RetentionPolicy> m_retentionRules;
|
||||||
|
private List<VariableGroup> m_variableGroups;
|
||||||
|
private IDictionary<String, BuildDefinitionVariable> m_variables;
|
||||||
|
}
|
||||||
|
}
|
||||||
162
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionReference.cs
Normal file
162
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionReference.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinitionReference : DefinitionReference
|
||||||
|
{
|
||||||
|
public BuildDefinitionReference()
|
||||||
|
{
|
||||||
|
Type = DefinitionType.Build;
|
||||||
|
QueueStatus = DefinitionQueueStatus.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The quality of the definition document (draft, etc.)
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Quality")]
|
||||||
|
public DefinitionQuality? DefinitionQuality
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The author of the definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IdentityRef AuthoredBy
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the definition that this definition is a draft of, if this is a draft definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "draftOf")]
|
||||||
|
public DefinitionReference ParentDefinition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of drafts associated with this definition, if this is not a draft definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public List<DefinitionReference> Drafts
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_drafts ?? (m_drafts = new List<DefinitionReference>());
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_drafts = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default queue for builds run against this definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AgentPoolQueue Queue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The metrics for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public List<BuildMetric> Metrics
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_metrics ?? (m_metrics = new List<BuildMetric>());
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_metrics = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The latest build for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public Build LatestBuild
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_latestBuild;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_latestBuild = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The latest completed build for this definition.
|
||||||
|
/// </summary>
|
||||||
|
public Build LatestCompletedBuild
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return m_latestCompletedBuild;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_latestCompletedBuild = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The links to other objects related to this object.
|
||||||
|
/// </summary>
|
||||||
|
public ReferenceLinks Links => m_links ?? (m_links = new ReferenceLinks());
|
||||||
|
|
||||||
|
[OnDeserialized]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_serializedMetrics, ref m_metrics, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerializing]
|
||||||
|
private void OnSerializing(StreamingContext context)
|
||||||
|
{
|
||||||
|
SerializationHelper.Copy(ref m_metrics, ref m_serializedMetrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerialized]
|
||||||
|
private void OnSerialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
m_serializedMetrics = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Metrics", EmitDefaultValue = false)]
|
||||||
|
private List<BuildMetric> m_serializedMetrics;
|
||||||
|
|
||||||
|
[DataMember(Name = "_links", EmitDefaultValue = false)]
|
||||||
|
private ReferenceLinks m_links;
|
||||||
|
|
||||||
|
private List<BuildMetric> m_metrics;
|
||||||
|
|
||||||
|
private List<DefinitionReference> m_drafts;
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "LatestBuild")]
|
||||||
|
private Build m_latestBuild;
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "LatestCompletedBuild")]
|
||||||
|
private Build m_latestCompletedBuild;
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionRevision.cs
Normal file
86
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionRevision.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a revision of a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinitionRevision
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The revision number.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 Revision
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identity of the person or process that changed the definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false, Order = 30)]
|
||||||
|
public IdentityRef ChangedBy
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date and time that the definition was changed.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime ChangedDate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The change type (add, edit, delete).
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public AuditAction ChangeType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The comment associated with the change.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Comment
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A link to the definition at this revision.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DefinitionUrl
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
250
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionStep.cs
Normal file
250
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionStep.cs
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to a task definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class TaskDefinitionReference : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public TaskDefinitionReference()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskDefinitionReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the task.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true)]
|
||||||
|
public Guid Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The version of the task.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true)]
|
||||||
|
public String VersionSpec
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of task (task or task group).
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false)]
|
||||||
|
public String DefinitionType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A clone of this reference.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TaskDefinitionReference Clone()
|
||||||
|
{
|
||||||
|
return (TaskDefinitionReference)this.MemberwiseClone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a step in a build phase.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinitionStep : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildDefinitionStep()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildDefinitionStep(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private BuildDefinitionStep(BuildDefinitionStep toClone)
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(toClone, nameof(toClone));
|
||||||
|
|
||||||
|
this.Enabled = toClone.Enabled;
|
||||||
|
this.ContinueOnError = toClone.ContinueOnError;
|
||||||
|
this.AlwaysRun = toClone.AlwaysRun;
|
||||||
|
this.DisplayName = toClone.DisplayName;
|
||||||
|
this.TimeoutInMinutes = toClone.TimeoutInMinutes;
|
||||||
|
this.Condition = toClone.Condition;
|
||||||
|
this.RefName = toClone.RefName;
|
||||||
|
|
||||||
|
// Cloning the reference type variables since memberwiseclone does a shallow copy
|
||||||
|
if (toClone.TaskDefinition != null)
|
||||||
|
{
|
||||||
|
this.TaskDefinition = toClone.TaskDefinition.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toClone.m_inputs != null)
|
||||||
|
{
|
||||||
|
foreach (var property in toClone.m_inputs)
|
||||||
|
{
|
||||||
|
this.Inputs.Add(property.Key, property.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toClone.m_environment != null)
|
||||||
|
{
|
||||||
|
foreach (var property in toClone.m_environment)
|
||||||
|
{
|
||||||
|
this.Environment.Add(property.Key, property.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The task associated with this step.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true, Order = 1, Name = "Task")]
|
||||||
|
public TaskDefinitionReference TaskDefinition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The inputs used by this step.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<String, String> Inputs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_inputs == null)
|
||||||
|
{
|
||||||
|
m_inputs = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
return m_inputs;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_inputs = new Dictionary<String, String>(value, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the step is enabled.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Boolean Enabled
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the phase should continue even if this step fails.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Boolean ContinueOnError
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether this step should run even if a previous step fails.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Boolean AlwaysRun
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The display name for this step.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DisplayName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time, in minutes, that this step is allowed to run.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Int32 TimeoutInMinutes
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A condition that determines whether this step should run.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false, IsRequired = false)]
|
||||||
|
public String Condition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The reference name for this step.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String RefName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The run-time environment for this step.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<String, String> Environment
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_environment == null)
|
||||||
|
{
|
||||||
|
m_environment = new Dictionary<String, String>(StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_environment;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_environment = new Dictionary<String, String>(value, StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A clone of this step.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public BuildDefinitionStep Clone()
|
||||||
|
{
|
||||||
|
return new BuildDefinitionStep(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Environment", EmitDefaultValue = false)]
|
||||||
|
private Dictionary<String, String> m_environment;
|
||||||
|
|
||||||
|
[DataMember(Name = "Inputs", EmitDefaultValue = false, Order = 2)]
|
||||||
|
private Dictionary<String, String> m_inputs;
|
||||||
|
}
|
||||||
|
}
|
||||||
122
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionTemplate.cs
Normal file
122
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionTemplate.cs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a template from which new build definitions can be created.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinitionTemplate
|
||||||
|
{
|
||||||
|
|
||||||
|
public BuildDefinitionTemplate()
|
||||||
|
{
|
||||||
|
Category = "Custom";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the template.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true)]
|
||||||
|
public String Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the template.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the template can be deleted.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Boolean CanDelete
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The template category.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public String Category
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An optional hosted agent queue for the template to use by default.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public String DefaultHostedQueue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the task whose icon is used when showing this template in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Guid IconTaskId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A description of the template.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Description
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The actual template.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public BuildDefinition Template
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of media type strings to icons for this template.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<String, String> Icons
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_icons == null)
|
||||||
|
{
|
||||||
|
m_icons = new Dictionary<String, String>(StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_icons;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_icons = new Dictionary<String, String>(value, StringComparer.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(EmitDefaultValue = false, Name = "Icons")]
|
||||||
|
private Dictionary<String, String> m_icons;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionVariable.cs
Normal file
69
src/Sdk/BuildWebApi/Api/Contracts/BuildDefinitionVariable.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a variable used by a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildDefinitionVariable : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildDefinitionVariable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildDefinitionVariable(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private BuildDefinitionVariable(BuildDefinitionVariable variableToClone)
|
||||||
|
{
|
||||||
|
Value = variableToClone.Value;
|
||||||
|
AllowOverride = variableToClone.AllowOverride;
|
||||||
|
IsSecret = variableToClone.IsSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the variable.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public String Value
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the value can be set at queue time.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean AllowOverride
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the variable's value is a secret.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean IsSecret
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A clone of this BuildDefinitionVariable.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A new BuildDefinitionVariable</returns>
|
||||||
|
public BuildDefinitionVariable Clone()
|
||||||
|
{
|
||||||
|
return new BuildDefinitionVariable(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/Sdk/BuildWebApi/Api/Contracts/BuildLog.cs
Normal file
53
src/Sdk/BuildWebApi/Api/Contracts/BuildLog.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a build log.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildLog : BuildLogReference
|
||||||
|
{
|
||||||
|
public BuildLog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildLog(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of lines in the log.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int64 LineCount
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date and time the log was created.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public DateTime? CreatedOn
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date and time the log was last changed.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public DateTime? LastChangedOn
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/Sdk/BuildWebApi/Api/Contracts/BuildLogReference.cs
Normal file
54
src/Sdk/BuildWebApi/Api/Contracts/BuildLogReference.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a build log.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildLogReference : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildLogReference()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildLogReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the log.
|
||||||
|
/// </summary>
|
||||||
|
// EmitDefaultValue is true to ensure that id = 0 is sent for XAML builds' "ActivityLog.xml"
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = true)]
|
||||||
|
public Int32 Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the log location.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public String Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A full link to the log resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = false, EmitDefaultValue = false)]
|
||||||
|
public String Url
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/Sdk/BuildWebApi/Api/Contracts/BuildMetric.cs
Normal file
63
src/Sdk/BuildWebApi/Api/Contracts/BuildMetric.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents metadata about builds in the system.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildMetric : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildMetric()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildMetric(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
:base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the metric.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scope.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Scope
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The value.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public Int32 IntValue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date for the scope.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public DateTime? Date
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/Sdk/BuildWebApi/Api/Contracts/BuildOption.cs
Normal file
67
src/Sdk/BuildWebApi/Api/Contracts/BuildOption.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the application of an optional behavior to a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildOption : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildOption()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildOption(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true, Order = 1, Name = "Definition")]
|
||||||
|
public virtual BuildOptionDefinitionReference BuildOptionDefinition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The inputs that configure the behavior.
|
||||||
|
/// </summary>
|
||||||
|
public virtual IDictionary<String, String> Inputs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_inputs == null)
|
||||||
|
{
|
||||||
|
m_inputs = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_inputs;
|
||||||
|
}
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
m_inputs = new Dictionary<String, String>(value, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the behavior is enabled.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = true)]
|
||||||
|
public virtual Boolean Enabled
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Inputs", EmitDefaultValue = false, Order = 2)]
|
||||||
|
private Dictionary<String, String> m_inputs;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/Sdk/BuildWebApi/Api/Contracts/BuildOptionDefinition.cs
Normal file
100
src/Sdk/BuildWebApi/Api/Contracts/BuildOptionDefinition.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an optional behavior that can be applied to a build definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildOptionDefinition : BuildOptionDefinitionReference
|
||||||
|
{
|
||||||
|
public BuildOptionDefinition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildOptionDefinition(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A value that indicates the relative order in which the behavior should be applied.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 Ordinal
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The description.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Description
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of inputs defined for the build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IList<BuildOptionInputDefinition> Inputs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_inputs == null)
|
||||||
|
{
|
||||||
|
m_inputs = new List<BuildOptionInputDefinition>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_inputs;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_inputs = new List<BuildOptionInputDefinition>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of input groups defined for the build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public IList<BuildOptionGroupDefinition> Groups
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_groups == null)
|
||||||
|
{
|
||||||
|
m_groups = new List<BuildOptionGroupDefinition>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_groups;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_groups = new List<BuildOptionGroupDefinition>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BuildOptionInputDefinition> m_inputs;
|
||||||
|
|
||||||
|
private List<BuildOptionGroupDefinition> m_groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a build option definition.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildOptionDefinitionReference : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildOptionDefinitionReference()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildOptionDefinitionReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the referenced build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(IsRequired = true, Order = 1)]
|
||||||
|
public Guid Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a group of inputs for a build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildOptionGroupDefinition : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildOptionGroupDefinition()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildOptionGroupDefinition(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The internal name of the group.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the group to display in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DisplayName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the group is initially displayed as expanded in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean IsExpanded
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
src/Sdk/BuildWebApi/Api/Contracts/BuildOptionInputDefinition.cs
Normal file
144
src/Sdk/BuildWebApi/Api/Contracts/BuildOptionInputDefinition.cs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an input for a build option.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class BuildOptionInputDefinition : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildOptionInputDefinition()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildOptionInputDefinition(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
InputType = BuildOptionInputType.String;
|
||||||
|
DefaultValue = String.Empty;
|
||||||
|
Required = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the input.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The label for the input.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Label
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default value.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String DefaultValue
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the input is required to have a value.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Boolean Required
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of the input value.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(Name = "Type")]
|
||||||
|
public BuildOptionInputType InputType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The rule that is applied to determine whether the input is visible in the UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String VisibleRule
|
||||||
|
{
|
||||||
|
// Typical format is "NAMEOFTHEDEPENDENTINPUT = VALUETOBEBOUND"
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the input group that this input belongs to.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String GroupName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of options for this input.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<String, String> Options
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_Options == null)
|
||||||
|
{
|
||||||
|
m_Options = new Dictionary<String, String>();
|
||||||
|
}
|
||||||
|
return m_Options;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_Options = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary of help documents for this input.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<String, String> HelpDocuments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_HelpDocuments == null)
|
||||||
|
{
|
||||||
|
m_HelpDocuments = new Dictionary<String, String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_HelpDocuments;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_HelpDocuments = new Dictionary<String, String>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Options", EmitDefaultValue = false)]
|
||||||
|
private Dictionary<String, String> m_Options;
|
||||||
|
|
||||||
|
[DataMember(Name = "Help", EmitDefaultValue = false)]
|
||||||
|
private Dictionary<String, String> m_HelpDocuments;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/Sdk/BuildWebApi/Api/Contracts/BuildProcess.cs
Normal file
45
src/Sdk/BuildWebApi/Api/Contracts/BuildProcess.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a build process.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
[KnownType(typeof(DesignerProcess))]
|
||||||
|
[KnownType(typeof(YamlProcess))]
|
||||||
|
[KnownType(typeof(DockerProcess))]
|
||||||
|
[KnownType(typeof(JustInTimeProcess))]
|
||||||
|
[JsonConverter(typeof(BuildProcessJsonConverter))]
|
||||||
|
public class BuildProcess : BaseSecuredObject
|
||||||
|
{
|
||||||
|
protected BuildProcess(
|
||||||
|
Int32 type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal BuildProcess(
|
||||||
|
Int32 type,
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
this.Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the process.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// See <see cref="ProcessType" /> for a list of valid process types.
|
||||||
|
/// </remarks>
|
||||||
|
[DataMember(Name = "Type")]
|
||||||
|
public Int32 Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
internal sealed class BuildProcessJsonConverter : TypePropertyJsonConverter<BuildProcess>
|
||||||
|
{
|
||||||
|
protected override BuildProcess GetInstance(
|
||||||
|
Type objectType)
|
||||||
|
{
|
||||||
|
if (objectType == typeof(DesignerProcess))
|
||||||
|
{
|
||||||
|
return new DesignerProcess();
|
||||||
|
}
|
||||||
|
else if (objectType == typeof(YamlProcess))
|
||||||
|
{
|
||||||
|
return new YamlProcess();
|
||||||
|
}
|
||||||
|
else if (objectType == typeof(DockerProcess))
|
||||||
|
{
|
||||||
|
return new DockerProcess();
|
||||||
|
}
|
||||||
|
else if (objectType == typeof(JustInTimeProcess))
|
||||||
|
{
|
||||||
|
return new JustInTimeProcess();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return base.GetInstance(objectType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BuildProcess GetInstance(
|
||||||
|
Int32 targetType)
|
||||||
|
{
|
||||||
|
switch (targetType)
|
||||||
|
{
|
||||||
|
case ProcessType.Yaml:
|
||||||
|
return new YamlProcess();
|
||||||
|
case ProcessType.Docker:
|
||||||
|
return new DockerProcess();
|
||||||
|
case ProcessType.JustInTime:
|
||||||
|
return new JustInTimeProcess();
|
||||||
|
case ProcessType.Designer:
|
||||||
|
default:
|
||||||
|
return new DesignerProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Boolean TryInferType(
|
||||||
|
JObject value,
|
||||||
|
out Int32 type)
|
||||||
|
{
|
||||||
|
// if it has a YamlFilename property, assume it's a YamlProcess
|
||||||
|
if (value.TryGetValue("yamlFilename", StringComparison.OrdinalIgnoreCase, out JToken yamlFilename))
|
||||||
|
{
|
||||||
|
type = ProcessType.Yaml;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// default to Designer process
|
||||||
|
type = ProcessType.Designer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
247
src/Sdk/BuildWebApi/Api/Contracts/BuildProcessResources.cs
Normal file
247
src/Sdk/BuildWebApi/Api/Contracts/BuildProcessResources.cs
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Build.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents resources used by a build process.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public sealed class BuildProcessResources : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public BuildProcessResources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal BuildProcessResources(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information about the queues used by the process.
|
||||||
|
/// </summary>
|
||||||
|
public IList<AgentPoolQueueReference> Queues
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_queues == null)
|
||||||
|
{
|
||||||
|
m_queues = new List<AgentPoolQueueReference>();
|
||||||
|
}
|
||||||
|
return m_queues;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_queues = new List<AgentPoolQueueReference>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information about the endpoints used by the process.
|
||||||
|
/// </summary>
|
||||||
|
public IList<ServiceEndpointReference> Endpoints
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_endpoints == null)
|
||||||
|
{
|
||||||
|
m_endpoints = new List<ServiceEndpointReference>();
|
||||||
|
}
|
||||||
|
return m_endpoints;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_endpoints = new List<ServiceEndpointReference>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information about the secure files used by the process.
|
||||||
|
/// </summary>
|
||||||
|
public IList<SecureFileReference> Files
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_files == null)
|
||||||
|
{
|
||||||
|
m_files = new List<SecureFileReference>();
|
||||||
|
}
|
||||||
|
return m_files;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_files = new List<SecureFileReference>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Information about the variable groups used by the process.
|
||||||
|
/// </summary>
|
||||||
|
public IList<VariableGroupReference> VariableGroups
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_variableGroups == null)
|
||||||
|
{
|
||||||
|
m_variableGroups = new List<VariableGroupReference>();
|
||||||
|
}
|
||||||
|
return m_variableGroups;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
m_variableGroups = new List<VariableGroupReference>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnSerializing]
|
||||||
|
private void OnSerializing(StreamingContext context)
|
||||||
|
{
|
||||||
|
if (m_queues?.Count == 0)
|
||||||
|
{
|
||||||
|
m_queues = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_endpoints?.Count == 0)
|
||||||
|
{
|
||||||
|
m_endpoints = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_files?.Count == 0)
|
||||||
|
{
|
||||||
|
m_files = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_variableGroups?.Count == 0)
|
||||||
|
{
|
||||||
|
m_variableGroups = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataMember(Name = "Queues", EmitDefaultValue = false)]
|
||||||
|
private List<AgentPoolQueueReference> m_queues;
|
||||||
|
|
||||||
|
[DataMember(Name = "Endpoints", EmitDefaultValue = false)]
|
||||||
|
private List<ServiceEndpointReference> m_endpoints;
|
||||||
|
|
||||||
|
[DataMember(Name = "Files", EmitDefaultValue = false)]
|
||||||
|
private List<SecureFileReference> m_files;
|
||||||
|
|
||||||
|
[DataMember(Name = "VariableGroups", EmitDefaultValue = false)]
|
||||||
|
private List<VariableGroupReference> m_variableGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public abstract class ResourceReference : BaseSecuredObject
|
||||||
|
{
|
||||||
|
public ResourceReference()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResourceReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An alias to be used when referencing the resource.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public String Alias
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to an agent queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class AgentPoolQueueReference : ResourceReference
|
||||||
|
{
|
||||||
|
public AgentPoolQueueReference()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal AgentPoolQueueReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the queue.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Int32 Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a referenec to a service endpoint.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class ServiceEndpointReference : ResourceReference
|
||||||
|
{
|
||||||
|
public ServiceEndpointReference()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ServiceEndpointReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the service endpoint.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Guid Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a secure file.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class SecureFileReference : ResourceReference
|
||||||
|
{
|
||||||
|
public SecureFileReference()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal SecureFileReference(
|
||||||
|
ISecuredObject securedObject)
|
||||||
|
: base(securedObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the secure file.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember(EmitDefaultValue = false)]
|
||||||
|
public Guid Id
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user