mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b061ec410f | ||
|
|
2b63b9c379 | ||
|
|
d93fb70a3e | ||
|
|
4ce1bfb58a | ||
|
|
7a6d9dc5c8 | ||
|
|
de29a39d14 | ||
|
|
7d505f7f77 | ||
|
|
159e4c506a | ||
|
|
45c19eb7cb | ||
|
|
9ba971592b | ||
|
|
b27cfb18e6 | ||
|
|
ced4c2ca50 | ||
|
|
54f21c641f | ||
|
|
c5cbac9796 | ||
|
|
8911283cdb | ||
|
|
76078b5c44 | ||
|
|
ec9cb6c68d | ||
|
|
bcac4557a0 | ||
|
|
19580bdaf8 | ||
|
|
96d3288553 | ||
|
|
5b6f9d3b93 | ||
|
|
51581ac865 | ||
|
|
e7dd2c6cc2 | ||
|
|
08b9f6e045 | ||
|
|
0129e8111f | ||
|
|
ccca13ac07 |
27
.github/workflows/build.yml
vendored
27
.github/workflows/build.yml
vendored
@@ -13,14 +13,28 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- runtime: linux-x64
|
||||||
|
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
|
||||||
@@ -28,7 +42,7 @@ jobs:
|
|||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} layout Release
|
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
@@ -36,6 +50,7 @@ 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
|
||||||
@@ -49,5 +64,5 @@ jobs:
|
|||||||
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.os }}
|
name: runner-package-${{ matrix.runtime }}
|
||||||
path: _package
|
path: _package
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,7 +3,6 @@
|
|||||||
**/libs
|
**/libs
|
||||||
**/*.xproj
|
**/*.xproj
|
||||||
**/*.xproj.user
|
**/*.xproj.user
|
||||||
**/*.sln
|
|
||||||
**/.vs
|
**/.vs
|
||||||
**/.vscode
|
**/.vscode
|
||||||
**/*.error
|
**/*.error
|
||||||
|
|||||||
73
ActionsRunner.sln
Normal file
73
ActionsRunner.sln
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
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,5 +16,17 @@
|
|||||||
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -11,6 +11,8 @@ 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: |
|
||||||
@@ -28,13 +30,13 @@ stages:
|
|||||||
displayName: Package UCRT
|
displayName: Package UCRT
|
||||||
|
|
||||||
# Create agent package zip
|
# Create agent package zip
|
||||||
- script: dev.cmd package Release
|
- script: dev.cmd package Release win-x64
|
||||||
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)
|
displayName: Publish Artifact (Windows x64)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
@@ -50,22 +52,76 @@ 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
|
- script: ./dev.sh package Release linux-x64
|
||||||
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)
|
displayName: Publish Artifact (Linux x64)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
artifactType: container
|
artifactType: container
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
- job: build_osx_agent
|
- job: build_linux_agent_arm64
|
||||||
|
################################################################################
|
||||||
|
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:
|
||||||
@@ -74,15 +130,17 @@ 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
|
- script: ./dev.sh package Release osx-x64
|
||||||
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)
|
displayName: Publish Artifact (OSX x64)
|
||||||
inputs:
|
inputs:
|
||||||
pathToPublish: _package
|
pathToPublish: _package
|
||||||
artifactName: runners
|
artifactName: runners
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# Contribute (Dev)
|
# Contribution guide for developers
|
||||||
|
|
||||||
## Dev Dependencies
|
## Required 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)
|
||||||
|
|
||||||
## Build, Test, Layout
|
## To Build, Test, Layout
|
||||||
|
|
||||||
From src:
|
Navigate to the `src` directory and run the following command:
|
||||||
|
|
||||||
 `dev {command}`
|
 `dev {command}`
|
||||||
|
|
||||||
@@ -14,13 +14,12 @@ From src:
|
|||||||
|
|
||||||
**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
|
||||||
|
|
||||||
`build` (`b`): build everything and update agent layout folder
|
Sample developer flow:
|
||||||
|
|
||||||
`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
|
||||||
@@ -37,5 +36,5 @@ cd ./src
|
|||||||
|
|
||||||
## Styling
|
## Styling
|
||||||
|
|
||||||
We use the dotnet foundation and CoreCLR style guidelines [located here](
|
We use the .NET 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 Sierra (10.12) and later versions
|
- macOS High Sierra (10.13) and later versions
|
||||||
|
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore2x)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -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=netcore2x)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
|
parameters:
|
||||||
|
targetRuntime: ''
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# Build agent layout
|
# Build agent layout
|
||||||
- script: ./dev.sh layout Release
|
- script: ./dev.sh layout Release ${{ parameters.targetRuntime }}
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Build & Layout Release
|
displayName: Build & Layout Release ${{ parameters.targetRuntime }}
|
||||||
|
|
||||||
# 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,40 +1,69 @@
|
|||||||
## Features
|
## Features
|
||||||
- Set Default shell to powershell for windows runners (#135)
|
- Added the "severity" keyword to allow action authors to set the default severity for problem matchers (#203)
|
||||||
- Use Powershell as fallback if Powershell Core is not available for default shell on windows (#142)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Removed unintended additional fields on error and warning commands (#137)
|
- Fixed generated self-hosted runner names to never go over 80 characters (helps Windows customers) (#193)
|
||||||
|
- Fixed `PrepareActions_DownloadActionFromGraph` test by pointing to an active Actions repository (#205)
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
- N/A
|
- Updated the publish and download artifact actions to use the v2 endpoint (#188)
|
||||||
|
- Updated the service name on self-hosted runner name to include repository or organization information (#193)
|
||||||
## 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
|
```
|
||||||
C:\> mkdir myagent && cd myagent
|
// Create a folder under the drive root
|
||||||
C:\myagent> Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
mkdir \actions-runner ; cd \actions-runner
|
||||||
|
// 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
|
||||||
~/$ mkdir myagent && cd myagent
|
// Create a folder
|
||||||
~/myagent$ tar xzf ~/Downloads/actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
mkdir actions-runner && cd actions-runner
|
||||||
|
// 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
|
||||||
~/$ mkdir myagent && cd myagent
|
// Create a folder
|
||||||
~/myagent$ tar xzf ~/Downloads/actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
mkdir actions-runner && cd actions-runner
|
||||||
|
// 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)
|
||||||
|
|||||||
49
src/Directory.Build.props
Normal file
49
src/Directory.Build.props
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<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>
|
||||||
75
src/Misc/dotnet-install.ps1
vendored
75
src/Misc/dotnet-install.ps1
vendored
@@ -37,10 +37,7 @@
|
|||||||
.PARAMETER SharedRuntime
|
.PARAMETER SharedRuntime
|
||||||
This parameter is obsolete and may be removed in a future version of this script.
|
This parameter is obsolete and may be removed in a future version of this script.
|
||||||
The recommended alternative is '-Runtime dotnet'.
|
The recommended alternative is '-Runtime dotnet'.
|
||||||
|
|
||||||
Default: false
|
|
||||||
Installs just the shared runtime bits, not the entire SDK.
|
Installs just the shared runtime bits, not the entire SDK.
|
||||||
This is equivalent to specifying `-Runtime dotnet`.
|
|
||||||
.PARAMETER Runtime
|
.PARAMETER Runtime
|
||||||
Installs just a shared runtime, not the entire SDK.
|
Installs just a shared runtime, not the entire SDK.
|
||||||
Possible values:
|
Possible values:
|
||||||
@@ -77,11 +74,15 @@
|
|||||||
Skips installing non-versioned files if they already exist, such as dotnet.exe.
|
Skips installing non-versioned files if they already exist, such as dotnet.exe.
|
||||||
.PARAMETER NoCdn
|
.PARAMETER NoCdn
|
||||||
Disable downloading from the Azure CDN, and use the uncached feed directly.
|
Disable downloading from the Azure CDN, and use the uncached feed directly.
|
||||||
|
.PARAMETER JSonFile
|
||||||
|
Determines the SDK version from a user specified global.json file
|
||||||
|
Note: global.json must have a value for 'SDK:Version'
|
||||||
#>
|
#>
|
||||||
[cmdletbinding()]
|
[cmdletbinding()]
|
||||||
param(
|
param(
|
||||||
[string]$Channel="LTS",
|
[string]$Channel="LTS",
|
||||||
[string]$Version="Latest",
|
[string]$Version="Latest",
|
||||||
|
[string]$JSonFile,
|
||||||
[string]$InstallDir="<auto>",
|
[string]$InstallDir="<auto>",
|
||||||
[string]$Architecture="<auto>",
|
[string]$Architecture="<auto>",
|
||||||
[ValidateSet("dotnet", "aspnetcore", "windowsdesktop", IgnoreCase = $false)]
|
[ValidateSet("dotnet", "aspnetcore", "windowsdesktop", IgnoreCase = $false)]
|
||||||
@@ -258,7 +259,6 @@ function GetHTTPResponse([Uri] $Uri)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) {
|
function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
@@ -304,10 +304,50 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
|
|||||||
return $VersionInfo
|
return $VersionInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Parse-Jsonfile-For-Version([string]$JSonFile) {
|
||||||
function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version) {
|
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
|
If (-Not (Test-Path $JSonFile)) {
|
||||||
|
throw "Unable to find '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$JSonContent = Get-Content($JSonFile) -Raw | ConvertFrom-Json | Select-Object -expand "sdk" -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw "Json file unreadable: '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
if ($JSonContent) {
|
||||||
|
try {
|
||||||
|
$JSonContent.PSObject.Properties | ForEach-Object {
|
||||||
|
$PropertyName = $_.Name
|
||||||
|
if ($PropertyName -eq "version") {
|
||||||
|
$Version = $_.Value
|
||||||
|
Say-Verbose "Version = $Version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
throw "Unable to parse the SDK node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Unable to find the SDK node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
If ($Version -eq $null) {
|
||||||
|
throw "Unable to find the SDK:version node in '$JSonFile'"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
return $Version
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version, [string]$JSonFile) {
|
||||||
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
|
if (-not $JSonFile) {
|
||||||
switch ($Version.ToLower()) {
|
switch ($Version.ToLower()) {
|
||||||
{ $_ -eq "latest" } {
|
{ $_ -eq "latest" } {
|
||||||
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False
|
$LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False
|
||||||
@@ -320,6 +360,10 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
|
|||||||
default { return $Version }
|
default { return $Version }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return Parse-Jsonfile-For-Version $JSonFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
|
function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
@@ -382,23 +426,6 @@ function Resolve-Installation-Path([string]$InstallDir) {
|
|||||||
return $InstallDir
|
return $InstallDir
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) {
|
|
||||||
Say-Invocation $MyInvocation
|
|
||||||
|
|
||||||
$VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile
|
|
||||||
Say-Verbose "Local version file: $VersionFile"
|
|
||||||
|
|
||||||
if (Test-Path $VersionFile) {
|
|
||||||
$VersionText = cat $VersionFile
|
|
||||||
Say-Verbose "Local version file text: $VersionText"
|
|
||||||
return Get-Version-Info-From-Version-Text $VersionText
|
|
||||||
}
|
|
||||||
|
|
||||||
Say-Verbose "Local version file not found."
|
|
||||||
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
|
|
||||||
function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) {
|
function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
@@ -534,7 +561,7 @@ function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolde
|
|||||||
}
|
}
|
||||||
|
|
||||||
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture
|
||||||
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version
|
$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -JSonFile $JSonFile
|
||||||
$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
||||||
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture
|
||||||
|
|
||||||
|
|||||||
85
src/Misc/dotnet-install.sh
vendored
85
src/Misc/dotnet-install.sh
vendored
@@ -435,11 +435,52 @@ get_latest_version_info() {
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# args:
|
||||||
|
# json_file - $1
|
||||||
|
parse_jsonfile_for_version() {
|
||||||
|
eval $invocation
|
||||||
|
|
||||||
|
local json_file="$1"
|
||||||
|
if [ ! -f "$json_file" ]; then
|
||||||
|
say_err "Unable to find \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sdk_section=$(cat $json_file | awk '/"sdk"/,/}/')
|
||||||
|
if [ -z "$sdk_section" ]; then
|
||||||
|
say_err "Unable to parse the SDK node in \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sdk_list=$(echo $sdk_section | awk -F"[{}]" '{print $2}')
|
||||||
|
sdk_list=${sdk_list//[\" ]/}
|
||||||
|
sdk_list=${sdk_list//,/$'\n'}
|
||||||
|
sdk_list="$(echo -e "${sdk_list}" | tr -d '[[:space:]]')"
|
||||||
|
|
||||||
|
local version_info=""
|
||||||
|
while read -r line; do
|
||||||
|
IFS=:
|
||||||
|
while read -r key value; do
|
||||||
|
if [[ "$key" == "version" ]]; then
|
||||||
|
version_info=$value
|
||||||
|
fi
|
||||||
|
done <<< "$line"
|
||||||
|
done <<< "$sdk_list"
|
||||||
|
if [ -z "$version_info" ]; then
|
||||||
|
say_err "Unable to find the SDK:version node in \`$json_file\`"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version_info"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
# azure_feed - $1
|
# azure_feed - $1
|
||||||
# channel - $2
|
# channel - $2
|
||||||
# normalized_architecture - $3
|
# normalized_architecture - $3
|
||||||
# version - $4
|
# version - $4
|
||||||
|
# json_file - $5
|
||||||
get_specific_version_from_version() {
|
get_specific_version_from_version() {
|
||||||
eval $invocation
|
eval $invocation
|
||||||
|
|
||||||
@@ -447,7 +488,9 @@ get_specific_version_from_version() {
|
|||||||
local channel="$2"
|
local channel="$2"
|
||||||
local normalized_architecture="$3"
|
local normalized_architecture="$3"
|
||||||
local version="$(to_lowercase "$4")"
|
local version="$(to_lowercase "$4")"
|
||||||
|
local json_file="$5"
|
||||||
|
|
||||||
|
if [ -z "$json_file" ]; then
|
||||||
case "$version" in
|
case "$version" in
|
||||||
latest)
|
latest)
|
||||||
local version_info
|
local version_info
|
||||||
@@ -468,6 +511,12 @@ get_specific_version_from_version() {
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
else
|
||||||
|
local version_info
|
||||||
|
version_info="$(parse_jsonfile_for_version "$json_file")" || return 1
|
||||||
|
echo "$version_info"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
@@ -558,24 +607,6 @@ resolve_installation_path() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# args:
|
|
||||||
# install_root - $1
|
|
||||||
get_installed_version_info() {
|
|
||||||
eval $invocation
|
|
||||||
|
|
||||||
local install_root="$1"
|
|
||||||
local version_file="$(combine_paths "$install_root" "$local_version_file_relative_path")"
|
|
||||||
say_verbose "Local version file: $version_file"
|
|
||||||
if [ ! -z "$version_file" ] | [ -r "$version_file" ]; then
|
|
||||||
local version_info="$(cat "$version_file")"
|
|
||||||
echo "$version_info"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
say_verbose "Local version file not found."
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# args:
|
# args:
|
||||||
# relative_or_absolute_path - $1
|
# relative_or_absolute_path - $1
|
||||||
get_absolute_path() {
|
get_absolute_path() {
|
||||||
@@ -724,7 +755,7 @@ calculate_vars() {
|
|||||||
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
|
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
|
||||||
say_verbose "normalized_architecture=$normalized_architecture"
|
say_verbose "normalized_architecture=$normalized_architecture"
|
||||||
|
|
||||||
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version")"
|
specific_version="$(get_specific_version_from_version "$azure_feed" "$channel" "$normalized_architecture" "$version" "$json_file")"
|
||||||
say_verbose "specific_version=$specific_version"
|
say_verbose "specific_version=$specific_version"
|
||||||
if [ -z "$specific_version" ]; then
|
if [ -z "$specific_version" ]; then
|
||||||
say_err "Could not resolve version information."
|
say_err "Could not resolve version information."
|
||||||
@@ -826,6 +857,7 @@ temporary_file_template="${TMPDIR:-/tmp}/dotnet.XXXXXXXXX"
|
|||||||
|
|
||||||
channel="LTS"
|
channel="LTS"
|
||||||
version="Latest"
|
version="Latest"
|
||||||
|
json_file=""
|
||||||
install_dir="<auto>"
|
install_dir="<auto>"
|
||||||
architecture="<auto>"
|
architecture="<auto>"
|
||||||
dry_run=false
|
dry_run=false
|
||||||
@@ -912,6 +944,10 @@ do
|
|||||||
runtime_id="$1"
|
runtime_id="$1"
|
||||||
non_dynamic_parameters+=" $name "\""$1"\"""
|
non_dynamic_parameters+=" $name "\""$1"\"""
|
||||||
;;
|
;;
|
||||||
|
--jsonfile|-[Jj][Ss]on[Ff]ile)
|
||||||
|
shift
|
||||||
|
json_file="$1"
|
||||||
|
;;
|
||||||
--skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
|
--skip-non-versioned-files|-[Ss]kip[Nn]on[Vv]ersioned[Ff]iles)
|
||||||
override_non_versioned_files=false
|
override_non_versioned_files=false
|
||||||
non_dynamic_parameters+=" $name"
|
non_dynamic_parameters+=" $name"
|
||||||
@@ -953,22 +989,25 @@ do
|
|||||||
echo " Possible values:"
|
echo " Possible values:"
|
||||||
echo " - dotnet - the Microsoft.NETCore.App shared runtime"
|
echo " - dotnet - the Microsoft.NETCore.App shared runtime"
|
||||||
echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
|
echo " - aspnetcore - the Microsoft.AspNetCore.App shared runtime"
|
||||||
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
|
|
||||||
echo " -SkipNonVersionedFiles"
|
|
||||||
echo " --dry-run,-DryRun Do not perform installation. Display download link."
|
echo " --dry-run,-DryRun Do not perform installation. Display download link."
|
||||||
echo " --no-path, -NoPath Do not set PATH for the current process."
|
echo " --no-path, -NoPath Do not set PATH for the current process."
|
||||||
echo " --verbose,-Verbose Display diagnostics information."
|
echo " --verbose,-Verbose Display diagnostics information."
|
||||||
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
|
echo " --azure-feed,-AzureFeed Azure feed location. Defaults to $azure_feed, This parameter typically is not changed by the user."
|
||||||
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
|
echo " --uncached-feed,-UncachedFeed Uncached feed location. This parameter typically is not changed by the user."
|
||||||
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
|
||||||
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
|
echo " --feed-credential,-FeedCredential Azure feed shared access token. This parameter typically is not specified."
|
||||||
|
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
|
||||||
|
echo " -SkipNonVersionedFiles"
|
||||||
|
echo " --no-cdn,-NoCdn Disable downloading from the Azure CDN, and use the uncached feed directly."
|
||||||
|
echo " --jsonfile <JSONFILE> Determines the SDK version from a user specified global.json file."
|
||||||
|
echo " Note: global.json must have a value for 'SDK:Version'"
|
||||||
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
echo " --runtime-id Installs the .NET Tools for the given platform (use linux-x64 for portable linux)."
|
||||||
echo " -RuntimeId"
|
echo " -RuntimeId"
|
||||||
echo " -?,--?,-h,--help,-Help Shows this help message"
|
echo " -?,--?,-h,--help,-Help Shows this help message"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Obsolete parameters:"
|
echo "Obsolete parameters:"
|
||||||
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
|
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
|
||||||
echo " -SharedRuntime Installs just the shared runtime bits, not the entire SDK."
|
echo " This parameter is obsolete and may be removed in a future version of this script."
|
||||||
|
echo " Installs just the shared runtime bits, not the entire SDK."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Install Location:"
|
echo "Install Location:"
|
||||||
echo " Location is chosen in following order:"
|
echo " Location is chosen in following order:"
|
||||||
|
|||||||
@@ -123,9 +123,9 @@ function acquireExternalTool() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/win-x64/node.exe" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/win-x64/node.lib" node12/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/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,13 +136,23 @@ 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 common across Linux PACKAGERUNTIMEs (excluding OSX).
|
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" || "$PACKAGERUNTIME" == "rhel.6-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-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
|
||||||
# TODO: Repath this blob to use a consistent version format (_ vs .)
|
# TODO: Repath this blob to use a consistent version format (_ vs .)
|
||||||
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12_4_0/alpine/node-v${NODE12_VERSION}-alpine.tar.gz" node12_alpine
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12_4_0/alpine/node-v${NODE12_VERSION}-alpine.tar.gz" node12_alpine
|
||||||
|
# acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12.13.0/alpine/x64/node-v${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||||
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
||||||
|
# TODO: alpine node runtime for arm64(8)
|
||||||
|
# acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12.13.0/alpine/arm64/node-v${NODE12_VERSION}-alpine-arm64.tar.gz" node12_alpine
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
||||||
|
# TODO: alpine node runtime for arm32(7)
|
||||||
|
# Need to set up custom gcc toolchain to cross compile on x64 ubuntu for armv7 (per https://github.com/nodejs/node/blob/master/BUILDING.md)
|
||||||
|
# acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/12.13.0/alpine/arm/node-v${NODE12_VERSION}-alpine-arm.tar.gz" node12_alpine
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
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;
|
||||||
@@ -51,6 +53,34 @@ 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]
|
||||||
|
|||||||
@@ -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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
@@ -28,42 +28,4 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ 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.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}.{2}";
|
private const string _svcNamePattern = "actions.runner.{0}.{1}";
|
||||||
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
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,5 +1,6 @@
|
|||||||
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;
|
||||||
@@ -37,25 +38,38 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
serviceName = string.Empty;
|
serviceName = string.Empty;
|
||||||
serviceDisplayName = string.Empty;
|
serviceDisplayName = string.Empty;
|
||||||
|
|
||||||
Uri accountUri = new Uri(settings.ServerUrl);
|
if (string.IsNullOrEmpty(settings.RepoOrOrgName))
|
||||||
string accountName = string.Empty;
|
|
||||||
|
|
||||||
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
accountName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
throw new InvalidOperationException($"Cannot find GitHub repository/organization name from server url: '{settings.ServerUrl}'");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
accountName = accountUri.Host.Split('.').FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(accountName))
|
// For the service name, replace any characters outside of the alpha-numeric set and ".", "_", "-" with "-"
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Cannot find GitHub organization name from server url: '{settings.ServerUrl}'");
|
Trace.Verbose($"Calculated service name is too long (> 80 chars). Trying again by calculating a shorter name.");
|
||||||
|
|
||||||
|
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, accountName, settings.PoolName, settings.AgentName);
|
serviceName = StringUtil.Format(serviceNamePattern, repoOrOrgNameSubstring, runnerNameSubstring);
|
||||||
serviceDisplayName = StringUtil.Format(serviceDisplayNamePattern, accountName, settings.PoolName, settings.AgentName);
|
}
|
||||||
|
|
||||||
|
serviceDisplayName = StringUtil.Format(serviceDisplayNamePattern, repoOrOrgName, 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}.{2}.service";
|
private const string _svcNamePattern = "actions.runner.{0}.{1}.service";
|
||||||
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
private const string _svcDisplayPattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
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 = "actionsrunner.{0}.{1}.{2}";
|
private const string ServiceNamePattern = "actions.runner.{0}.{1}";
|
||||||
private const string ServiceDisplayNamePattern = "GitHub Actions Runner ({0}.{1}.{2})";
|
private const string ServiceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
|
|
||||||
private INativeWindowsServiceHelper _windowsServiceHelper;
|
private INativeWindowsServiceHelper _windowsServiceHelper;
|
||||||
private ITerminal _term;
|
private ITerminal _term;
|
||||||
|
|||||||
@@ -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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
@@ -31,42 +31,4 @@
|
|||||||
<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,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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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,42 +24,4 @@
|
|||||||
<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,28 +50,61 @@ 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}");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Output($"Download artifact '{artifactName}' to: '{targetPath}'");
|
// Determine whether to call Pipelines or Build endpoint to publish artifact based on variable setting
|
||||||
|
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}'");
|
||||||
|
|
||||||
|
if (usePipelinesArtifactEndpoint)
|
||||||
|
{
|
||||||
|
context.Debug("Downloading artifact using v2 endpoint");
|
||||||
|
|
||||||
|
// Definition ID is a dummy value only used by HTTP client routing purposes
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
containerPath = actionsStorageArtifact.Name; // In actions storage artifacts, name equals the path
|
||||||
|
containerId = actionsStorageArtifact.ContainerId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Debug("Downloading artifact using v1 endpoint");
|
||||||
|
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
BuildArtifact buildArtifact = await buildHelper.GetArtifact(projectId, buildId, artifactName, token);
|
BuildArtifact buildArtifact = await buildHelper.GetArtifact(projectId, buildId, artifactName, token);
|
||||||
|
|
||||||
if (string.Equals(buildArtifact.Resource.Type, "Container", StringComparison.OrdinalIgnoreCase))
|
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 containerUrl = buildArtifact.Resource.Data;
|
||||||
string[] parts = containerUrl.Split(new[] { '/' }, 3);
|
string[] parts = containerUrl.Split(new[] { '/' }, 3);
|
||||||
if (parts.Length < 3 || !long.TryParse(parts[1], out long containerId))
|
if (parts.Length < 3 || !long.TryParse(parts[1], out containerId))
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException($"Invalid container url '{containerUrl}' for artifact '{buildArtifact.Name}'");
|
throw new ArgumentOutOfRangeException($"Invalid container url '{containerUrl}' for artifact '{buildArtifact.Name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
string containerPath = parts[2];
|
containerPath = parts[2];
|
||||||
FileContainerServer fileContainerServer = new FileContainerServer(context.VssConnection, projectId, containerId, containerPath);
|
|
||||||
await fileContainerServer.DownloadFromContainerAsync(context, targetPath, token);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"Invalid artifact type: {buildArtifact.Resource.Type}");
|
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.");
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/Runner.Plugins/Artifact/PipelinesServer.cs
Normal file
60
src/Runner.Plugins/Artifact/PipelinesServer.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
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,27 +68,59 @@ 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 a Int64: {containerIdStr}");
|
throw new ArgumentException($"Container Id is not an 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
|
||||||
{
|
{
|
||||||
long size = await fileContainerHelper.CopyToContainerAsync(context, fullPath, token);
|
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 usePipelinesArtifactEndpointVar = context.Variables.GetValueOrDefault("Runner.UseActionsArtifactsApis")?.Value;
|
||||||
|
bool.TryParse(usePipelinesArtifactEndpointVar, out bool usePipelinesArtifactEndpoint);
|
||||||
|
|
||||||
|
if (usePipelinesArtifactEndpoint)
|
||||||
|
{
|
||||||
|
// 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}");
|
string fileContainerFullPath = StringUtil.Format($"#/{containerId}/{artifactName}");
|
||||||
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
BuildServer buildHelper = new BuildServer(context.VssConnection);
|
||||||
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
string jobId = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobId).Value ?? string.Empty;
|
||||||
var artifact = await buildHelper.AssociateArtifact(projectId, buildId, jobId, artifactName, ArtifactResourceTypes.Container, fileContainerFullPath, propertiesDictionary, token);
|
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.Output($"Associated artifact {artifactName} ({artifact.Id}) with run #{buildId}");
|
||||||
|
context.Debug($"Associated artifact using v1 endpoint");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
@@ -20,42 +20,4 @@
|
|||||||
<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,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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
@@ -25,42 +25,4 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -122,5 +122,10 @@ 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -9,9 +9,8 @@
|
|||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>RunnerService</RootNamespace>
|
<RootNamespace>RunnerService</RootNamespace>
|
||||||
<AssemblyName>RunnerService</AssemblyName>
|
<AssemblyName>RunnerService</AssemblyName>
|
||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>false</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>FinalPublicKey.snk</AssemblyOriginatorKeyFile>
|
<DelaySign>false</DelaySign>
|
||||||
<DelaySign>true</DelaySign>
|
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
@@ -64,7 +63,6 @@
|
|||||||
</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">
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace GitHub.Runner.Worker
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process action command in serialize oreder.
|
// process action command in serialize order.
|
||||||
lock (_commandSerializeLock)
|
lock (_commandSerializeLock)
|
||||||
{
|
{
|
||||||
if (_stopProcessCommand)
|
if (_stopProcessCommand)
|
||||||
@@ -107,32 +107,19 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension))
|
||||||
{
|
{
|
||||||
bool commandHasBeenOutput = false;
|
if (context.EchoOnActionCommand && !extension.OmitEcho)
|
||||||
|
{
|
||||||
|
context.Output(input);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (context.EchoOnActionCommand)
|
|
||||||
{
|
|
||||||
context.Output(input);
|
|
||||||
context.Debug($"Processing command '{actionCommand.Command}'");
|
|
||||||
commandHasBeenOutput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension.ProcessCommand(context, input, actionCommand);
|
extension.ProcessCommand(context, input, actionCommand);
|
||||||
|
|
||||||
if (context.EchoOnActionCommand)
|
|
||||||
{
|
|
||||||
context.Debug($"Processed command '{actionCommand.Command}' successfully");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (!commandHasBeenOutput)
|
var commandInformation = extension.OmitEcho ? extension.Command : input;
|
||||||
{
|
context.Error($"Unable to process command '{commandInformation}' successfully.");
|
||||||
context.Output(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Error($"Unable to process command '{input}' successfully.");
|
|
||||||
context.Error(ex);
|
context.Error(ex);
|
||||||
context.CommandResult = TaskResult.Failed;
|
context.CommandResult = TaskResult.Failed;
|
||||||
}
|
}
|
||||||
@@ -151,6 +138,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public interface IActionCommandExtension : IExtension
|
public interface IActionCommandExtension : IExtension
|
||||||
{
|
{
|
||||||
string Command { get; }
|
string Command { get; }
|
||||||
|
bool OmitEcho { get; }
|
||||||
|
|
||||||
void ProcessCommand(IExecutionContext context, string line, ActionCommand command);
|
void ProcessCommand(IExecutionContext context, string line, ActionCommand command);
|
||||||
}
|
}
|
||||||
@@ -158,6 +146,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "internal-set-repo-path";
|
public string Command => "internal-set-repo-path";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -187,6 +176,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class SetEnvCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class SetEnvCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "set-env";
|
public string Command => "set-env";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -211,6 +201,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class SetOutputCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class SetOutputCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "set-output";
|
public string Command => "set-output";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -234,6 +225,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class SaveStateCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class SaveStateCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "save-state";
|
public string Command => "save-state";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -257,6 +249,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class AddMaskCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class AddMaskCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "add-mask";
|
public string Command => "add-mask";
|
||||||
|
public bool OmitEcho => true;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -268,6 +261,11 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (context.EchoOnActionCommand)
|
||||||
|
{
|
||||||
|
context.Output($"::{Command}::***");
|
||||||
|
}
|
||||||
|
|
||||||
HostContext.SecretMasker.AddValue(command.Data);
|
HostContext.SecretMasker.AddValue(command.Data);
|
||||||
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
Trace.Info($"Add new secret mask with length of {command.Data.Length}");
|
||||||
}
|
}
|
||||||
@@ -277,6 +275,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class AddPathCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class AddPathCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "add-path";
|
public string Command => "add-path";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -291,6 +290,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class AddMatcherCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class AddMatcherCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "add-matcher";
|
public string Command => "add-matcher";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -337,6 +337,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class RemoveMatcherCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class RemoveMatcherCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "remove-matcher";
|
public string Command => "remove-matcher";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -404,6 +405,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class DebugCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class DebugCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "debug";
|
public string Command => "debug";
|
||||||
|
public bool OmitEcho => true;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -431,11 +433,16 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
public abstract IssueType Type { get; }
|
public abstract IssueType Type { get; }
|
||||||
public abstract string Command { get; }
|
public abstract string Command { get; }
|
||||||
|
public bool OmitEcho => true;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
|
||||||
{
|
{
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
|
||||||
|
command.Properties.TryGetValue(IssueCommandProperties.Column, out string column);
|
||||||
|
|
||||||
Issue issue = new Issue()
|
Issue issue = new Issue()
|
||||||
{
|
{
|
||||||
Category = "General",
|
Category = "General",
|
||||||
@@ -443,8 +450,54 @@ namespace GitHub.Runner.Worker
|
|||||||
Message = command.Data
|
Message = command.Data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(file))
|
||||||
|
{
|
||||||
|
issue.Category = "Code";
|
||||||
|
|
||||||
|
if (context.Container != null)
|
||||||
|
{
|
||||||
|
// Translate file path back from container path
|
||||||
|
file = context.Container.TranslateToHostPath(file);
|
||||||
|
command.Properties[IssueCommandProperties.File] = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the values that represent the server path given a local path
|
||||||
|
string repoName = context.GetGitHubContext("repository");
|
||||||
|
var repoPath = context.GetGitHubContext("workspace");
|
||||||
|
|
||||||
|
string relativeSourcePath = IOUtil.MakeRelative(file, repoPath);
|
||||||
|
if (!string.Equals(relativeSourcePath, file, IOUtil.FilePathStringComparison))
|
||||||
|
{
|
||||||
|
// add repo info
|
||||||
|
if (!string.IsNullOrEmpty(repoName))
|
||||||
|
{
|
||||||
|
command.Properties["repo"] = repoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(relativeSourcePath))
|
||||||
|
{
|
||||||
|
// replace sourcePath with the new relative path
|
||||||
|
// prefer `/` on all platforms
|
||||||
|
command.Properties[IssueCommandProperties.File] = relativeSourcePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var property in command.Properties)
|
||||||
|
{
|
||||||
|
issue.Data[property.Key] = property.Value;
|
||||||
|
}
|
||||||
|
|
||||||
context.AddIssue(issue);
|
context.AddIssue(issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class IssueCommandProperties
|
||||||
|
{
|
||||||
|
public const String File = "file";
|
||||||
|
public const String Line = "line";
|
||||||
|
public const String Column = "col";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class GroupCommandExtension : GroupingCommandExtension
|
public sealed class GroupCommandExtension : GroupingCommandExtension
|
||||||
@@ -460,6 +513,8 @@ namespace GitHub.Runner.Worker
|
|||||||
public abstract class GroupingCommandExtension : RunnerService, IActionCommandExtension
|
public abstract class GroupingCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public abstract string Command { get; }
|
public abstract string Command { get; }
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
|
||||||
@@ -472,6 +527,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class EchoCommandExtension : RunnerService, IActionCommandExtension
|
public sealed class EchoCommandExtension : RunnerService, IActionCommandExtension
|
||||||
{
|
{
|
||||||
public string Command => "echo";
|
public string Command => "echo";
|
||||||
|
public bool OmitEcho => false;
|
||||||
|
|
||||||
public Type ExtensionType => typeof(IActionCommandExtension);
|
public Type ExtensionType => typeof(IActionCommandExtension);
|
||||||
|
|
||||||
@@ -491,7 +547,6 @@ 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
executionContext.Warning("The 'PREVIEW_ACTION_TOKEN' secret is depreciated. Please remove it from the repository's secrets");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the cache (local runner)
|
||||||
|
IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken);
|
||||||
|
|
||||||
foreach (var action in actions)
|
foreach (var action in actions)
|
||||||
{
|
{
|
||||||
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
if (action.Reference.Type == Pipelines.ActionSourceType.ContainerRegistry)
|
||||||
@@ -445,7 +448,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// make sure we get an clean folder ready to use.
|
// make sure we get a clean folder ready to use.
|
||||||
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
IOUtil.DeleteDirectory(destDirectory, executionContext.CancellationToken);
|
||||||
Directory.CreateDirectory(destDirectory);
|
Directory.CreateDirectory(destDirectory);
|
||||||
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'");
|
||||||
|
|||||||
@@ -94,7 +94,21 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
postDisplayName = $"Post {this.DisplayName}";
|
postDisplayName = $"Post {this.DisplayName}";
|
||||||
}
|
}
|
||||||
ExecutionContext.RegisterPostJobAction(postDisplayName, handlerData.CleanupCondition, Action);
|
|
||||||
|
var repositoryReference = Action.Reference as RepositoryPathReference;
|
||||||
|
var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
|
||||||
|
var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
|
||||||
|
$"{repositoryReference.Name}{pathString}@{repositoryReference.Ref}";
|
||||||
|
|
||||||
|
ExecutionContext.Debug($"Register post job cleanup for action: {repoString}");
|
||||||
|
|
||||||
|
var actionRunner = HostContext.CreateService<IActionRunner>();
|
||||||
|
actionRunner.Action = Action;
|
||||||
|
actionRunner.Stage = ActionRunStage.Post;
|
||||||
|
actionRunner.Condition = handlerData.CleanupCondition;
|
||||||
|
actionRunner.DisplayName = postDisplayName;
|
||||||
|
|
||||||
|
ExecutionContext.RegisterPostJobStep($"{actionRunner.Action.Name}_post", actionRunner);
|
||||||
}
|
}
|
||||||
|
|
||||||
IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>();
|
IStepHost stepHost = HostContext.CreateService<IDefaultStepHost>();
|
||||||
|
|||||||
@@ -276,7 +276,9 @@ 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));
|
||||||
|
|
||||||
@@ -337,7 +339,9 @@ 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}");
|
||||||
@@ -362,7 +366,9 @@ 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}");
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using GitHub.Runner.Common;
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -38,6 +39,14 @@ namespace GitHub.Runner.Worker
|
|||||||
List<ContainerInfo> containers = data as List<ContainerInfo>;
|
List<ContainerInfo> containers = data as List<ContainerInfo>;
|
||||||
ArgUtil.NotNull(containers, nameof(containers));
|
ArgUtil.NotNull(containers, nameof(containers));
|
||||||
|
|
||||||
|
var postJobStep = new JobExtensionRunner(runAsync: this.StopContainersAsync,
|
||||||
|
condition: $"{PipelineTemplateConstants.Always}()",
|
||||||
|
displayName: "Stop containers",
|
||||||
|
data: data);
|
||||||
|
|
||||||
|
executionContext.Debug($"Register post job cleanup for stoping/deleting containers.");
|
||||||
|
executionContext.RegisterPostJobStep(nameof(StopContainersAsync), postJobStep);
|
||||||
|
|
||||||
// Check whether we are inside a container.
|
// Check whether we are inside a container.
|
||||||
// Our container feature requires to map working directory from host to the container.
|
// Our container feature requires to map working directory from host to the container.
|
||||||
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
||||||
@@ -48,9 +57,6 @@ 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))
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ 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";
|
||||||
|
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously (method has async logic on only certain platforms)
|
||||||
public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
|
public async Task UploadDiagnosticLogsAsync(IExecutionContext executionContext,
|
||||||
|
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||||
IExecutionContext parentContext,
|
IExecutionContext parentContext,
|
||||||
Pipelines.AgentJobRequestMessage message,
|
Pipelines.AgentJobRequestMessage message,
|
||||||
DateTime jobStartTimeUtc)
|
DateTime jobStartTimeUtc)
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// others
|
// others
|
||||||
void ForceTaskComplete();
|
void ForceTaskComplete();
|
||||||
void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action);
|
void RegisterPostJobStep(string refName, IStep step);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
||||||
@@ -240,27 +240,10 @@ namespace GitHub.Runner.Worker
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterPostJobAction(string displayName, string condition, Pipelines.ActionStep action)
|
public void RegisterPostJobStep(string refName, IStep step)
|
||||||
{
|
{
|
||||||
if (action.Reference.Type != ActionSourceType.Repository)
|
step.ExecutionContext = Root.CreatePostChild(step.DisplayName, refName, IntraActionState);
|
||||||
{
|
Root.PostJobSteps.Push(step);
|
||||||
throw new NotSupportedException("Only action that has `action.yml` can define post job execution.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var repositoryReference = action.Reference as RepositoryPathReference;
|
|
||||||
var pathString = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
|
|
||||||
var repoString = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
|
|
||||||
$"{repositoryReference.Name}{pathString}@{repositoryReference.Ref}";
|
|
||||||
|
|
||||||
this.Debug($"Register post job cleanup for action: {repoString}");
|
|
||||||
|
|
||||||
var actionRunner = HostContext.CreateService<IActionRunner>();
|
|
||||||
actionRunner.Action = action;
|
|
||||||
actionRunner.Stage = ActionRunStage.Post;
|
|
||||||
actionRunner.Condition = condition;
|
|
||||||
actionRunner.DisplayName = displayName;
|
|
||||||
actionRunner.ExecutionContext = Root.CreatePostChild(displayName, $"{actionRunner.Action.Name}_post", IntraActionState);
|
|
||||||
Root.PostJobSteps.Push(actionRunner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null)
|
public IExecutionContext CreateChild(Guid recordId, string displayName, string refName, string scopeName, string contextName, Dictionary<string, string> intraActionState = null, int? recordOrder = null)
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ 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();
|
||||||
|
|||||||
@@ -263,15 +263,17 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
// Root using fromPath
|
// Root using fromPath
|
||||||
if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file))
|
if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file))
|
||||||
{
|
{
|
||||||
file = Path.Combine(match.FromPath, file);
|
var fromDirectory = Path.GetDirectoryName(match.FromPath);
|
||||||
|
if (!string.IsNullOrWhiteSpace(fromDirectory))
|
||||||
|
{
|
||||||
|
file = Path.Combine(fromDirectory, file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root using system.defaultWorkingDirectory
|
// Root using workspace
|
||||||
if (!Path.IsPathRooted(file))
|
if (!Path.IsPathRooted(file))
|
||||||
{
|
{
|
||||||
var githubContext = _executionContext.ExpressionValues["github"] as GitHubContext;
|
var workspace = _executionContext.GetGitHubContext("workspace");
|
||||||
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);
|
||||||
@@ -297,7 +299,7 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// prefer `/` on all platforms
|
// Prefer `/` on all platforms
|
||||||
issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ 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;
|
||||||
@@ -27,6 +28,7 @@ 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();
|
||||||
}
|
}
|
||||||
@@ -37,13 +39,26 @@ 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
|
||||||
@@ -54,7 +69,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
return new IssueMatch(null, pattern, regexMatch.Groups);
|
return new IssueMatch(null, pattern, regexMatch.Groups, DefaultSeverity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -95,7 +110,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return new IssueMatch(runningMatch, pattern, regexMatch.Groups);
|
return new IssueMatch(runningMatch, pattern, regexMatch.Groups, DefaultSeverity);
|
||||||
}
|
}
|
||||||
// Not the last pattern
|
// Not the last pattern
|
||||||
else
|
else
|
||||||
@@ -169,7 +184,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public sealed class IssueMatch
|
public sealed class IssueMatch
|
||||||
{
|
{
|
||||||
public IssueMatch(IssueMatch runningMatch, IssuePattern pattern, GroupCollection groups)
|
public IssueMatch(IssueMatch runningMatch, IssuePattern pattern, GroupCollection groups, string defaultSeverity = null)
|
||||||
{
|
{
|
||||||
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);
|
||||||
@@ -178,6 +193,11 @@ 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; }
|
||||||
@@ -256,6 +276,9 @@ 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;
|
||||||
|
|
||||||
@@ -265,7 +288,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
if (_owner == null)
|
if (_owner == null)
|
||||||
{
|
{
|
||||||
_owner = String.Empty;
|
_owner = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _owner;
|
return _owner;
|
||||||
@@ -277,6 +300,24 @@ 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
|
||||||
@@ -303,6 +344,17 @@ 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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,9 +110,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build up 3 lists of steps, pre-job, job, post-job
|
// Build up 2 lists of steps, pre-job, job
|
||||||
var postJobStepsBuilder = new Stack<IStep>();
|
|
||||||
|
|
||||||
// Download actions not already in the cache
|
// Download actions not already in the cache
|
||||||
Trace.Info("Downloading actions");
|
Trace.Info("Downloading actions");
|
||||||
var actionManager = HostContext.GetService<IActionManager>();
|
var actionManager = HostContext.GetService<IActionManager>();
|
||||||
@@ -134,10 +132,6 @@ namespace GitHub.Runner.Worker
|
|||||||
condition: $"{PipelineTemplateConstants.Success}()",
|
condition: $"{PipelineTemplateConstants.Success}()",
|
||||||
displayName: "Initialize containers",
|
displayName: "Initialize containers",
|
||||||
data: (object)containers));
|
data: (object)containers));
|
||||||
postJobStepsBuilder.Push(new JobExtensionRunner(runAsync: containerProvider.StopContainersAsync,
|
|
||||||
condition: $"{PipelineTemplateConstants.Always}()",
|
|
||||||
displayName: "Stop containers",
|
|
||||||
data: (object)containers));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add action steps
|
// Add action steps
|
||||||
@@ -187,33 +181,9 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add post-job steps
|
|
||||||
Trace.Info("Adding post-job steps");
|
|
||||||
while (postJobStepsBuilder.Count > 0)
|
|
||||||
{
|
|
||||||
postJobSteps.Add(postJobStepsBuilder.Pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create execution context for post-job steps
|
|
||||||
foreach (var step in postJobSteps)
|
|
||||||
{
|
|
||||||
if (step is JobExtensionRunner)
|
|
||||||
{
|
|
||||||
JobExtensionRunner extensionStep = step as JobExtensionRunner;
|
|
||||||
ArgUtil.NotNull(extensionStep, extensionStep.DisplayName);
|
|
||||||
Guid stepId = Guid.NewGuid();
|
|
||||||
extensionStep.ExecutionContext = jobContext.CreateChild(stepId, extensionStep.DisplayName, stepId.ToString("N"), null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IStep> steps = new List<IStep>();
|
List<IStep> steps = new List<IStep>();
|
||||||
steps.AddRange(preJobSteps);
|
steps.AddRange(preJobSteps);
|
||||||
steps.AddRange(jobSteps);
|
steps.AddRange(jobSteps);
|
||||||
steps.AddRange(postJobSteps);
|
|
||||||
|
|
||||||
// Start agent log plugin host process
|
|
||||||
// var logPlugin = HostContext.GetService<IAgentLogPlugin>();
|
|
||||||
// await logPlugin.StartAsync(context, steps, jobContext.CancellationToken);
|
|
||||||
|
|
||||||
// Prepare for orphan process cleanup
|
// Prepare for orphan process cleanup
|
||||||
_processCleanup = jobContext.Variables.GetBoolean("process.clean") ?? true;
|
_processCleanup = jobContext.Variables.GetBoolean("process.clean") ?? true;
|
||||||
|
|||||||
@@ -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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
@@ -35,42 +35,4 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using Minimatch;
|
using Minimatch;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using GitHub.DistributedTask.Expressions2.Sdk;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||||
namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
||||||
@@ -28,29 +29,50 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
string searchRoot = workspaceData.Value;
|
string searchRoot = workspaceData.Value;
|
||||||
string pattern = Parameters[0].Evaluate(context).ConvertToString();
|
string pattern = Parameters[0].Evaluate(context).ConvertToString();
|
||||||
|
|
||||||
|
// Convert slashes on Windows
|
||||||
|
if (s_isWindows)
|
||||||
|
{
|
||||||
|
pattern = pattern.Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root the pattern
|
||||||
|
if (!Path.IsPathRooted(pattern))
|
||||||
|
{
|
||||||
|
var patternRoot = s_isWindows ? searchRoot.Replace('\\', '/').TrimEnd('/') : searchRoot.TrimEnd('/');
|
||||||
|
pattern = string.Concat(patternRoot, "/", pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all files
|
||||||
context.Trace.Info($"Search root directory: '{searchRoot}'");
|
context.Trace.Info($"Search root directory: '{searchRoot}'");
|
||||||
context.Trace.Info($"Search pattern: '{pattern}'");
|
context.Trace.Info($"Search pattern: '{pattern}'");
|
||||||
var files = Directory.GetFiles(searchRoot, "*", SearchOption.AllDirectories).OrderBy(x => x).ToList();
|
var files = Directory.GetFiles(searchRoot, "*", SearchOption.AllDirectories)
|
||||||
|
.Select(x => s_isWindows ? x.Replace('\\', '/') : x)
|
||||||
|
.OrderBy(x => x, StringComparer.Ordinal)
|
||||||
|
.ToList();
|
||||||
if (files.Count == 0)
|
if (files.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"'hashFiles({pattern})' failed. Directory '{searchRoot}' is empty");
|
throw new ArgumentException($"hashFiles('{ExpressionUtility.StringEscape(pattern)}') failed. Directory '{searchRoot}' is empty");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Trace.Info($"Found {files.Count} files");
|
context.Trace.Info($"Found {files.Count} files");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Match
|
||||||
var matcher = new Minimatcher(pattern, s_minimatchOptions);
|
var matcher = new Minimatcher(pattern, s_minimatchOptions);
|
||||||
files = matcher.Filter(files).ToList();
|
files = matcher.Filter(files)
|
||||||
|
.Select(x => s_isWindows ? x.Replace('/', '\\') : x)
|
||||||
|
.ToList();
|
||||||
if (files.Count == 0)
|
if (files.Count == 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"'hashFiles({pattern})' failed. Search pattern '{pattern}' doesn't match any file under '{searchRoot}'");
|
throw new ArgumentException($"hashFiles('{ExpressionUtility.StringEscape(pattern)}') failed. Search pattern '{pattern}' doesn't match any file under '{searchRoot}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Trace.Info($"{files.Count} matches to hash");
|
context.Trace.Info($"{files.Count} matches to hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash each file
|
||||||
List<byte> filesSha256 = new List<byte>();
|
List<byte> filesSha256 = new List<byte>();
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
@@ -64,6 +86,7 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash the hashes
|
||||||
using (SHA256 sha256hash = SHA256.Create())
|
using (SHA256 sha256hash = SHA256.Create())
|
||||||
{
|
{
|
||||||
var hashBytes = sha256hash.ComputeHash(filesSha256.ToArray());
|
var hashBytes = sha256hash.ComputeHash(filesSha256.ToArray());
|
||||||
@@ -83,11 +106,17 @@ namespace GitHub.DistributedTask.Expressions2.Sdk.Functions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly bool s_isWindows = Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX;
|
||||||
|
|
||||||
|
// Only support basic globbing (* ? and []) and globstar (**)
|
||||||
private static readonly Options s_minimatchOptions = new Options
|
private static readonly Options s_minimatchOptions = new Options
|
||||||
{
|
{
|
||||||
Dot = true,
|
Dot = true,
|
||||||
NoBrace = true,
|
NoBrace = true,
|
||||||
NoCase = Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX
|
NoCase = s_isWindows,
|
||||||
|
NoComment = true,
|
||||||
|
NoExt = true,
|
||||||
|
NoNegate = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
44
src/Sdk/PipelinesWebApi/Contracts/ActionsStorageArtifact.cs
Normal file
44
src/Sdk/PipelinesWebApi/Contracts/ActionsStorageArtifact.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[DataContract]
|
||||||
|
public class ActionsStorageArtifact : Artifact
|
||||||
|
{
|
||||||
|
public ActionsStorageArtifact()
|
||||||
|
: base(ArtifactType.Actions_Storage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File Container ID
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public long ContainerId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the file in bytes
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public long Size
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signed content url for downloading the artifact
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public SignedUrl SignedContent
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/Sdk/PipelinesWebApi/Contracts/Artifact.cs
Normal file
46
src/Sdk/PipelinesWebApi/Contracts/Artifact.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Actions.Pipelines.WebApi.Contracts;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[DataContract]
|
||||||
|
[KnownType(typeof(ActionsStorageArtifact))]
|
||||||
|
[JsonConverter(typeof(ArtifactJsonConverter))]
|
||||||
|
public class Artifact
|
||||||
|
{
|
||||||
|
public Artifact(ArtifactType type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the artifact.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public ArtifactType Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the artifact.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Self-referential url
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public string Url
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public abstract class ArtifactBaseJsonConverter<T> : VssSecureJsonConverter where T : class
|
||||||
|
{
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return typeof(T).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
// by returning false, the converter doesn't take part in writes
|
||||||
|
// which means we use the default serialization logic
|
||||||
|
public override bool CanWrite
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T Create(Type objectType);
|
||||||
|
|
||||||
|
protected abstract T Create(ArtifactType type);
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object existingValue,
|
||||||
|
JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonToken.StartObject)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract;
|
||||||
|
if (contract == null)
|
||||||
|
{
|
||||||
|
return existingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if objectType is one of our known types, we can ignore the type property
|
||||||
|
T targetObject = Create(objectType);
|
||||||
|
|
||||||
|
// read the data into a JObject so we can look at it
|
||||||
|
var value = JObject.Load(reader);
|
||||||
|
|
||||||
|
if (targetObject == null)
|
||||||
|
{
|
||||||
|
// use the Type property
|
||||||
|
var typeProperty = contract.Properties.GetClosestMatchProperty("Type");
|
||||||
|
if (typeProperty == null)
|
||||||
|
{
|
||||||
|
// we don't know the type. just bail
|
||||||
|
return existingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value.TryGetValue(typeProperty.PropertyName, StringComparison.OrdinalIgnoreCase, out var typeValue))
|
||||||
|
{
|
||||||
|
// a type property exists on the contract, but the JObject has no value for it
|
||||||
|
return existingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = UnknownEnum.Parse<ArtifactType>(typeValue.ToString());
|
||||||
|
targetObject = Create(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetObject != null)
|
||||||
|
{
|
||||||
|
using (var objectReader = value.CreateReader())
|
||||||
|
{
|
||||||
|
serializer.Populate(objectReader, targetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/Sdk/PipelinesWebApi/Contracts/ArtifactJsonConverter.cs
Normal file
29
src/Sdk/PipelinesWebApi/Contracts/ArtifactJsonConverter.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi.Contracts
|
||||||
|
{
|
||||||
|
public class ArtifactJsonConverter : ArtifactBaseJsonConverter<Artifact>
|
||||||
|
{
|
||||||
|
protected override Artifact Create(Type objectType)
|
||||||
|
{
|
||||||
|
if (objectType == typeof(ActionsStorageArtifact))
|
||||||
|
{
|
||||||
|
return new ActionsStorageArtifact();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Artifact Create(ArtifactType type)
|
||||||
|
{
|
||||||
|
if (type == ArtifactType.Actions_Storage)
|
||||||
|
{
|
||||||
|
return new ActionsStorageArtifact();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/Sdk/PipelinesWebApi/Contracts/ArtifactType.cs
Normal file
14
src/Sdk/PipelinesWebApi/Contracts/ArtifactType.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[DataContract]
|
||||||
|
[JsonConverter(typeof(ArtifactTypeEnumJsonConverter))]
|
||||||
|
public enum ArtifactType
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Actions_Storage = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http.Formatting;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public class ArtifactTypeEnumJsonConverter : UnknownEnumJsonConverter
|
||||||
|
{
|
||||||
|
//json.net v12 exposes a "NamingStrategy" member that can do all this. We are at json.net v10 which only supports camel case.
|
||||||
|
//This is a poor man's way to fake it
|
||||||
|
public override void WriteJson(JsonWriter writer, object enumValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
var value = (ArtifactType)enumValue;
|
||||||
|
if (value == ArtifactType.Actions_Storage)
|
||||||
|
{
|
||||||
|
writer.WriteValue("actions_storage");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.WriteJson(writer, enumValue, serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[DataContract]
|
||||||
|
public class CreateActionsStorageArtifactParameters : CreateArtifactParameters
|
||||||
|
{
|
||||||
|
public CreateActionsStorageArtifactParameters()
|
||||||
|
: base(ArtifactType.Actions_Storage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the id of the file container
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public long ContainerId
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the file in bytes
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public long Size
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[DataContract]
|
||||||
|
[KnownType(typeof(CreateActionsStorageArtifactParameters))]
|
||||||
|
[JsonConverter(typeof(CreateArtifactParametersJsonConverter))]
|
||||||
|
public class CreateArtifactParameters
|
||||||
|
{
|
||||||
|
protected CreateArtifactParameters(ArtifactType type)
|
||||||
|
{
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the artifact.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public ArtifactType Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the artifact.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public class CreateArtifactParametersJsonConverter : ArtifactBaseJsonConverter<CreateArtifactParameters>
|
||||||
|
{
|
||||||
|
protected override CreateArtifactParameters Create(Type objectType)
|
||||||
|
{
|
||||||
|
if (objectType == typeof(CreateActionsStorageArtifactParameters))
|
||||||
|
{
|
||||||
|
return new CreateActionsStorageArtifactParameters();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override CreateArtifactParameters Create(ArtifactType type)
|
||||||
|
{
|
||||||
|
if (type == ArtifactType.Actions_Storage)
|
||||||
|
{
|
||||||
|
return new CreateActionsStorageArtifactParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// $expand options for GetArtifact and ListArtifacts.
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(KnownFlagsEnumTypeConverter))]
|
||||||
|
[Flags]
|
||||||
|
public enum GetArtifactExpandOptions
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
SignedContent = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
105
src/Sdk/PipelinesWebApi/FlagsEnum.cs
Normal file
105
src/Sdk/PipelinesWebApi/FlagsEnum.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public static class FlagsEnum
|
||||||
|
{
|
||||||
|
public static TEnum ParseKnownFlags<TEnum>(string stringValue) where TEnum : System.Enum
|
||||||
|
{
|
||||||
|
return (TEnum)ParseKnownFlags(typeof(TEnum), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse known enum flags in a comma-separated string. Unknown flags are ignored. Allows for degraded compatibility without serializing enums to integers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Case insensitive. Both standard and EnumMemberAttribute names are parsed.
|
||||||
|
/// </remarks>
|
||||||
|
/// <exception cref="NullReferenceException">Thrown if stringValue is null.</exception>
|
||||||
|
/// <exception cref="ArgumentException">Thrown if a flag name is empty.</exception>
|
||||||
|
public static object ParseKnownFlags(Type enumType, string stringValue)
|
||||||
|
{
|
||||||
|
ArgumentUtility.CheckForNull(enumType, nameof(enumType));
|
||||||
|
if (!enumType.IsEnum)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(PipelinesWebApiResources.FlagEnumTypeRequired());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the flags attribute in debug. Skip this reflection in release.
|
||||||
|
Debug.Assert(enumType.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any(), "FlagsEnum only intended for enums with the Flags attribute.");
|
||||||
|
|
||||||
|
// The exception types below are based on Enum.TryParseEnum (http://index/?query=TryParseEnum&rightProject=mscorlib&file=system%5Cenum.cs&rightSymbol=bhaeh2vnegwo)
|
||||||
|
if (stringValue == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrWhiteSpace(stringValue))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(PipelinesWebApiResources.NonEmptyEnumElementsRequired(stringValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UInt64.TryParse(stringValue, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out ulong ulongValue))
|
||||||
|
{
|
||||||
|
return Enum.Parse(enumType, stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumNames = Enum.GetNames(enumType).ToHashSet(name => name, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var enumMemberMappings = new Lazy<IDictionary<string, string>>(() =>
|
||||||
|
{
|
||||||
|
IDictionary<string, string> mappings = null;
|
||||||
|
foreach (var field in enumType.GetFields())
|
||||||
|
{
|
||||||
|
if (field.GetCustomAttributes(typeof(EnumMemberAttribute), false).FirstOrDefault() is EnumMemberAttribute enumMemberAttribute)
|
||||||
|
{
|
||||||
|
if (mappings == null)
|
||||||
|
{
|
||||||
|
mappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
mappings.Add(enumMemberAttribute.Value, field.GetValue(null).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappings;
|
||||||
|
});
|
||||||
|
|
||||||
|
var values = stringValue.Split(s_enumSeparatorCharArray);
|
||||||
|
|
||||||
|
var matches = new List<string>();
|
||||||
|
for (int i = 0; i < values.Length; i++)
|
||||||
|
{
|
||||||
|
string value = values[i].Trim();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(PipelinesWebApiResources.NonEmptyEnumElementsRequired(stringValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enumNames.Contains(value))
|
||||||
|
{
|
||||||
|
matches.Add(value);
|
||||||
|
}
|
||||||
|
else if (enumMemberMappings.Value != null && enumMemberMappings.Value.TryGetValue(value, out string matchingValue))
|
||||||
|
{
|
||||||
|
matches.Add(matchingValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matches.Any())
|
||||||
|
{
|
||||||
|
return Enum.Parse(enumType, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
string matchesString = String.Join(", ", matches);
|
||||||
|
return Enum.Parse(enumType, matchesString, ignoreCase: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly char[] s_enumSeparatorCharArray = new char[] { ',' };
|
||||||
|
}
|
||||||
|
}
|
||||||
273
src/Sdk/PipelinesWebApi/Generated/PipelinesHttpClientBase.cs
Normal file
273
src/Sdk/PipelinesWebApi/Generated/PipelinesHttpClientBase.cs
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
* Copyright(C) Microsoft Corporation. All rights reserved.
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
* Generated file, DO NOT EDIT
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
*
|
||||||
|
* See following wiki page for instructions on how to regenerate:
|
||||||
|
* https://aka.ms/azure-devops-client-generation
|
||||||
|
*
|
||||||
|
* Configuration file:
|
||||||
|
* actions\client\webapi\clientgeneratorconfigs\pipelines.genclient.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Formatting;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[ResourceArea(PipelinesArea.IdString)]
|
||||||
|
public abstract class PipelinesHttpClientBase : VssHttpClientBase
|
||||||
|
{
|
||||||
|
public PipelinesHttpClientBase(Uri baseUrl, VssCredentials credentials)
|
||||||
|
: base(baseUrl, credentials)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClientBase(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings)
|
||||||
|
: base(baseUrl, credentials, settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClientBase(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers)
|
||||||
|
: base(baseUrl, credentials, handlers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClientBase(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers)
|
||||||
|
: base(baseUrl, credentials, settings, handlers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClientBase(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler)
|
||||||
|
: base(baseUrl, pipeline, disposeHandler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Associates an artifact with a run.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="createArtifactParameters"></param>
|
||||||
|
/// <param name="pipelineId">The ID of the pipeline.</param>
|
||||||
|
/// <param name="runId">The ID of the run.</param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> CreateArtifactAsync(
|
||||||
|
CreateArtifactParameters createArtifactParameters,
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("POST");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { pipelineId = pipelineId, runId = runId };
|
||||||
|
HttpContent content = new ObjectContent<CreateArtifactParameters>(createArtifactParameters, new VssJsonMediaTypeFormatter(true));
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken,
|
||||||
|
content: content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Associates an artifact with a run.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="createArtifactParameters"></param>
|
||||||
|
/// <param name="project">Project ID or project name</param>
|
||||||
|
/// <param name="pipelineId">The ID of the pipeline.</param>
|
||||||
|
/// <param name="runId">The ID of the run.</param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> CreateArtifactAsync(
|
||||||
|
CreateArtifactParameters createArtifactParameters,
|
||||||
|
string project,
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("POST");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { project = project, pipelineId = pipelineId, runId = runId };
|
||||||
|
HttpContent content = new ObjectContent<CreateArtifactParameters>(createArtifactParameters, new VssJsonMediaTypeFormatter(true));
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken,
|
||||||
|
content: content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Associates an artifact with a run.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="createArtifactParameters"></param>
|
||||||
|
/// <param name="project">Project ID</param>
|
||||||
|
/// <param name="pipelineId">The ID of the pipeline.</param>
|
||||||
|
/// <param name="runId">The ID of the run.</param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> CreateArtifactAsync(
|
||||||
|
CreateArtifactParameters createArtifactParameters,
|
||||||
|
Guid project,
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("POST");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { project = project, pipelineId = pipelineId, runId = runId };
|
||||||
|
HttpContent content = new ObjectContent<CreateArtifactParameters>(createArtifactParameters, new VssJsonMediaTypeFormatter(true));
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken,
|
||||||
|
content: content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Get a specific artifact
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="project">Project ID or project name</param>
|
||||||
|
/// <param name="pipelineId"></param>
|
||||||
|
/// <param name="runId"></param>
|
||||||
|
/// <param name="artifactName"></param>
|
||||||
|
/// <param name="expand"></param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> GetArtifactAsync(
|
||||||
|
string project,
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
string artifactName,
|
||||||
|
GetArtifactExpandOptions? expand = null,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("GET");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { project = project, pipelineId = pipelineId, runId = runId };
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
|
queryParams.Add("artifactName", artifactName);
|
||||||
|
if (expand != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("$expand", expand.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
queryParameters: queryParams,
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Get a specific artifact
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="project">Project ID</param>
|
||||||
|
/// <param name="pipelineId"></param>
|
||||||
|
/// <param name="runId"></param>
|
||||||
|
/// <param name="artifactName"></param>
|
||||||
|
/// <param name="expand"></param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> GetArtifactAsync(
|
||||||
|
Guid project,
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
string artifactName,
|
||||||
|
GetArtifactExpandOptions? expand = null,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("GET");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { project = project, pipelineId = pipelineId, runId = runId };
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
|
queryParams.Add("artifactName", artifactName);
|
||||||
|
if (expand != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("$expand", expand.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
queryParameters: queryParams,
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API] Get a specific artifact
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pipelineId"></param>
|
||||||
|
/// <param name="runId"></param>
|
||||||
|
/// <param name="artifactName"></param>
|
||||||
|
/// <param name="expand"></param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
public virtual Task<Artifact> GetArtifactAsync(
|
||||||
|
int pipelineId,
|
||||||
|
int runId,
|
||||||
|
string artifactName,
|
||||||
|
GetArtifactExpandOptions? expand = null,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("GET");
|
||||||
|
Guid locationId = new Guid("85023071-bd5e-4438-89b0-2a5bf362a19d");
|
||||||
|
object routeValues = new { pipelineId = pipelineId, runId = runId };
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
|
queryParams.Add("artifactName", artifactName);
|
||||||
|
if (expand != null)
|
||||||
|
{
|
||||||
|
queryParams.Add("$expand", expand.Value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SendAsync<Artifact>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
routeValues: routeValues,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
queryParameters: queryParams,
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/Sdk/PipelinesWebApi/KnownFlagsEnumTypeConverter.cs
Normal file
44
src/Sdk/PipelinesWebApi/KnownFlagsEnumTypeConverter.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Parses known enum flags in a comma-separated string. Unknown flags are ignored. Allows for degraded compatibility without serializing enums to integer values.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Case insensitive. Both standard and EnumMemberAttribute names are parsed.
|
||||||
|
/// json deserialization doesn't happen for query parameters :)
|
||||||
|
/// </remarks>
|
||||||
|
public class KnownFlagsEnumTypeConverter : EnumConverter
|
||||||
|
{
|
||||||
|
public KnownFlagsEnumTypeConverter(Type type)
|
||||||
|
: base(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||||
|
{
|
||||||
|
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <exception cref="FormatException">Thrown if a flag name is empty.</exception>
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is string stringValue)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return FlagsEnum.ParseKnownFlags(EnumType, stringValue);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Matches the exception type thrown by EnumTypeConverter.
|
||||||
|
throw new FormatException(PipelinesWebApiResources.InvalidFlagsEnumValue(stringValue, EnumType), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/Sdk/PipelinesWebApi/PipelinesHttpClient.cs
Normal file
36
src/Sdk/PipelinesWebApi/PipelinesHttpClient.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
[ResourceArea(PipelinesArea.IdString)]
|
||||||
|
public class PipelinesHttpClient : PipelinesHttpClientBase
|
||||||
|
{
|
||||||
|
public PipelinesHttpClient(Uri baseUrl, VssCredentials credentials)
|
||||||
|
: base(baseUrl, credentials)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings)
|
||||||
|
: base(baseUrl, credentials, settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClient(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers)
|
||||||
|
: base(baseUrl, credentials, handlers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers)
|
||||||
|
: base(baseUrl, credentials, settings, handlers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipelinesHttpClient(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler)
|
||||||
|
: base(baseUrl, pipeline, disposeHandler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/Sdk/PipelinesWebApi/PipelinesResourceIds.cs
Normal file
74
src/Sdk/PipelinesWebApi/PipelinesResourceIds.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public static class PipelinesArea
|
||||||
|
{
|
||||||
|
public const string Name = "pipelines";
|
||||||
|
public const string IdString = "2e0bf237-8973-4ec9-a581-9c3d679d1776";
|
||||||
|
public static readonly Guid Id = new Guid(PipelinesArea.IdString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PipelinesResources
|
||||||
|
{
|
||||||
|
public static class Artifacts
|
||||||
|
{
|
||||||
|
public const string Name = "artifacts";
|
||||||
|
public static readonly Guid Id = new Guid("85023071-BD5E-4438-89B0-2A5BF362A19D");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PipelineOrgs
|
||||||
|
{
|
||||||
|
public const string Name = "orgs";
|
||||||
|
public static readonly Guid Id = new Guid("CD70BA1A-D59A-4E0B-9934-97998159CCC8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Logs
|
||||||
|
{
|
||||||
|
public const string Name = "logs";
|
||||||
|
public static readonly Guid Id = new Guid("fb1b6d27-3957-43d5-a14b-a2d70403e545");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Pipelines
|
||||||
|
{
|
||||||
|
public const string Name = "pipelines";
|
||||||
|
public static readonly Guid Id = new Guid("28e1305e-2afe-47bf-abaf-cbb0e6a91988");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Reputations
|
||||||
|
{
|
||||||
|
public const string Name = "reputations";
|
||||||
|
public static readonly Guid Id = new Guid("ABA353B0-46FB-4885-88C5-391C6B6382B3");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Runs
|
||||||
|
{
|
||||||
|
public const string Name = "runs";
|
||||||
|
public static readonly Guid Id = new Guid("7859261e-d2e9-4a68-b820-a5d84cc5bb3d");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SignalR
|
||||||
|
{
|
||||||
|
public const string Name = "signalr";
|
||||||
|
public static readonly Guid Id = new Guid("1FFE4916-AC72-4566-ADD0-9BAB31E44FCF");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SignedArtifactsContent
|
||||||
|
{
|
||||||
|
public const string Name = "signedartifactscontent";
|
||||||
|
public static readonly Guid Id = new Guid("6B2AC16F-CD00-4DF9-A13B-3A1CC8AFB188");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SignedLogContent
|
||||||
|
{
|
||||||
|
public const string Name = "signedlogcontent";
|
||||||
|
public static readonly Guid Id = new Guid("74f99e32-e2c4-44f4-93dc-dec0bca530a5");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SignalRLive
|
||||||
|
{
|
||||||
|
public const string Name = "live";
|
||||||
|
public static readonly Guid Id = new Guid("C41B3775-6D50-48BD-B261-42DA7F0F1BA0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/Sdk/PipelinesWebApi/UnknownEnum.cs
Normal file
45
src/Sdk/PipelinesWebApi/UnknownEnum.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public static class UnknownEnum
|
||||||
|
{
|
||||||
|
public static T Parse<T>(string stringValue)
|
||||||
|
{
|
||||||
|
return (T)Parse(typeof(T), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object Parse(Type enumType, string stringValue)
|
||||||
|
{
|
||||||
|
var underlyingType = Nullable.GetUnderlyingType(enumType);
|
||||||
|
enumType = underlyingType != null ? underlyingType : enumType;
|
||||||
|
|
||||||
|
var names = Enum.GetNames(enumType);
|
||||||
|
if (!string.IsNullOrEmpty(stringValue))
|
||||||
|
{
|
||||||
|
var match = names.FirstOrDefault(name => string.Equals(name, stringValue, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
return Enum.Parse(enumType, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybe we have an enum member with an EnumMember attribute specifying a custom name
|
||||||
|
foreach (var field in enumType.GetFields())
|
||||||
|
{
|
||||||
|
var enumMemberAttribute = field.GetCustomAttributes(typeof(EnumMemberAttribute), false).FirstOrDefault() as EnumMemberAttribute;
|
||||||
|
if (enumMemberAttribute != null && string.Equals(enumMemberAttribute.Value, stringValue, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// we already have the field, no need to do enum.parse on it
|
||||||
|
return field.GetValue(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enum.Parse(enumType, UnknownName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string UnknownName = "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/Sdk/PipelinesWebApi/UnknownEnumJsonConverter.cs
Normal file
53
src/Sdk/PipelinesWebApi/UnknownEnumJsonConverter.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public class UnknownEnumJsonConverter : StringEnumConverter
|
||||||
|
{
|
||||||
|
public UnknownEnumJsonConverter()
|
||||||
|
{
|
||||||
|
this.CamelCaseText = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
// we require one member to be named "Unknown"
|
||||||
|
return objectType.IsEnum && Enum.GetNames(objectType).Any(name => string.Equals(name, UnknownName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
// Newtonsoft doesn't call CanConvert if you specify the converter using a JsonConverter attribute
|
||||||
|
// they just assume you know what you're doing :)
|
||||||
|
if (!CanConvert(objectType))
|
||||||
|
{
|
||||||
|
// if there's no Unknown value, fall back to the StringEnumConverter behavior
|
||||||
|
return base.ReadJson(reader, objectType, existingValue, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonToken.Integer)
|
||||||
|
{
|
||||||
|
var intValue = Convert.ToInt32(reader.Value);
|
||||||
|
var values = (int[])Enum.GetValues(objectType);
|
||||||
|
if (values.Contains(intValue))
|
||||||
|
{
|
||||||
|
return Enum.Parse(objectType, intValue.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonToken.String)
|
||||||
|
{
|
||||||
|
var stringValue = reader.Value.ToString();
|
||||||
|
return UnknownEnum.Parse(objectType, stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we know there's an Unknown value because CanConvert returned true
|
||||||
|
return Enum.Parse(objectType, UnknownName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string UnknownName = "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/Sdk/Resources/PipelinesWebApiResources.g.cs
Normal file
26
src/Sdk/Resources/PipelinesWebApiResources.g.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace GitHub.Actions.Pipelines.WebApi
|
||||||
|
{
|
||||||
|
public static class PipelinesWebApiResources
|
||||||
|
{
|
||||||
|
|
||||||
|
public static string FlagEnumTypeRequired()
|
||||||
|
{
|
||||||
|
const string Format = @"Invalid type. An enum type with the Flags attribute must be supplied.";
|
||||||
|
return Format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string InvalidFlagsEnumValue(object arg0, object arg1)
|
||||||
|
{
|
||||||
|
const string Format = @"'{0}' is not a valid value for {1}";
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, Format, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string NonEmptyEnumElementsRequired(object arg0)
|
||||||
|
{
|
||||||
|
const string Format = @"Each comma separated enum value must be non-empty: {0}";
|
||||||
|
return string.Format(CultureInfo.CurrentCulture, Format, arg0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;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>
|
||||||
|
|||||||
18
src/Sdk/WebApi/WebApi/Contracts/SignedUrl/SignedUrl.cs
Normal file
18
src/Sdk/WebApi/WebApi/Contracts/SignedUrl/SignedUrl.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace GitHub.Services.WebApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A signed url allowing limited-time anonymous access to private resources.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class SignedUrl
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public DateTime SignatureExpires { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,8 +47,8 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(hc.SecretMasker.MaskSecrets("secret value 1"), "***");
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("secret value 1"));
|
||||||
Assert.Equal(hc.SecretMasker.MaskSecrets("secret value 2"), "***");
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("secret value 2"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +90,9 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
trace.Info("Args: {0}", clp.Args.Count);
|
trace.Info("Args: {0}", clp.Args.Count);
|
||||||
Assert.True(clp.Args.Count == 2);
|
Assert.True(clp.Args.Count == 2);
|
||||||
Assert.True(clp.Args.ContainsKey("arg1"));
|
Assert.True(clp.Args.ContainsKey("arg1"));
|
||||||
Assert.Equal(clp.Args["arg1"], "arg1val");
|
Assert.Equal("arg1val", clp.Args["arg1"]);
|
||||||
Assert.True(clp.Args.ContainsKey("arg2"));
|
Assert.True(clp.Args.ContainsKey("arg2"));
|
||||||
Assert.Equal(clp.Args["arg2"], "arg2val");
|
Assert.Equal("arg2val", clp.Args["arg2"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,8 +113,8 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
|
|
||||||
trace.Info("Args: {0}", clp.Flags.Count);
|
trace.Info("Args: {0}", clp.Flags.Count);
|
||||||
Assert.True(clp.Flags.Count == 2);
|
Assert.True(clp.Flags.Count == 2);
|
||||||
Assert.True(clp.Flags.Contains("flag1"));
|
Assert.Contains("flag1", clp.Flags);
|
||||||
Assert.True(clp.Flags.Contains("flag2"));
|
Assert.Contains("flag2", clp.Flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
"win-x86",
|
"win-x86",
|
||||||
"linux-x64",
|
"linux-x64",
|
||||||
"linux-arm",
|
"linux-arm",
|
||||||
"rhel.6-x64",
|
"linux-arm64",
|
||||||
"osx-x64"
|
"osx-x64"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(result0);
|
Assert.NotNull(result0);
|
||||||
Assert.Equal(result0.Count, 0);
|
Assert.Equal(0, result0.Count);
|
||||||
|
|
||||||
Assert.NotNull(result1);
|
Assert.NotNull(result1);
|
||||||
Assert.Equal(result1.Count, 1);
|
Assert.Equal(1, result1.Count);
|
||||||
var result1Port80Mapping = result1.Find(pm =>
|
var result1Port80Mapping = result1.Find(pm =>
|
||||||
string.Equals(pm.ContainerPort, "80") &&
|
string.Equals(pm.ContainerPort, "80") &&
|
||||||
string.Equals(pm.HostPort, "32881") &&
|
string.Equals(pm.HostPort, "32881") &&
|
||||||
@@ -48,10 +48,10 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
|
|||||||
Assert.NotNull(result1Port80Mapping);
|
Assert.NotNull(result1Port80Mapping);
|
||||||
|
|
||||||
Assert.NotNull(result1Empty);
|
Assert.NotNull(result1Empty);
|
||||||
Assert.Equal(result1Empty.Count, 0);
|
Assert.Equal(0, result1Empty.Count);
|
||||||
|
|
||||||
Assert.NotNull(result2);
|
Assert.NotNull(result2);
|
||||||
Assert.Equal(result2.Count, 2);
|
Assert.Equal(2, result2.Count);
|
||||||
var result2Port80Mapping = result2.Find(pm =>
|
var result2Port80Mapping = result2.Find(pm =>
|
||||||
string.Equals(pm.ContainerPort, "80") &&
|
string.Equals(pm.ContainerPort, "80") &&
|
||||||
string.Equals(pm.HostPort, "32881") &&
|
string.Equals(pm.HostPort, "32881") &&
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Setup([CallerMemberName] string testName = "")
|
private void Setup([CallerMemberName] string testName = "")
|
||||||
{
|
{
|
||||||
_tokenSource = new CancellationTokenSource();
|
_tokenSource = new CancellationTokenSource();
|
||||||
_hc = new HostContext(
|
_hc = new HostContext(
|
||||||
@@ -115,7 +115,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
logFile: Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"trace_{nameof(HostContextL0)}_{testName}.log"));
|
logFile: Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"trace_{nameof(HostContextL0)}_{testName}.log"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Teardown()
|
private void Teardown()
|
||||||
{
|
{
|
||||||
_hc?.Dispose();
|
_hc?.Dispose();
|
||||||
_tokenSource?.Dispose();
|
_tokenSource?.Dispose();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal("some agent", actual);
|
Assert.Equal("some agent", actual);
|
||||||
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_AGENT") ?? string.Empty); // Should remove.
|
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_AGENT") ?? string.Empty); // Should remove.
|
||||||
Assert.Equal(hc.SecretMasker.MaskSecrets("some agent"), "some agent");
|
Assert.Equal("some agent", hc.SecretMasker.MaskSecrets("some agent"));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal("some secret token value", actual);
|
Assert.Equal("some secret token value", actual);
|
||||||
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_TOKEN") ?? string.Empty); // Should remove.
|
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_TOKEN") ?? string.Empty); // Should remove.
|
||||||
Assert.Equal(hc.SecretMasker.MaskSecrets("some secret token value"), "***");
|
Assert.Equal("***", hc.SecretMasker.MaskSecrets("some secret token value"));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -250,7 +250,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
bool actual = command.Unattended;
|
bool actual = command.Unattended;
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(true, actual);
|
Assert.True(actual);
|
||||||
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_UNATTENDED") ?? string.Empty); // Should remove.
|
Assert.Equal(string.Empty, Environment.GetEnvironmentVariable("ACTIONS_RUNNER_INPUT_UNATTENDED") ?? string.Empty); // Should remove.
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -720,7 +720,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
var command = new CommandSettings(hc, args: new string[] { "badcommand" });
|
var command = new CommandSettings(hc, args: new string[] { "badcommand" });
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.True(command.Validate().Contains("badcommand"));
|
Assert.Contains("badcommand", command.Validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,7 +735,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
var command = new CommandSettings(hc, args: new string[] { "--badflag" });
|
var command = new CommandSettings(hc, args: new string[] { "--badflag" });
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.True(command.Validate().Contains("badflag"));
|
Assert.Contains("badflag", command.Validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -750,7 +750,7 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" });
|
var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" });
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.True(command.Validate().Contains("badargname"));
|
Assert.Contains("badargname", command.Validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
|
|||||||
private string _expectedServerUrl = "https://localhost";
|
private string _expectedServerUrl = "https://localhost";
|
||||||
private string _expectedAgentName = "expectedAgentName";
|
private string _expectedAgentName = "expectedAgentName";
|
||||||
private string _expectedPoolName = "poolName";
|
private string _expectedPoolName = "poolName";
|
||||||
private string _expectedCollectionName = "testCollectionName";
|
|
||||||
private string _expectedProjectName = "testProjectName";
|
|
||||||
private string _expectedProjectId = "edf3f94e-d251-49df-bfce-602d6c967409";
|
|
||||||
private string _expectedMachineGroupName = "testMachineGroupName";
|
|
||||||
private string _expectedAuthType = "pat";
|
private string _expectedAuthType = "pat";
|
||||||
private string _expectedWorkFolder = "_work";
|
private string _expectedWorkFolder = "_work";
|
||||||
private int _expectedPoolId = 1;
|
private int _expectedPoolId = 1;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
string line;
|
string line;
|
||||||
while ((line = freader.ReadLine()) != null)
|
while ((line = freader.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
Assert.True(line.EndsWith(LogData));
|
Assert.EndsWith(LogData, line);
|
||||||
bytesWritten += logDataSize;
|
bytesWritten += logDataSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
175
src/Test/L0/ServiceControlManagerL0.cs
Normal file
175
src/Test/L0/ServiceControlManagerL0.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using GitHub.Runner.Common;
|
||||||
|
using GitHub.Runner.Listener.Configuration;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common.Tests
|
||||||
|
{
|
||||||
|
public sealed class ServiceControlManagerL0
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Service")]
|
||||||
|
public void CalculateServiceName()
|
||||||
|
{
|
||||||
|
RunnerSettings settings = new RunnerSettings();
|
||||||
|
|
||||||
|
settings.AgentName = "thisiskindofalongrunnername1";
|
||||||
|
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
|
||||||
|
settings.GitHubUrl = "https://github.com/myorganizationexample/myrepoexample";
|
||||||
|
|
||||||
|
string serviceNamePattern = "actions.runner.{0}.{1}";
|
||||||
|
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
|
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
ServiceControlManager scm = new ServiceControlManager();
|
||||||
|
|
||||||
|
scm.Initialize(hc);
|
||||||
|
scm.CalculateServiceName(
|
||||||
|
settings,
|
||||||
|
serviceNamePattern,
|
||||||
|
serviceDisplayNamePattern,
|
||||||
|
out string serviceName,
|
||||||
|
out string serviceDisplayName);
|
||||||
|
|
||||||
|
var serviceNameParts = serviceName.Split('.');
|
||||||
|
|
||||||
|
// Verify name is 79 characters
|
||||||
|
Assert.Equal(79, serviceName.Length);
|
||||||
|
|
||||||
|
// Verify nothing has been shortened out
|
||||||
|
Assert.Equal("actions", serviceNameParts[0]);
|
||||||
|
Assert.Equal("runner", serviceNameParts[1]);
|
||||||
|
Assert.Equal("myorganizationexample-myrepoexample", serviceNameParts[2]); // '/' has been replaced with '-'
|
||||||
|
Assert.Equal("thisiskindofalongrunnername1", serviceNameParts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Service")]
|
||||||
|
public void CalculateServiceName80Chars()
|
||||||
|
{
|
||||||
|
RunnerSettings settings = new RunnerSettings();
|
||||||
|
|
||||||
|
settings.AgentName = "thisiskindofalongrunnername12";
|
||||||
|
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
|
||||||
|
settings.GitHubUrl = "https://github.com/myorganizationexample/myrepoexample";
|
||||||
|
|
||||||
|
string serviceNamePattern = "actions.runner.{0}.{1}";
|
||||||
|
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
|
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
ServiceControlManager scm = new ServiceControlManager();
|
||||||
|
|
||||||
|
scm.Initialize(hc);
|
||||||
|
scm.CalculateServiceName(
|
||||||
|
settings,
|
||||||
|
serviceNamePattern,
|
||||||
|
serviceDisplayNamePattern,
|
||||||
|
out string serviceName,
|
||||||
|
out string serviceDisplayName);
|
||||||
|
|
||||||
|
// Verify name is still equal to 80 characters
|
||||||
|
Assert.Equal(80, serviceName.Length);
|
||||||
|
|
||||||
|
var serviceNameParts = serviceName.Split('.');
|
||||||
|
|
||||||
|
// Verify nothing has been shortened out
|
||||||
|
Assert.Equal("actions", serviceNameParts[0]);
|
||||||
|
Assert.Equal("runner", serviceNameParts[1]);
|
||||||
|
Assert.Equal("myorganizationexample-myrepoexample", serviceNameParts[2]); // '/' has been replaced with '-'
|
||||||
|
Assert.Equal("thisiskindofalongrunnername12", serviceNameParts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Service")]
|
||||||
|
public void CalculateServiceNameLimitsServiceNameTo80Chars()
|
||||||
|
{
|
||||||
|
RunnerSettings settings = new RunnerSettings();
|
||||||
|
|
||||||
|
settings.AgentName = "thisisareallyreallylongbutstillvalidagentname";
|
||||||
|
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
|
||||||
|
settings.GitHubUrl = "https://github.com/myreallylongorganizationexample/myreallylongrepoexample";
|
||||||
|
|
||||||
|
string serviceNamePattern = "actions.runner.{0}.{1}";
|
||||||
|
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
|
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
ServiceControlManager scm = new ServiceControlManager();
|
||||||
|
|
||||||
|
scm.Initialize(hc);
|
||||||
|
scm.CalculateServiceName(
|
||||||
|
settings,
|
||||||
|
serviceNamePattern,
|
||||||
|
serviceDisplayNamePattern,
|
||||||
|
out string serviceName,
|
||||||
|
out string serviceDisplayName);
|
||||||
|
|
||||||
|
// Verify name has been shortened to 80 characters
|
||||||
|
Assert.Equal(80, serviceName.Length);
|
||||||
|
|
||||||
|
var serviceNameParts = serviceName.Split('.');
|
||||||
|
|
||||||
|
// Verify that each component has been shortened to a sensible length
|
||||||
|
Assert.Equal("actions", serviceNameParts[0]); // Never shortened
|
||||||
|
Assert.Equal("runner", serviceNameParts[1]); // Never shortened
|
||||||
|
Assert.Equal("myreallylongorganizationexample-myreallylongr", serviceNameParts[2]); // First 45 chars, '/' has been replaced with '-'
|
||||||
|
Assert.Equal("thisisareallyreally", serviceNameParts[3]); // Remainder of unused chars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special 'defensive' test that verifies we can gracefully handle creating service names
|
||||||
|
// in case GitHub.com changes its org/repo naming convention in the future,
|
||||||
|
// and some of these characters may be invalid for service names
|
||||||
|
// Not meant to test character set exhaustively -- it's just here to exercise the sanitizing logic
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Service")]
|
||||||
|
public void CalculateServiceNameSanitizeOutOfRangeChars()
|
||||||
|
{
|
||||||
|
RunnerSettings settings = new RunnerSettings();
|
||||||
|
|
||||||
|
settings.AgentName = "name";
|
||||||
|
settings.ServerUrl = "https://example.githubusercontent.com/12345678901234567890123456789012345678901234567890";
|
||||||
|
settings.GitHubUrl = "https://github.com/org!@$*+[]()/repo!@$*+[]()";
|
||||||
|
|
||||||
|
string serviceNamePattern = "actions.runner.{0}.{1}";
|
||||||
|
string serviceDisplayNamePattern = "GitHub Actions Runner ({0}.{1})";
|
||||||
|
|
||||||
|
using (TestHostContext hc = CreateTestContext())
|
||||||
|
{
|
||||||
|
ServiceControlManager scm = new ServiceControlManager();
|
||||||
|
|
||||||
|
scm.Initialize(hc);
|
||||||
|
scm.CalculateServiceName(
|
||||||
|
settings,
|
||||||
|
serviceNamePattern,
|
||||||
|
serviceDisplayNamePattern,
|
||||||
|
out string serviceName,
|
||||||
|
out string serviceDisplayName);
|
||||||
|
|
||||||
|
var serviceNameParts = serviceName.Split('.');
|
||||||
|
|
||||||
|
// Verify service name parts are sanitized correctly
|
||||||
|
Assert.Equal("actions", serviceNameParts[0]);
|
||||||
|
Assert.Equal("runner", serviceNameParts[1]);
|
||||||
|
Assert.Equal("org----------repo---------", serviceNameParts[2]); // Chars replaced with '-'
|
||||||
|
Assert.Equal("name", serviceNameParts[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
|
||||||
|
{
|
||||||
|
TestHostContext hc = new TestHostContext(this, testName);
|
||||||
|
|
||||||
|
return hc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,8 +31,8 @@ namespace GitHub.Runner.Common.Tests.Util
|
|||||||
var connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
var connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10");
|
Assert.Equal("10", connect.Settings.MaxRetryRequest.ToString());
|
||||||
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "360");
|
Assert.Equal("360", connect.Settings.SendTimeout.TotalSeconds.ToString());
|
||||||
|
|
||||||
trace.Info("Set httpretry to 100.");
|
trace.Info("Set httpretry to 100.");
|
||||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "100");
|
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "100");
|
||||||
@@ -42,8 +42,8 @@ namespace GitHub.Runner.Common.Tests.Util
|
|||||||
connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10");
|
Assert.Equal("10", connect.Settings.MaxRetryRequest.ToString());
|
||||||
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "1200");
|
Assert.Equal("1200", connect.Settings.SendTimeout.TotalSeconds.ToString());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Id = actionId,
|
Id = actionId,
|
||||||
Reference = new Pipelines.RepositoryPathReference()
|
Reference = new Pipelines.RepositoryPathReference()
|
||||||
{
|
{
|
||||||
Name = "actions/npm",
|
Name = "actions/download-artifact",
|
||||||
Ref = "master",
|
Ref = "master",
|
||||||
RepositoryType = "GitHub"
|
RepositoryType = "GitHub"
|
||||||
}
|
}
|
||||||
@@ -220,12 +220,12 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
await _actionManager.PrepareActionsAsync(_ec.Object, actions);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
var watermarkFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "actions/npm", "master.completed");
|
var watermarkFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "actions/download-artifact", "master.completed");
|
||||||
Assert.True(File.Exists(watermarkFile));
|
Assert.True(File.Exists(watermarkFile));
|
||||||
|
|
||||||
var actionDockerfile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "actions/npm", "master", "Dockerfile");
|
var actionYamlFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "actions/download-artifact", "master", "action.yml");
|
||||||
Assert.True(File.Exists(actionDockerfile));
|
Assert.True(File.Exists(actionYamlFile));
|
||||||
_hc.GetTrace().Info(File.ReadAllText(actionDockerfile));
|
_hc.GetTrace().Info(File.ReadAllText(actionYamlFile));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -233,6 +233,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -272,6 +273,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -306,6 +308,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#if OS_LINUX
|
#if OS_LINUX
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
@@ -772,6 +775,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Teardown();
|
Teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
|
|||||||
@@ -37,25 +37,25 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container);
|
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(containerAction.Image, "Dockerfile");
|
Assert.Equal("Dockerfile", containerAction.Image);
|
||||||
Assert.Equal(containerAction.EntryPoint, "main.sh");
|
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||||
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz");
|
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token");
|
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo");
|
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url");
|
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar");
|
Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -81,27 +81,27 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container);
|
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(containerAction.Image, "Dockerfile");
|
Assert.Equal("Dockerfile", containerAction.Image);
|
||||||
Assert.Equal(containerAction.EntryPoint, "main.sh");
|
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||||
Assert.Equal(containerAction.Cleanup, "cleanup.sh");
|
Assert.Equal("cleanup.sh", containerAction.Cleanup);
|
||||||
Assert.Equal(containerAction.CleanupCondition, "failure()");
|
Assert.Equal("failure()", containerAction.CleanupCondition);
|
||||||
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz");
|
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token");
|
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo");
|
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url");
|
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar");
|
Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -126,19 +126,19 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_noargs_noenv_noentrypoint.yml"));
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerfileaction_noargs_noenv_noentrypoint.yml"));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container);
|
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(containerAction.Image, "Dockerfile");
|
Assert.Equal("Dockerfile", containerAction.Image);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -164,25 +164,25 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
|
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container);
|
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(containerAction.Image, "Dockerfile");
|
Assert.Equal("Dockerfile", containerAction.Image);
|
||||||
Assert.Equal(containerAction.EntryPoint, "main.sh");
|
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||||
Assert.Equal(containerAction.Arguments[0].ToString(), "${{ inputs.greeting }}");
|
Assert.Equal("${{ inputs.greeting }}", containerAction.Arguments[0].ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token");
|
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo");
|
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url");
|
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Value.ToString(), "${{ inputs.entryPoint }}");
|
Assert.Equal("${{ inputs.entryPoint }}", containerAction.Environment[1].Value.ToString());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -207,25 +207,25 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerhubaction.yml"));
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "dockerhubaction.yml"));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Container);
|
Assert.Equal(ActionExecutionType.Container, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var containerAction = result.Execution as ContainerActionExecutionData;
|
var containerAction = result.Execution as ContainerActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(containerAction.Image, "docker://ubuntu:18.04");
|
Assert.Equal("docker://ubuntu:18.04", containerAction.Image);
|
||||||
Assert.Equal(containerAction.EntryPoint, "main.sh");
|
Assert.Equal("main.sh", containerAction.EntryPoint);
|
||||||
Assert.Equal(containerAction.Arguments[0].ToString(), "bzz");
|
Assert.Equal("bzz", containerAction.Arguments[0].ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Key.ToString(), "Token");
|
Assert.Equal("Token", containerAction.Environment[0].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[0].Value.ToString(), "foo");
|
Assert.Equal("foo", containerAction.Environment[0].Value.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Key.ToString(), "Url");
|
Assert.Equal("Url", containerAction.Environment[1].Key.ToString());
|
||||||
Assert.Equal(containerAction.Environment[1].Value.ToString(), "bar");
|
Assert.Equal("bar", containerAction.Environment[1].Value.ToString());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -250,24 +250,24 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction.yml"));
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction.yml"));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Deprecated.Count, 1);
|
Assert.Equal(1, result.Deprecated.Count);
|
||||||
|
|
||||||
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
||||||
result.Deprecated.TryGetValue("greeting", out string value);
|
result.Deprecated.TryGetValue("greeting", out string value);
|
||||||
Assert.Equal(value, "This property has been deprecated");
|
Assert.Equal("This property has been deprecated", value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.NodeJS);
|
Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(nodeAction.Script, "main.js");
|
Assert.Equal("main.js", nodeAction.Script);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -292,26 +292,26 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_cleanup.yml"));
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "nodeaction_cleanup.yml"));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Deprecated.Count, 1);
|
Assert.Equal(1, result.Deprecated.Count);
|
||||||
|
|
||||||
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
Assert.True(result.Deprecated.ContainsKey("greeting"));
|
||||||
result.Deprecated.TryGetValue("greeting", out string value);
|
result.Deprecated.TryGetValue("greeting", out string value);
|
||||||
Assert.Equal(value, "This property has been deprecated");
|
Assert.Equal("This property has been deprecated", value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.NodeJS);
|
Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
var nodeAction = result.Execution as NodeJSActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(nodeAction.Script, "main.js");
|
Assert.Equal("main.js", nodeAction.Script);
|
||||||
Assert.Equal(nodeAction.Cleanup, "cleanup.js");
|
Assert.Equal("cleanup.js", nodeAction.Cleanup);
|
||||||
Assert.Equal(nodeAction.CleanupCondition, "cancelled()");
|
Assert.Equal("cancelled()", nodeAction.CleanupCondition);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -336,19 +336,19 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "pluginaction.yml"));
|
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "pluginaction.yml"));
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result.Name, "Hello World");
|
Assert.Equal("Hello World", result.Name);
|
||||||
Assert.Equal(result.Description, "Greet the world and record the time");
|
Assert.Equal("Greet the world and record the time", result.Description);
|
||||||
Assert.Equal(result.Inputs.Count, 2);
|
Assert.Equal(2, result.Inputs.Count);
|
||||||
Assert.Equal(result.Inputs[0].Key.AssertString("key").Value, "greeting");
|
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[0].Value.AssertString("value").Value, "Hello");
|
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
|
||||||
Assert.Equal(result.Inputs[1].Key.AssertString("key").Value, "entryPoint");
|
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
|
||||||
Assert.Equal(result.Inputs[1].Value.AssertString("value").Value, "");
|
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
|
||||||
|
|
||||||
Assert.Equal(result.Execution.ExecutionType, ActionExecutionType.Plugin);
|
Assert.Equal(ActionExecutionType.Plugin, result.Execution.ExecutionType);
|
||||||
|
|
||||||
var pluginAction = result.Execution as PluginActionExecutionData;
|
var pluginAction = result.Execution as PluginActionExecutionData;
|
||||||
|
|
||||||
Assert.Equal(pluginAction.Plugin, "someplugin");
|
Assert.Equal("someplugin", pluginAction.Plugin);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -383,9 +383,9 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.EvaluateContainerArguments(_ec.Object, arguments, evaluateContext);
|
var result = actionManifest.EvaluateContainerArguments(_ec.Object, arguments, evaluateContext);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result[0], "hello");
|
Assert.Equal("hello", result[0]);
|
||||||
Assert.Equal(result[1], "test");
|
Assert.Equal("test", result[1]);
|
||||||
Assert.Equal(result.Count, 2);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -420,9 +420,9 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.EvaluateContainerEnvironment(_ec.Object, environment, evaluateContext);
|
var result = actionManifest.EvaluateContainerEnvironment(_ec.Object, environment, evaluateContext);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result["hello"], "hello");
|
Assert.Equal("hello", result["hello"]);
|
||||||
Assert.Equal(result["test"], "test");
|
Assert.Equal("test", result["test"]);
|
||||||
Assert.Equal(result.Count, 2);
|
Assert.Equal(2, result.Count);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -459,13 +459,13 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new StringToken(null, null, null, "defaultValue"), evaluateContext);
|
var result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new StringToken(null, null, null, "defaultValue"), evaluateContext);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result, "defaultValue");
|
Assert.Equal("defaultValue", result);
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new BasicExpressionToken(null, null, null, "github.ref"), evaluateContext);
|
result = actionManifest.EvaluateDefaultInput(_ec.Object, "testInput", new BasicExpressionToken(null, null, null, "github.ref"), evaluateContext);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(result, "refs/heads/master");
|
Assert.Equal("refs/heads/master", result);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
private TestHostContext _hc;
|
private TestHostContext _hc;
|
||||||
private ActionRunner _actionRunner;
|
private ActionRunner _actionRunner;
|
||||||
private IActionManifestManager _actionManifestManager;
|
private IActionManifestManager _actionManifestManager;
|
||||||
private string _workFolder;
|
|
||||||
private DictionaryContextData _context = new DictionaryContextData();
|
private DictionaryContextData _context = new DictionaryContextData();
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -75,9 +74,9 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(finialInputs["input1"], "test1");
|
Assert.Equal("test1", finialInputs["input1"]);
|
||||||
Assert.Equal(finialInputs["input2"], "test2");
|
Assert.Equal("test2", finialInputs["input2"]);
|
||||||
Assert.Equal(finialInputs["input3"], "github");
|
Assert.Equal("github", finialInputs["input3"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -278,24 +277,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.Equal("${{ matrix.node }}", _actionRunner.DisplayName);
|
Assert.Equal("${{ matrix.node }}", _actionRunner.DisplayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateAction(string yamlContent, out Pipelines.ActionStep instance, out string directory)
|
|
||||||
{
|
|
||||||
directory = Path.Combine(_workFolder, Constants.Path.ActionsDirectory, "GitHub/actions".Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), "master");
|
|
||||||
string file = Path.Combine(directory, Constants.Path.ActionManifestFile);
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
|
||||||
File.WriteAllText(file, yamlContent);
|
|
||||||
instance = new Pipelines.ActionStep()
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid(),
|
|
||||||
Reference = new Pipelines.RepositoryPathReference()
|
|
||||||
{
|
|
||||||
Name = "GitHub/actions",
|
|
||||||
Ref = "master",
|
|
||||||
RepositoryType = Pipelines.RepositoryTypes.GitHub
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Setup([CallerMemberName] string name = "")
|
private void Setup([CallerMemberName] string name = "")
|
||||||
{
|
{
|
||||||
_ecTokenSource?.Dispose();
|
_ecTokenSource?.Dispose();
|
||||||
|
|||||||
@@ -206,8 +206,22 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null);
|
var action2 = jobContext.CreateChild(Guid.NewGuid(), "action_2", "action_2", null, null);
|
||||||
action2.IntraActionState["state"] = "2";
|
action2.IntraActionState["state"] = "2";
|
||||||
|
|
||||||
action1.RegisterPostJobAction("post1", "always()", new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } });
|
|
||||||
action2.RegisterPostJobAction("post2", "always()", new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } });
|
var postRunner1 = hc.CreateService<IActionRunner>();
|
||||||
|
postRunner1.Action = new Pipelines.ActionStep() { Name = "post1", DisplayName = "Test 1", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||||
|
postRunner1.Stage = ActionRunStage.Post;
|
||||||
|
postRunner1.Condition = "always()";
|
||||||
|
postRunner1.DisplayName = "post1";
|
||||||
|
|
||||||
|
|
||||||
|
var postRunner2 = hc.CreateService<IActionRunner>();
|
||||||
|
postRunner2.Action = new Pipelines.ActionStep() { Name = "post2", DisplayName = "Test 2", Reference = new Pipelines.RepositoryPathReference() { Name = "actions/action" } };
|
||||||
|
postRunner2.Stage = ActionRunStage.Post;
|
||||||
|
postRunner2.Condition = "always()";
|
||||||
|
postRunner2.DisplayName = "post2";
|
||||||
|
|
||||||
|
action1.RegisterPostJobStep("post1", postRunner1);
|
||||||
|
action2.RegisterPostJobStep("post2", postRunner2);
|
||||||
|
|
||||||
Assert.NotNull(jobContext.JobSteps);
|
Assert.NotNull(jobContext.JobSteps);
|
||||||
Assert.NotNull(jobContext.PostJobSteps);
|
Assert.NotNull(jobContext.PostJobSteps);
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -353,6 +350,48 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
config.Validate();
|
config.Validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void Matcher_MultiplePatterns_DefaultSeverity()
|
||||||
|
{
|
||||||
|
var config = JsonUtility.FromString<IssueMatchersConfig>(@"
|
||||||
|
{
|
||||||
|
""problemMatcher"": [
|
||||||
|
{
|
||||||
|
""owner"": ""myMatcher"",
|
||||||
|
""severity"": ""warning"",
|
||||||
|
""pattern"": [
|
||||||
|
{
|
||||||
|
""regexp"": ""^(ERROR)?(?: )?(.+):$"",
|
||||||
|
""severity"": 1,
|
||||||
|
""code"": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""regexp"": ""^(.+)$"",
|
||||||
|
""message"": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
");
|
||||||
|
config.Validate();
|
||||||
|
var matcher = new IssueMatcher(config.Matchers[0], TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
var match = matcher.Match("ABC:");
|
||||||
|
match = matcher.Match("not-working");
|
||||||
|
Assert.Equal("warning", match.Severity);
|
||||||
|
Assert.Equal("ABC", match.Code);
|
||||||
|
Assert.Equal("not-working", match.Message);
|
||||||
|
|
||||||
|
match = matcher.Match("ERROR ABC:");
|
||||||
|
match = matcher.Match("not-working");
|
||||||
|
Assert.Equal("ERROR", match.Severity);
|
||||||
|
Assert.Equal("ABC", match.Code);
|
||||||
|
Assert.Equal("not-working", match.Message);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
@@ -754,6 +793,43 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.Equal("myMatcher", matcher.Owner);
|
Assert.Equal("myMatcher", matcher.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void Matcher_SinglePattern_DefaultSeverity()
|
||||||
|
{
|
||||||
|
var config = JsonUtility.FromString<IssueMatchersConfig>(@"
|
||||||
|
{
|
||||||
|
""problemMatcher"": [
|
||||||
|
{
|
||||||
|
""owner"": ""myMatcher"",
|
||||||
|
""severity"": ""warning"",
|
||||||
|
""pattern"": [
|
||||||
|
{
|
||||||
|
""regexp"": ""^(ERROR)?(?: )?(.+): (.+)$"",
|
||||||
|
""severity"": 1,
|
||||||
|
""code"": 2,
|
||||||
|
""message"": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
");
|
||||||
|
config.Validate();
|
||||||
|
var matcher = new IssueMatcher(config.Matchers[0], TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
var match = matcher.Match("ABC: not-working");
|
||||||
|
Assert.Equal("warning", match.Severity);
|
||||||
|
Assert.Equal("ABC", match.Code);
|
||||||
|
Assert.Equal("not-working", match.Message);
|
||||||
|
|
||||||
|
match = matcher.Match("ERROR ABC: not-working");
|
||||||
|
Assert.Equal("ERROR", match.Severity);
|
||||||
|
Assert.Equal("ABC", match.Code);
|
||||||
|
Assert.Equal("not-working", match.Message);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
@@ -158,7 +159,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void Code()
|
public void MatcherCode()
|
||||||
{
|
{
|
||||||
var matchers = new IssueMatchersConfig
|
var matchers = new IssueMatchersConfig
|
||||||
{
|
{
|
||||||
@@ -300,7 +301,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void LineColumn()
|
public void MatcherLineColumn()
|
||||||
{
|
{
|
||||||
var matchers = new IssueMatchersConfig
|
var matchers = new IssueMatchersConfig
|
||||||
{
|
{
|
||||||
@@ -348,7 +349,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void ProcessCommand()
|
public void MatcherDoesNotReceiveCommand()
|
||||||
{
|
{
|
||||||
using (Setup())
|
using (Setup())
|
||||||
using (_outputManager)
|
using (_outputManager)
|
||||||
@@ -382,7 +383,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void RemoveColorCodes()
|
public void MatcherRemoveColorCodes()
|
||||||
{
|
{
|
||||||
using (Setup())
|
using (Setup())
|
||||||
using (_outputManager)
|
using (_outputManager)
|
||||||
@@ -528,7 +529,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void Severity()
|
public void MatcherSeverity()
|
||||||
{
|
{
|
||||||
var matchers = new IssueMatchersConfig
|
var matchers = new IssueMatchersConfig
|
||||||
{
|
{
|
||||||
@@ -589,7 +590,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
public void Timeout()
|
public void MatcherTimeout()
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT", "0:0:0.01");
|
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT", "0:0:0.01");
|
||||||
var matchers = new IssueMatchersConfig
|
var matchers = new IssueMatchersConfig
|
||||||
@@ -640,10 +641,216 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: roots file against fromPath
|
[Fact]
|
||||||
// todo: roots file against system.defaultWorkingDirectory
|
[Trait("Level", "L0")]
|
||||||
// todo: matches repository
|
[Trait("Category", "Worker")]
|
||||||
// todo: checks file exists
|
public void MatcherFile()
|
||||||
|
{
|
||||||
|
var matchers = new IssueMatchersConfig
|
||||||
|
{
|
||||||
|
Matchers =
|
||||||
|
{
|
||||||
|
new IssueMatcherConfig
|
||||||
|
{
|
||||||
|
Owner = "my-matcher-1",
|
||||||
|
Patterns = new[]
|
||||||
|
{
|
||||||
|
new IssuePatternConfig
|
||||||
|
{
|
||||||
|
Pattern = @"(.+): (.+)",
|
||||||
|
File = 1,
|
||||||
|
Message = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
using (var hostContext = Setup(matchers: matchers))
|
||||||
|
using (_outputManager)
|
||||||
|
{
|
||||||
|
// Setup github.workspace
|
||||||
|
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
|
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
|
||||||
|
Directory.CreateDirectory(workDirectory);
|
||||||
|
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
|
||||||
|
Directory.CreateDirectory(workspaceDirectory);
|
||||||
|
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
|
||||||
|
|
||||||
|
// Create a test file
|
||||||
|
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory"));
|
||||||
|
var filePath = Path.Combine(workspaceDirectory, "some-directory", "some-file.txt");
|
||||||
|
File.WriteAllText(filePath, "");
|
||||||
|
|
||||||
|
// Process
|
||||||
|
Process("some-directory/some-file.txt: some error");
|
||||||
|
Assert.Equal(1, _issues.Count);
|
||||||
|
Assert.Equal("some error", _issues[0].Item1.Message);
|
||||||
|
Assert.Equal("some-directory/some-file.txt", _issues[0].Item1.Data["file"]);
|
||||||
|
Assert.Equal(0, _commands.Count);
|
||||||
|
Assert.Equal(0, _messages.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void MatcherFileExists()
|
||||||
|
{
|
||||||
|
var matchers = new IssueMatchersConfig
|
||||||
|
{
|
||||||
|
Matchers =
|
||||||
|
{
|
||||||
|
new IssueMatcherConfig
|
||||||
|
{
|
||||||
|
Owner = "my-matcher-1",
|
||||||
|
Patterns = new[]
|
||||||
|
{
|
||||||
|
new IssuePatternConfig
|
||||||
|
{
|
||||||
|
Pattern = @"(.+): (.+)",
|
||||||
|
File = 1,
|
||||||
|
Message = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
using (var hostContext = Setup(matchers: matchers))
|
||||||
|
using (_outputManager)
|
||||||
|
{
|
||||||
|
// Setup github.workspace
|
||||||
|
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
|
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
|
||||||
|
Directory.CreateDirectory(workDirectory);
|
||||||
|
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
|
||||||
|
Directory.CreateDirectory(workspaceDirectory);
|
||||||
|
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
|
||||||
|
|
||||||
|
// Create a test file
|
||||||
|
File.WriteAllText(Path.Combine(workspaceDirectory, "some-file-1.txt"), "");
|
||||||
|
|
||||||
|
// Process
|
||||||
|
Process("some-file-1.txt: some error 1"); // file exists
|
||||||
|
Process("some-file-2.txt: some error 2"); // file does not exist
|
||||||
|
|
||||||
|
Assert.Equal(2, _issues.Count);
|
||||||
|
Assert.Equal("some error 1", _issues[0].Item1.Message);
|
||||||
|
Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]);
|
||||||
|
Assert.Equal("some error 2", _issues[1].Item1.Message);
|
||||||
|
Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key
|
||||||
|
Assert.Equal(0, _commands.Count);
|
||||||
|
Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void MatcherFileOutsideRepository()
|
||||||
|
{
|
||||||
|
var matchers = new IssueMatchersConfig
|
||||||
|
{
|
||||||
|
Matchers =
|
||||||
|
{
|
||||||
|
new IssueMatcherConfig
|
||||||
|
{
|
||||||
|
Owner = "my-matcher-1",
|
||||||
|
Patterns = new[]
|
||||||
|
{
|
||||||
|
new IssuePatternConfig
|
||||||
|
{
|
||||||
|
Pattern = @"(.+): (.+)",
|
||||||
|
File = 1,
|
||||||
|
Message = 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
using (var hostContext = Setup(matchers: matchers))
|
||||||
|
using (_outputManager)
|
||||||
|
{
|
||||||
|
// Setup github.workspace
|
||||||
|
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
|
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
|
||||||
|
Directory.CreateDirectory(workDirectory);
|
||||||
|
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
|
||||||
|
Directory.CreateDirectory(workspaceDirectory);
|
||||||
|
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
|
||||||
|
|
||||||
|
// Create test files
|
||||||
|
var filePath1 = Path.Combine(workspaceDirectory, "some-file-1.txt");
|
||||||
|
File.WriteAllText(filePath1, "");
|
||||||
|
var workspaceSiblingDirectory = Path.Combine(Path.GetDirectoryName(workspaceDirectory), "workspace-sibling");
|
||||||
|
Directory.CreateDirectory(workspaceSiblingDirectory);
|
||||||
|
var filePath2 = Path.Combine(workspaceSiblingDirectory, "some-file-2.txt");
|
||||||
|
File.WriteAllText(filePath2, "");
|
||||||
|
|
||||||
|
// Process
|
||||||
|
Process($"{filePath1}: some error 1"); // file exists inside workspace
|
||||||
|
Process($"{filePath2}: some error 2"); // file exists outside workspace
|
||||||
|
|
||||||
|
Assert.Equal(2, _issues.Count);
|
||||||
|
Assert.Equal("some error 1", _issues[0].Item1.Message);
|
||||||
|
Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]);
|
||||||
|
Assert.Equal("some error 2", _issues[1].Item1.Message);
|
||||||
|
Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key
|
||||||
|
Assert.Equal(0, _commands.Count);
|
||||||
|
Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Level", "L0")]
|
||||||
|
[Trait("Category", "Worker")]
|
||||||
|
public void MatcherFromPath()
|
||||||
|
{
|
||||||
|
var matchers = new IssueMatchersConfig
|
||||||
|
{
|
||||||
|
Matchers =
|
||||||
|
{
|
||||||
|
new IssueMatcherConfig
|
||||||
|
{
|
||||||
|
Owner = "my-matcher-1",
|
||||||
|
Patterns = new[]
|
||||||
|
{
|
||||||
|
new IssuePatternConfig
|
||||||
|
{
|
||||||
|
Pattern = @"(.+): (.+) \[(.+)\]",
|
||||||
|
File = 1,
|
||||||
|
Message = 2,
|
||||||
|
FromPath = 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
using (var hostContext = Setup(matchers: matchers))
|
||||||
|
using (_outputManager)
|
||||||
|
{
|
||||||
|
// Setup github.workspace
|
||||||
|
var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work);
|
||||||
|
ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory));
|
||||||
|
Directory.CreateDirectory(workDirectory);
|
||||||
|
var workspaceDirectory = Path.Combine(workDirectory, "workspace");
|
||||||
|
Directory.CreateDirectory(workspaceDirectory);
|
||||||
|
_executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory);
|
||||||
|
|
||||||
|
// Create a test file
|
||||||
|
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-project", "some-directory"));
|
||||||
|
var filePath = Path.Combine(workspaceDirectory, "some-project", "some-directory", "some-file.txt");
|
||||||
|
File.WriteAllText(filePath, "");
|
||||||
|
|
||||||
|
// Process
|
||||||
|
Process("some-directory/some-file.txt: some error [some-project/some-project.proj]");
|
||||||
|
Assert.Equal(1, _issues.Count);
|
||||||
|
Assert.Equal("some error", _issues[0].Item1.Message);
|
||||||
|
Assert.Equal("some-project/some-directory/some-file.txt", _issues[0].Item1.Data["file"]);
|
||||||
|
Assert.Equal(0, _commands.Count);
|
||||||
|
Assert.Equal(0, _messages.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TestHostContext Setup(
|
private TestHostContext Setup(
|
||||||
[CallerMemberName] string name = "",
|
[CallerMemberName] string name = "",
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
string actual = variables.Get("no such");
|
string actual = variables.Get("no such");
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(null, actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm;rhel.6-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||||
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
<AssetTargetFallback>portable-net45+win8</AssetTargetFallback>
|
||||||
<NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
|
<NoWarn>NU1701;NU1603;NU1603;xUnit2013;</NoWarn>
|
||||||
@@ -29,42 +29,4 @@
|
|||||||
<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
src/dev.sh
24
src/dev.sh
@@ -10,6 +10,7 @@ set -e
|
|||||||
|
|
||||||
DEV_CMD=$1
|
DEV_CMD=$1
|
||||||
DEV_CONFIG=$2
|
DEV_CONFIG=$2
|
||||||
|
DEV_TARGET_RUNTIME=$3
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
||||||
@@ -43,24 +44,20 @@ elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
|
|||||||
CPU_NAME=$(uname -m)
|
CPU_NAME=$(uname -m)
|
||||||
case $CPU_NAME in
|
case $CPU_NAME in
|
||||||
armv7l) RUNTIME_ID="linux-arm";;
|
armv7l) RUNTIME_ID="linux-arm";;
|
||||||
aarch64) RUNTIME_ID="linux-arm";;
|
aarch64) RUNTIME_ID="linux-arm64";;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -e /etc/redhat-release ]; then
|
|
||||||
redhatRelease=$(</etc/redhat-release)
|
|
||||||
if [[ $redhatRelease == "CentOS release 6."* || $redhatRelease == "Red Hat Enterprise Linux Server release 6."* ]]; then
|
|
||||||
RUNTIME_ID='rhel.6-x64'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
|
elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
|
||||||
RUNTIME_ID='osx-x64'
|
RUNTIME_ID='osx-x64'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$DEV_TARGET_RUNTIME" ]]; then
|
||||||
|
RUNTIME_ID="$DEV_TARGET_RUNTIME"
|
||||||
|
fi
|
||||||
|
|
||||||
# Make sure current platform support publish the dotnet runtime
|
# Make sure current platform support publish the dotnet runtime
|
||||||
# Windows can publish win-x86/x64
|
# Windows can publish win-x86/x64
|
||||||
# Linux can publish linux-x64/arm/rhel.6-x64
|
# Linux can publish linux-x64/arm/arm64
|
||||||
# OSX can publish osx-x64
|
# OSX can publish osx-x64
|
||||||
if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
|
if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
|
||||||
if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') ]]; then
|
if [[ ("$RUNTIME_ID" != 'win-x86') && ("$RUNTIME_ID" != 'win-x64') ]]; then
|
||||||
@@ -68,7 +65,7 @@ if [[ "$CURRENT_PLATFORM" == 'windows' ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
|
elif [[ "$CURRENT_PLATFORM" == 'linux' ]]; then
|
||||||
if [[ ("$RUNTIME_ID" != 'linux-x64') && ("$RUNTIME_ID" != 'linux-arm') && ("$RUNTIME_ID" != 'rhel.6-x64') ]]; then
|
if [[ ("$RUNTIME_ID" != 'linux-x64') && ("$RUNTIME_ID" != 'linux-x86') && ("$RUNTIME_ID" != 'linux-arm64') && ("$RUNTIME_ID" != 'linux-arm') ]]; then
|
||||||
echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
|
echo "Failed: Can't build $RUNTIME_ID package $CURRENT_PLATFORM" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -151,7 +148,8 @@ function package ()
|
|||||||
echo "You must build first. Expecting to find ${LAYOUT_DIR}/bin"
|
echo "You must build first. Expecting to find ${LAYOUT_DIR}/bin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
runner_ver=$("${LAYOUT_DIR}/bin/Runner.Listener" --version) || failed "version"
|
# TODO: We are cross-compiling arm on x64 so we cant exec Runner.Listener. Remove after building on native arm host
|
||||||
|
runner_ver=$("${LAYOUT_DIR}/bin/Runner.Listener" --version) || runner_ver=$(cat runnerversion) || failed "version"
|
||||||
runner_pkg_name="actions-runner-${RUNTIME_ID}-${runner_ver}"
|
runner_pkg_name="actions-runner-${RUNTIME_ID}-${runner_ver}"
|
||||||
|
|
||||||
heading "Packaging ${runner_pkg_name}"
|
heading "Packaging ${runner_pkg_name}"
|
||||||
@@ -208,8 +206,6 @@ fi
|
|||||||
echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%"
|
echo "Prepend ${DOTNETSDK_INSTALLDIR} to %PATH%"
|
||||||
export PATH=${DOTNETSDK_INSTALLDIR}:$PATH
|
export PATH=${DOTNETSDK_INSTALLDIR}:$PATH
|
||||||
|
|
||||||
heading "Github Dreamlifter Runner"
|
|
||||||
|
|
||||||
heading "Dotnet SDK Version"
|
heading "Dotnet SDK Version"
|
||||||
dotnet --version
|
dotnet --version
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.159.2
|
2.162.0
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
parameters:
|
||||||
|
targetRuntime: ''
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# Build agent layout
|
# Build agent layout
|
||||||
- script: dev.cmd layout Release
|
- script: dev.cmd layout Release ${{ parameters.targetRuntime }}
|
||||||
workingDirectory: src
|
workingDirectory: src
|
||||||
displayName: Build & Layout Release
|
displayName: Build & Layout Release ${{ parameters.targetRuntime }}
|
||||||
|
|
||||||
# Run test
|
# Run test
|
||||||
- script: dev.cmd test
|
- script: dev.cmd test
|
||||||
|
|||||||
Reference in New Issue
Block a user