mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Compare commits
1 Commits
users/etha
...
users/tihu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eed84f6cf3 |
@@ -23,7 +23,7 @@ An ADR is an Architectural Decision Record. This allows consensus on the direct
|
|||||||
|
|
||||||
### Required Dev Dependencies
|
### Required Dev Dependencies
|
||||||
|
|
||||||
  Git for Windows and Linux [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
 Git for Windows [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
||||||
|
|
||||||
### To Build, Test, Layout
|
### To Build, Test, Layout
|
||||||
|
|
||||||
@@ -43,7 +43,6 @@ Sample developer flow:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/actions/runner
|
git clone https://github.com/actions/runner
|
||||||
cd runner
|
|
||||||
cd ./src
|
cd ./src
|
||||||
./dev.(sh/cmd) layout # the runner that built from source is in {root}/_layout
|
./dev.(sh/cmd) layout # the runner that built from source is in {root}/_layout
|
||||||
<make code changes>
|
<make code changes>
|
||||||
@@ -51,23 +50,10 @@ cd ./src
|
|||||||
./dev.(sh/cmd) test # run all unit tests before git commit/push
|
./dev.(sh/cmd) test # run all unit tests before git commit/push
|
||||||
```
|
```
|
||||||
|
|
||||||
View logs:
|
|
||||||
```bash
|
|
||||||
cd runner/_layout/_diag
|
|
||||||
ls
|
|
||||||
cat (Runner/Worker)_TIMESTAMP.log # view your log file
|
|
||||||
```
|
|
||||||
|
|
||||||
Run Runner:
|
|
||||||
```bash
|
|
||||||
cd runner/_layout
|
|
||||||
./run.sh # run your custom runner
|
|
||||||
```
|
|
||||||
|
|
||||||
### Editors
|
### Editors
|
||||||
|
|
||||||
[Using Visual Studio Code](https://code.visualstudio.com/)
|
[Using Visual Studio Code](https://code.visualstudio.com/)
|
||||||
[Using Visual Studio](https://code.visualstudio.com/docs)
|
[Using Visual Studio 2019](https://www.visualstudio.com/vs/)
|
||||||
|
|
||||||
### Styling
|
### Styling
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
## Features
|
## Features
|
||||||
- Resolve action download info from server (#508, #515, #550)
|
- N/A
|
||||||
- Print runner and machine name to log. (#539)
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Reduce input validation warnings (#506)
|
- Handle `jq` returns "null" if the field does not exist in create-latest-svc.sh (#478)
|
||||||
- Fix null ref exception in SecretMasker caused by `hashfiles` timeout. (#516)
|
- Switch GITHUB_URL to GITHUB_SERVER_URL (#482)
|
||||||
- Add libicu66 to `./installDependencies.sh` for Ubuntu 20.04 (#535)
|
- Fix problem matcher for GHES (#488)
|
||||||
- Fix DataContract with Token service (#532)
|
- Fix container action inputs validation warning (#490)
|
||||||
- Skip search $PATH on command with fully qualified path (#526)
|
- Fix post step display name (#490)
|
||||||
- Restore SELinux context on service file when SELinux is enabled (#525)
|
- Fix worker crash due to exception from evaluating step.env (#490)
|
||||||
## Misc
|
## Misc
|
||||||
- Remove SPS/Token migration code. Remove GHES url manipulate code. (#513)
|
- N/A
|
||||||
- Add sub-step for developer flow for clarity (#523)
|
|
||||||
- Update Links and Language to Git + VSCode (#522)
|
|
||||||
- Update runner configuration exception message (#540)
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
|
|||||||
379
src/Misc/dotnet-install.ps1
vendored
379
src/Misc/dotnet-install.ps1
vendored
@@ -154,16 +154,7 @@ function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [in
|
|||||||
function Get-Machine-Architecture() {
|
function Get-Machine-Architecture() {
|
||||||
Say-Invocation $MyInvocation
|
Say-Invocation $MyInvocation
|
||||||
|
|
||||||
# On PS x86, PROCESSOR_ARCHITECTURE reports x86 even on x64 systems.
|
# possible values: amd64, x64, x86, arm64, arm
|
||||||
# To get the correct architecture, we need to use PROCESSOR_ARCHITEW6432.
|
|
||||||
# PS x64 doesn't define this, so we fall back to PROCESSOR_ARCHITECTURE.
|
|
||||||
# Possible values: amd64, x64, x86, arm64, arm
|
|
||||||
|
|
||||||
if( $ENV:PROCESSOR_ARCHITEW6432 -ne $null )
|
|
||||||
{
|
|
||||||
return $ENV:PROCESSOR_ARCHITEW6432
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ENV:PROCESSOR_ARCHITECTURE
|
return $ENV:PROCESSOR_ARCHITECTURE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,194 +686,194 @@ Say "Installation finished"
|
|||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
# SIG # Begin signature block
|
# SIG # Begin signature block
|
||||||
# MIIjhwYJKoZIhvcNAQcCoIIjeDCCI3QCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
# MIIjkQYJKoZIhvcNAQcCoIIjgjCCI34CAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
||||||
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
||||||
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAiKYSY4KtkeThH
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAwp4UsNdAkvwY3
|
||||||
# d5M1aXqv1K0/pff07QwfUbYZ/qX5LqCCDYUwggYDMIID66ADAgECAhMzAAABiK9S
|
# VhbuN9D6NGOz+qNqW2+62YubWa4qJaCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
|
||||||
# 1rmSbej5AAAAAAGIMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
|
||||||
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
|
||||||
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ4WhcNMjEwMzAzMTgzOTQ4WjB0MQsw
|
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
|
||||||
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
|
||||||
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
|
||||||
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||||
# AQCSCNryE+Cewy2m4t/a74wZ7C9YTwv1PyC4BvM/kSWPNs8n0RTe+FvYfU+E9uf0
|
# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
|
||||||
# t7nYlAzHjK+plif2BhD+NgdhIUQ8sVwWO39tjvQRHjP2//vSvIfmmkRoML1Ihnjs
|
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
|
||||||
# 9kQiZQzYRDYYRp9xSQYmRwQjk5hl8/U7RgOiQDitVHaU7BT1MI92lfZRuIIDDYBd
|
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
|
||||||
# vXtbclYJMVOwqZtv0O9zQCret6R+fRSGaDNfEEpcILL+D7RV3M4uaJE4Ta6KAOdv
|
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
|
||||||
# V+MVaJp1YXFTZPKtpjHO6d9pHQPZiG7NdC6QbnRGmsa48uNQrb6AfmLKDI1Lp31W
|
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
|
||||||
# MogTaX5tZf+CZT9PSuvjOCLNAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
|
# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
|
||||||
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUj9RJL9zNrPcL10RZdMQIXZN7MG8w
|
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
|
||||||
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
|
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
|
||||||
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ1ODM4NjAfBgNVHSMEGDAW
|
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
|
||||||
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
|
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
|
||||||
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
|
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
|
||||||
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
|
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
|
||||||
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
|
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
|
||||||
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
|
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
|
||||||
# ACnXo8hjp7FeT+H6iQlV3CcGnkSbFvIpKYafgzYCFo3UHY1VHYJVb5jHEO8oG26Q
|
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
|
||||||
# qBELmak6MTI+ra3WKMTGhE1sEIlowTcp4IAs8a5wpCh6Vf4Z/bAtIppP3p3gXk2X
|
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
|
||||||
# 8UXTc+WxjQYsDkFiSzo/OBa5hkdW1g4EpO43l9mjToBdqEPtIXsZ7Hi1/6y4gK0P
|
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
|
||||||
# mMiwG8LMpSn0n/oSHGjrUNBgHJPxgs63Slf58QGBznuXiRaXmfTUDdrvhRocdxIM
|
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
|
||||||
# i8nXQwWACMiQzJSRzBP5S2wUq7nMAqjaTbeXhJqD2SFVHdUYlKruvtPSwbnqSRWT
|
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
|
||||||
# GI8s4FEXt+TL3w5JnwVZmZkUFoioQDMMjFyaKurdJ6pnzbr1h6QW0R97fWc8xEIz
|
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
|
||||||
# LIOiU2rjwWAtlQqFO8KNiykjYGyEf5LyAJKAO+rJd9fsYR+VBauIEQoYmjnUbTXM
|
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
|
||||||
# SY2Lf5KMluWlDOGVh8q6XjmBccpaT+8tCfxpaVYPi1ncnwTwaPQvVq8RjWDRB7Pa
|
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
|
||||||
# 8ruHgj2HJFi69+hcq7mWx5nTUtzzFa7RSZfE5a1a5AuBmGNRr7f8cNfa01+tiWjV
|
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
|
||||||
# Kk1a+gJUBSP0sIxecFbVSXTZ7bqeal45XSDIisZBkWb+83TbXdTGMDSUFKTAdtC+
|
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
|
||||||
# r35GfsN8QVy59Hb5ZYzAXczhgRmk7NyE6jD0Ym5TKiW5MIIHejCCBWKgAwIBAgIK
|
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
|
||||||
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
|
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
|
||||||
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
|
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
|
||||||
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
|
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
|
||||||
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
|
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
|
||||||
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
|
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
|
||||||
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
|
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
|
||||||
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
|
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
|
||||||
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
|
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
|
||||||
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
|
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
|
||||||
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
|
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
|
||||||
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
|
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
|
||||||
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
|
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
|
||||||
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
|
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
|
||||||
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
|
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
|
||||||
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
|
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
|
||||||
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
|
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
|
||||||
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
|
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
|
||||||
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
|
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
|
||||||
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
|
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
|
||||||
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
|
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
|
||||||
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
|
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
|
||||||
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
|
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
|
||||||
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||||
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
|
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
|
||||||
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
|
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
|
||||||
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
|
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
|
||||||
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
|
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
|
||||||
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
|
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
|
||||||
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
|
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
|
||||||
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
|
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
|
||||||
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
|
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
|
||||||
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
|
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
|
||||||
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
|
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
|
||||||
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
|
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
|
||||||
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
|
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
|
||||||
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
|
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
|
||||||
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
|
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
|
||||||
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
|
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
|
||||||
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
|
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
|
||||||
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCFVgwghVUAgEBMIGVMH4x
|
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZjCCFWICAQEwgZUwfjELMAkG
|
||||||
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
|
|
||||||
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
|
|
||||||
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAGIr1LWuZJt6PkAAAAA
|
|
||||||
# AYgwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
|
|
||||||
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFxZ
|
|
||||||
# Yezh3liQqiGQuXNa+zYfoSIbLqOpdEn2ZKskBkisMEIGCisGAQQBgjcCAQwxNDAy
|
|
||||||
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
|
|
||||||
# b20wDQYJKoZIhvcNAQEBBQAEggEAjLUrwCXJCPHZulZuKAQSX+MfnIRFAhlN7ru2
|
|
||||||
# 6H8rudvhkWgqMISkLb9gFDPR5FhR4sqdYgKW4P0ERao9ypCGi1FWDLqygC2XBbHj
|
|
||||||
# NEQHBxHJs5SMsMAXNSIcYHqVAvhF3nXoseaNBkhOTrkQ1FS/fW7AfDGRbsiiESzv
|
|
||||||
# lebf92shZylBFKOsKQLAL0mF/B7xrxHJIj5dgQoD1phATRNHOEQj3jgmkidFWowV
|
|
||||||
# 4r8MzbxRhAEORbnJexlUoDQJQH3YwxuUyXkTvrYMTKSbGJLlwRaZQbrcBU0k4gCH
|
|
||||||
# y8Sci+p9Rq+aOTzLCoNrZyh9E7OdwVDm1FJAtY30bV50T2WSFKGCEuIwghLeBgor
|
|
||||||
# BgEEAYI3AwMBMYISzjCCEsoGCSqGSIb3DQEHAqCCErswghK3AgEDMQ8wDQYJYIZI
|
|
||||||
# AWUDBAIBBQAwggFRBgsqhkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGE
|
|
||||||
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCD7JNcBBSfhlKPL1tN3CEKRKJuT/dZ8RO9K
|
|
||||||
# orYLXJeLTwIGXvN89YD7GBMyMDIwMDcwMTE0MTYyMC40MDVaMASAAgH0oIHQpIHN
|
|
||||||
# MIHKMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1JlZG1vbmQx
|
|
||||||
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z
|
|
||||||
# b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg
|
|
||||||
# VFNTIEVTTjoxNzlFLTRCQjAtODI0NjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
|
|
||||||
# U3RhbXAgU2VydmljZaCCDjkwggTxMIID2aADAgECAhMzAAABDKp4btzMQkzBAAAA
|
|
||||||
# AAEMMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
|
|
||||||
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
|
|
||||||
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
|
|
||||||
# MB4XDTE5MTAyMzIzMTkxNloXDTIxMDEyMTIzMTkxNlowgcoxCzAJBgNVBAYTAlVT
|
|
||||||
# MQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
|
|
||||||
# b2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVy
|
|
||||||
# YXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjE3OUUtNEJC
|
|
||||||
# MC04MjQ2MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIB
|
|
||||||
# IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq5011+XqVJmQKtiw39igeEMv
|
|
||||||
# CLcZ1forbmxsDkpnCN1SrThKI+n2Pr3zqTzJVgdJFCoKm1ks1gtRJ7HaL6tDkrOw
|
|
||||||
# 8XJmfJaxyQAluCQ+e40NI+A4w+u59Gy89AVY5lJNrmCva6gozfg1kxw6abV5WWr+
|
|
||||||
# PjEpNCshO4hxv3UqgMcCKnT2YVSZzF1Gy7APub1fY0P1vNEuOFKrNCEEvWIKRrqs
|
|
||||||
# eyBB73G8KD2yw6jfz0VKxNSRAdhJV/ghOyrDt5a+L6C3m1rpr8sqiof3iohv3ANI
|
|
||||||
# gNqw6ex+4+G+B7JMbIHbGpPdebedL6ePbuBCnbgJoDn340k0aw6ij21GvvUnkQID
|
|
||||||
# AQABo4IBGzCCARcwHQYDVR0OBBYEFAlCOq9DDIa0A0oqgKtM5vjuZeK+MB8GA1Ud
|
|
||||||
# IwQYMBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeGRWh0
|
|
||||||
# dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0
|
|
||||||
# YVBDQV8yMDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKG
|
|
||||||
# Pmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3RhUENB
|
|
||||||
# XzIwMTAtMDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUH
|
|
||||||
# AwgwDQYJKoZIhvcNAQELBQADggEBAET3xBg/IZ9zdOfwbDGK7cK3qKYt/qUOlbRB
|
|
||||||
# zgeNjb32K86nGeRGkBee10dVOEGWUw6KtBeWh1LQ70b64/tLtiLcsf9JzaAyDYb1
|
|
||||||
# sRmMi5fjRZ753TquaT8V7NJ7RfEuYfvZlubfQD0MVbU4tzsdZdYuxE37V2J9pN89
|
|
||||||
# j7GoFNtAnSnCn1MRxENAILgt9XzeQzTEDhFYW0N2DNphTkRPXGjpDmwi6WtkJ5fv
|
|
||||||
# 0iTyB4dwEC+/ed0lGbFLcytJoMwfTNMdH6gcnHlMzsniornGFZa5PPiV78XoZ9Fe
|
|
||||||
# upKo8ZKNGhLLLB5GTtqfHex5no3ioVSq+NthvhX0I/V+iXJsopowggZxMIIEWaAD
|
|
||||||
# AgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzET
|
|
||||||
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
|
|
||||||
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBD
|
|
||||||
# ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0xMDA3MDEyMTM2NTVaFw0yNTA3
|
|
||||||
# MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
|
|
||||||
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
|
|
||||||
# JjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjANBgkq
|
|
||||||
# hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcRijog7PwTl/X6f2mUa3RUENWl
|
|
||||||
# CgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBED/Fg
|
|
||||||
# iIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRgMlhgRvJYR4YyhB50YWeR
|
|
||||||
# X4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd/Xcf
|
|
||||||
# PfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajyeioKMfDaTgaRtogI
|
|
||||||
# Neh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJRF1eFpwBBU8iTQIDAQABo4IB
|
|
||||||
# 5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyKMZDzQ3t8RhvF
|
|
||||||
# M2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAP
|
|
||||||
# BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjE
|
|
||||||
# MFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kv
|
|
||||||
# Y3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEF
|
|
||||||
# BQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
|
|
||||||
# a2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSABAf8E
|
|
||||||
# gZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcCARYxaHR0cDovL3d3dy5t
|
|
||||||
# aWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEFBQcC
|
|
||||||
# AjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMAdABhAHQAZQBtAGUA
|
|
||||||
# bgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Ehb7Pr
|
|
||||||
# psz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcIK1GCRBL7uVOM
|
|
||||||
# zPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMivv3/Gf/I3fVo/HPKZeUqRUgCv
|
|
||||||
# OA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8ySif9Va8v
|
|
||||||
# /rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbiOewZSnFjnXshbcOco6I8+n99
|
|
||||||
# lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+Y1kl
|
|
||||||
# D3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ732D8OE7cQnfXXSYIghh2rBQ
|
|
||||||
# Hm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRyzR30
|
|
||||||
# uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp9cAvVCch98isTtoouLGp
|
|
||||||
# 25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx16HS
|
|
||||||
# xVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA12u8JJxzVs341Hgi6
|
|
||||||
# 2jbb01+P3nSISRKhggLLMIICNAIBATCB+KGB0KSBzTCByjELMAkGA1UEBhMCVVMx
|
|
||||||
# CzAJBgNVBAgTAldBMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
|
|
||||||
# ZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
|
|
||||||
# dGlvbnMgTGltaXRlZDEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046MTc5RS00QkIw
|
|
||||||
# LTgyNDYxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoB
|
|
||||||
# ATAHBgUrDgMCGgMVAMsg9FQ9pgPLXI2Ld5z7xDS0QAZ9oIGDMIGApH4wfDELMAkG
|
|
||||||
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
|
||||||
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9z
|
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
|
||||||
# b2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEFBQACBQDipo0MMCIY
|
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
|
||||||
# DzIwMjAwNzAxMTIxODIwWhgPMjAyMDA3MDIxMjE4MjBaMHQwOgYKKwYBBAGEWQoE
|
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
|
||||||
# ATEsMCowCgIFAOKmjQwCAQAwBwIBAAICE70wBwIBAAICEeIwCgIFAOKn3owCAQAw
|
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQga11B1DE+
|
||||||
# NgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgC
|
# y9z0lmEO+MC+bhXPKfWALB7Snkn7G/wCUncwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
|
||||||
# AQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQCOPjlHOH8nYtgt2XnpKXenxPUR03ED
|
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
|
||||||
# xPBm8XR5Z1vIq53RU9jG6yYcYNTdK+q38SGZtu0W/SgagTfKCQhjhRakuv7rGSs2
|
# BgkqhkiG9w0BAQEFAASCAQBIgx+sFXkLXf7Xbx7opCD3uhpQGEQ4x/LsqTax0bu1
|
||||||
# dlhx9LGCoc/q1vqmZpRSjkqWVcc/NzmldUWIWnLlV6rmLGoDmfCH5BcsiU6Eo6wU
|
# GC/cxiI+dodUz+T4hKj1ZQyUH0Zlce32GutY048O9tkr7fQyuohoFUgChdIATEOY
|
||||||
# iUVwnnXoqsCaBzGCAw0wggMJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
|
# qAIESFbDT07i7khJfO2pewlhgM+A5ClvBa8HAvV0wOd+2IVgv3pgow1LEJm0/5NB
|
||||||
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
|
# E3IFA+hFrqiWALOY0uUep4H20EHMrbqw3YoV3EodIkTj3fC76q4K/bF84EZLUgjY
|
||||||
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
|
# e4rmXac8n7A9qR18QzGl8usEJej4OHU4nlUT1J734m+AWIFmfb/Zr2MyXED0V4q4
|
||||||
# QSAyMDEwAhMzAAABDKp4btzMQkzBAAAAAAEMMA0GCWCGSAFlAwQCAQUAoIIBSjAa
|
# Vbmw3O7xD9STeNYrn5RjPmGPEN04akHxhNUSqLIc9vxQoYIS8DCCEuwGCisGAQQB
|
||||||
# BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIDpwhjyu
|
# gjcDAwExghLcMIIS2AYJKoZIhvcNAQcCoIISyTCCEsUCAQMxDzANBglghkgBZQME
|
||||||
# zgu3Kmxpnpz86ZlthBqEzG5vaEMOkYRyuFCaMIH6BgsqhkiG9w0BCRACLzGB6jCB
|
# AgEFADCCAVQGCyqGSIb3DQEJEAEEoIIBQwSCAT8wggE7AgEBBgorBgEEAYRZCgMB
|
||||||
# 5zCB5DCBvQQgg5AWKX7M1+m2//+V7qmRvt1K/ww5Muu8XzGJBqygVCkwgZgwgYCk
|
# MDEwDQYJYIZIAWUDBAIBBQAEIPPK1A0D1n7ZEdgTjKPY4sWiOMtohMqGpFvG55NY
|
||||||
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
|
# SFHeAgZepuJh/dEYEjIwMjAwNTI5MTYyNzE1LjMxWjAEgAIB9KCB1KSB0TCBzjEL
|
||||||
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
|
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
|
||||||
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAQyqeG7czEJMwQAA
|
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWlj
|
||||||
# AAABDDAiBCD11urvv5vgo4gFVQ2NMVrzgxT87Yuiq16YdswYbaYeITANBgkqhkiG
|
# cm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBU
|
||||||
# 9w0BAQsFAASCAQAi3q8hwcT2ft4b2EleaiyZxOImV/cKusmth1dtCh5/Jb0GbOld
|
# U1MgRVNOOjYwQkMtRTM4My0yNjM1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1T
|
||||||
# f5cSalrjf42MNPodWAtgmWozkYrQF6HxnsOiYiamfRA8E3E7xyRMy7AFfAhjcwMi
|
# dGFtcCBTZXJ2aWNloIIORDCCBPUwggPdoAMCAQICEzMAAAEm37pLIrmCggcAAAAA
|
||||||
# xaW4Iye6E1Ec6LtULANxfDtG/KIdCWdZxKqOezL3nzFNQWmm1mXPV+UnKpnJkA3E
|
# ASYwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
|
||||||
# DsQOUWk8J6ojDurhrP536WI+3arg8PcnppHBLd/xNKYdlsTb+6qndgzKXkDDt1CV
|
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
|
||||||
# 4zCyuZ7bO8eyZAmNoSZz22k7vus9UjBz/CDhXylo20N43nr29rWPItUgH4uvOGQn
|
# b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw
|
||||||
# t26Y/yjBaQImz32psrfJEMbQ7cl789s8WOx8
|
# HhcNMTkxMjE5MDExNDU5WhcNMjEwMzE3MDExNDU5WjCBzjELMAkGA1UEBhMCVVMx
|
||||||
# SIG # End signature block
|
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
|
||||||
|
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9wZXJh
|
||||||
|
# dGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjYwQkMt
|
||||||
|
# RTM4My0yNjM1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl
|
||||||
|
# MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnjC+hpxO8w2VdBO18X8L
|
||||||
|
# Hk6XdfR9yNQ0y+MuBOY7n5YdgkVunvbk/f6q8UoNFAdYQjVLPSAHbi6tUMiNeMGH
|
||||||
|
# k1U0lUxAkja2W2/szj/ghuFklvfHNBbsuiUShlhRlqcFNS7KXL2iwKDijmOhWJPY
|
||||||
|
# a2bLEr4W/mQLbSXail5p6m138Ttx4MAVEzzuGI0Kwr8ofIL7z6zCeWDiBM57LrNC
|
||||||
|
# qHOA2wboeuMsG4O0Oz2LMAzBLbJZPRPnZAD2HdD4HUL2mzZ8wox74Mekb7RzrUP3
|
||||||
|
# hiHpxXZceJvhIEKfAgVkB5kTZQnio8A1JijMjw8f4TmsJPdJWpi8ei73sexe8/Yj
|
||||||
|
# cwIDAQABo4IBGzCCARcwHQYDVR0OBBYEFEmrrB8XsH6YQo3RWKZfxqM0DmFBMB8G
|
||||||
|
# A1UdIwQYMBaAFNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeG
|
||||||
|
# RWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Rp
|
||||||
|
# bVN0YVBDQV8yMDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUH
|
||||||
|
# MAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3Rh
|
||||||
|
# UENBXzIwMTAtMDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYB
|
||||||
|
# BQUHAwgwDQYJKoZIhvcNAQELBQADggEBAECW+51o6W/0J/O/npudfjVzMXq0u0cs
|
||||||
|
# HjqXpdRyH6o03jlmY5MXAui3cmPBKufijJxD2pMRPVMUNh3VA0PQuJeYrP06oFdq
|
||||||
|
# LpLxd3IJARm98vzaMgCz2nCwBDpe9X2M3Js9K1GAX+w4Az8N7J+Z6P1OD0VxHBdq
|
||||||
|
# eTaqDN1lk1vwagTN7t/WitxMXRDz0hRdYiWbATBAVgXXCOfzs3hnEv1n/EDab9HX
|
||||||
|
# OLMXKVY/+alqYKdV9lkuRp8Us1Q1WZy9z72Azu9x4mzft3fJ1puTjBHo5tHfixZo
|
||||||
|
# ummbI+WwjVCrku7pskJahfNi5amSgrqgR6nWAwvpJELccpVLdSxxmG0wggZxMIIE
|
||||||
|
# WaADAgECAgphCYEqAAAAAAACMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJV
|
||||||
|
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
|
||||||
|
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9v
|
||||||
|
# dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0xMDA3MDEyMTM2NTVaFw0y
|
||||||
|
# NTA3MDEyMTQ2NTVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
|
||||||
|
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
|
||||||
|
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIIBIjAN
|
||||||
|
# BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqR0NvHcRijog7PwTl/X6f2mUa3RU
|
||||||
|
# ENWlCgCChfvtfGhLLF/Fw+Vhwna3PmYrW/AVUycEMR9BGxqVHc4JE458YTBZsTBE
|
||||||
|
# D/FgiIRUQwzXTbg4CLNC3ZOs1nMwVyaCo0UN0Or1R4HNvyRgMlhgRvJYR4YyhB50
|
||||||
|
# YWeRX4FUsc+TTJLBxKZd0WETbijGGvmGgLvfYfxGwScdJGcSchohiq9LZIlQYrFd
|
||||||
|
# /XcfPfBXday9ikJNQFHRD5wGPmd/9WbAA5ZEfu/QS/1u5ZrKsajyeioKMfDaTgaR
|
||||||
|
# togINeh4HLDpmc085y9Euqf03GS9pAHBIAmTeM38vMDJRF1eFpwBBU8iTQIDAQAB
|
||||||
|
# o4IB5jCCAeIwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNVjOlyKMZDzQ3t8
|
||||||
|
# RhvFM2hahW1VMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIB
|
||||||
|
# hjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fO
|
||||||
|
# mhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w
|
||||||
|
# a2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggr
|
||||||
|
# BgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNv
|
||||||
|
# bS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MIGgBgNVHSAB
|
||||||
|
# Af8EgZUwgZIwgY8GCSsGAQQBgjcuAzCBgTA9BggrBgEFBQcCARYxaHR0cDovL3d3
|
||||||
|
# dy5taWNyb3NvZnQuY29tL1BLSS9kb2NzL0NQUy9kZWZhdWx0Lmh0bTBABggrBgEF
|
||||||
|
# BQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBQAG8AbABpAGMAeQBfAFMAdABhAHQAZQBt
|
||||||
|
# AGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEAB+aIUQ3ixuCYP4FxAz2do6Eh
|
||||||
|
# b7Prpsz1Mb7PBeKp/vpXbRkws8LFZslq3/Xn8Hi9x6ieJeP5vO1rVFcIK1GCRBL7
|
||||||
|
# uVOMzPRgEop2zEBAQZvcXBf/XPleFzWYJFZLdO9CEMivv3/Gf/I3fVo/HPKZeUqR
|
||||||
|
# UgCvOA8X9S95gWXZqbVr5MfO9sp6AG9LMEQkIjzP7QOllo9ZKby2/QThcJ8ySif9
|
||||||
|
# Va8v/rbljjO7Yl+a21dA6fHOmWaQjP9qYn/dxUoLkSbiOewZSnFjnXshbcOco6I8
|
||||||
|
# +n99lmqQeKZt0uGc+R38ONiU9MalCpaGpL2eGq4EQoO4tYCbIjggtSXlZOz39L9+
|
||||||
|
# Y1klD3ouOVd2onGqBooPiRa6YacRy5rYDkeagMXQzafQ732D8OE7cQnfXXSYIghh
|
||||||
|
# 2rBQHm+98eEA3+cxB6STOvdlR3jo+KhIq/fecn5ha293qYHLpwmsObvsxsvYgrRy
|
||||||
|
# zR30uIUBHoD7G4kqVDmyW9rIDVWZeodzOwjmmC3qjeAzLhIp9cAvVCch98isTtoo
|
||||||
|
# uLGp25ayp0Kiyc8ZQU3ghvkqmqMRZjDTu3QyS99je/WZii8bxyGvWbWu3EQ8l1Bx
|
||||||
|
# 16HSxVXjad5XwdHeMMD9zOZN+w2/XU/pnR4ZOC+8z1gFLu8NoFA12u8JJxzVs341
|
||||||
|
# Hgi62jbb01+P3nSISRKhggLSMIICOwIBATCB/KGB1KSB0TCBzjELMAkGA1UEBhMC
|
||||||
|
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
|
||||||
|
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9w
|
||||||
|
# ZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOjYw
|
||||||
|
# QkMtRTM4My0yNjM1MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2
|
||||||
|
# aWNloiMKAQEwBwYFKw4DAhoDFQAKZzI5aZnESumrToHx3Lqgxnr//KCBgzCBgKR+
|
||||||
|
# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
|
||||||
|
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT
|
||||||
|
# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA
|
||||||
|
# 4nuQTDAiGA8yMDIwMDUyOTE3NDQ0NFoYDzIwMjAwNTMwMTc0NDQ0WjB3MD0GCisG
|
||||||
|
# AQQBhFkKBAExLzAtMAoCBQDie5BMAgEAMAoCAQACAiZJAgH/MAcCAQACAhEjMAoC
|
||||||
|
# BQDifOHMAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA
|
||||||
|
# AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQADgYEAprmyJTXdH9FmQZ0I
|
||||||
|
# mRSJdjc/RrSqDm8DUEq/h3FL73G/xvg9MbQj1J/h3hdlSIPcQXjrhL8hud/vyF0j
|
||||||
|
# IFaTK5YOcixkX++9t7Vz3Mn0KkQo8F4DNSyZEPpz682AyKKwLMJDy52pFFFKNP5l
|
||||||
|
# NpOz6YY1Od1xvk4nyN1WwfLnGswxggMNMIIDCQIBATCBkzB8MQswCQYDVQQGEwJV
|
||||||
|
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
|
||||||
|
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt
|
||||||
|
# ZS1TdGFtcCBQQ0EgMjAxMAITMwAAASbfuksiuYKCBwAAAAABJjANBglghkgBZQME
|
||||||
|
# AgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJ
|
||||||
|
# BDEiBCB0IE0Q6P23RQlh8TFyp57UQQUF/sbui7mOMStRgTFZxTCB+gYLKoZIhvcN
|
||||||
|
# AQkQAi8xgeowgecwgeQwgb0EIDb9z++evV5wDO9qk5ZnbEZ8CTOuR+kZyu8xbTsJ
|
||||||
|
# CXUPMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
|
||||||
|
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
|
||||||
|
# bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAEm
|
||||||
|
# 37pLIrmCggcAAAAAASYwIgQgtwi02bvsGAOdpAxEF607G6g9PlyS8vc2bAUSHovH
|
||||||
|
# /IIwDQYJKoZIhvcNAQELBQAEggEAEMCfsXNudrjztjI6JNyNDVpdF1axRVcGiNy6
|
||||||
|
# 67pgb1EePsjA2EaBB+5ZjgO/73JxuiVgsoXgH7em8tKG5RQJtcm5obVDb+jKksK4
|
||||||
|
# qcFLA1f7seQRGfE06UAPnSFh2GqMtTNJGCXWwqWLH2LduTjOqPt8Nupo16ABFIT2
|
||||||
|
# akTzBSJ81EHBkEU0Et6CgeaZiBYrCCXUtD+ASvLDkPSrjweQGu3Zk1SSROEzxMY9
|
||||||
|
# jdlGfMkK2krMd9ub9UZ13RcQDijJqo+h6mz76pAuiFFvuQl6wMoSGFaaUQwfd+WQ
|
||||||
|
# gXlVVX/A9JFBihrxnDVglEPlsIOxCHkTeIxLfnAkCbax+9pevA==
|
||||||
|
# SIG # End signature block
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
# libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
apt install -y libicu66 || apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt' failed with exit code '$?'"
|
echo "'apt' failed with exit code '$?'"
|
||||||
@@ -99,8 +99,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
# libicu version prefer: libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
apt-get install -y libicu66 || apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
if [ $? -ne 0 ]
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
echo "'apt-get' failed with exit code '$?'"
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
|
|||||||
@@ -63,25 +63,12 @@ function install()
|
|||||||
|
|
||||||
sed "s/{{User}}/${run_as_user}/g; s/{{Description}}/$(echo ${SVC_DESCRIPTION} | sed -e 's/[\/&]/\\&/g')/g; s/{{RunnerRoot}}/$(echo ${RUNNER_ROOT} | sed -e 's/[\/&]/\\&/g')/g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
sed "s/{{User}}/${run_as_user}/g; s/{{Description}}/$(echo ${SVC_DESCRIPTION} | sed -e 's/[\/&]/\\&/g')/g; s/{{RunnerRoot}}/$(echo ${RUNNER_ROOT} | sed -e 's/[\/&]/\\&/g')/g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
||||||
mv "${TEMP_PATH}" "${UNIT_PATH}" || failed "failed to copy unit file"
|
mv "${TEMP_PATH}" "${UNIT_PATH}" || failed "failed to copy unit file"
|
||||||
|
|
||||||
# Recent Fedora based Linux (CentOS/Redhat) has SELinux enabled by default
|
|
||||||
# We need to restore security context on the unit file we added otherwise SystemD have no access to it.
|
|
||||||
command -v getenforce > /dev/null
|
|
||||||
if [ $? -eq 0 ]
|
|
||||||
then
|
|
||||||
selinuxEnabled=$(getenforce)
|
|
||||||
if [[ $selinuxEnabled == "Enforcing" ]]
|
|
||||||
then
|
|
||||||
# SELinux is enabled, we will need to Restore SELinux Context for the service file
|
|
||||||
restorecon -r -v "${UNIT_PATH}" || failed "failed to restore SELinux context on ${UNIT_PATH}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# unit file should not be executable and world writable
|
# unit file should not be executable and world writable
|
||||||
chmod 664 "${UNIT_PATH}" || failed "failed to set permissions on ${UNIT_PATH}"
|
chmod 664 ${UNIT_PATH} || failed "failed to set permissions on ${UNIT_PATH}"
|
||||||
systemctl daemon-reload || failed "failed to reload daemons"
|
systemctl daemon-reload || failed "failed to reload daemons"
|
||||||
|
|
||||||
# Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user.
|
# Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user.
|
||||||
cp ./bin/runsvc.sh ./runsvc.sh || failed "failed to copy runsvc.sh"
|
cp ./bin/runsvc.sh ./runsvc.sh || failed "failed to copy runsvc.sh"
|
||||||
chown ${run_as_uid}:${run_as_gid} ./runsvc.sh || failed "failed to set owner for runsvc.sh"
|
chown ${run_as_uid}:${run_as_gid} ./runsvc.sh || failed "failed to set owner for runsvc.sh"
|
||||||
chmod 755 ./runsvc.sh || failed "failed to set permission for runsvc.sh"
|
chmod 755 ./runsvc.sh || failed "failed to set permission for runsvc.sh"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ namespace GitHub.Runner.Common
|
|||||||
Task<List<TimelineRecord>> UpdateTimelineRecordsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
|
Task<List<TimelineRecord>> UpdateTimelineRecordsAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, IEnumerable<TimelineRecord> records, CancellationToken cancellationToken);
|
||||||
Task RaisePlanEventAsync<T>(Guid scopeIdentifier, string hubName, Guid planId, T eventData, CancellationToken cancellationToken) where T : JobEvent;
|
Task RaisePlanEventAsync<T>(Guid scopeIdentifier, string hubName, Guid planId, T eventData, CancellationToken cancellationToken) where T : JobEvent;
|
||||||
Task<Timeline> GetTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken);
|
Task<Timeline> GetTimelineAsync(Guid scopeIdentifier, string hubName, Guid planId, Guid timelineId, CancellationToken cancellationToken);
|
||||||
Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, ActionReferenceList actions, CancellationToken cancellationToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class JobServer : RunnerService, IJobServer
|
public sealed class JobServer : RunnerService, IJobServer
|
||||||
@@ -114,14 +113,5 @@ namespace GitHub.Runner.Common
|
|||||||
CheckConnection();
|
CheckConnection();
|
||||||
return _taskClient.GetTimelineAsync(scopeIdentifier, hubName, planId, timelineId, includeRecords: true, cancellationToken: cancellationToken);
|
return _taskClient.GetTimelineAsync(scopeIdentifier, hubName, planId, timelineId, includeRecords: true, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
// Action download info
|
|
||||||
//-----------------------------------------------------------------
|
|
||||||
public Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(Guid scopeIdentifier, string hubName, Guid planId, ActionReferenceList actions, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
return _taskClient.ResolveActionDownloadInfoAsync(scopeIdentifier, hubName, planId, actions, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
else if (command.Unattended)
|
else if (command.Unattended)
|
||||||
{
|
{
|
||||||
// if not replace and it is unattended config.
|
// if not replace and it is unattended config.
|
||||||
throw new TaskAgentExistsException($"A runner exists with the same name {runnerSettings.AgentName}.");
|
throw new TaskAgentExistsException($"Pool {runnerSettings.PoolId} already contains a runner with name {runnerSettings.AgentName}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -346,16 +346,16 @@ namespace GitHub.Runner.Sdk
|
|||||||
// data buffers one last time before returning
|
// data buffers one last time before returning
|
||||||
ProcessOutput();
|
ProcessOutput();
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
// Ensure cancellation also finish on the cancellationToken.Register thread.
|
|
||||||
await cancellationFinished.Task;
|
|
||||||
Trace.Info($"Process Cancellation finished.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}.");
|
Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
// Ensure cancellation also finish on the cancellationToken.Register thread.
|
||||||
|
await cancellationFinished.Task;
|
||||||
|
Trace.Info($"Process Cancellation finished.");
|
||||||
|
}
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
// Wait for process to finish.
|
// Wait for process to finish.
|
||||||
|
|||||||
@@ -11,11 +11,6 @@ namespace GitHub.Runner.Sdk
|
|||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(command, nameof(command));
|
ArgUtil.NotNullOrEmpty(command, nameof(command));
|
||||||
trace?.Info($"Which: '{command}'");
|
trace?.Info($"Which: '{command}'");
|
||||||
if (Path.IsPathFullyQualified(command) && File.Exists(command))
|
|
||||||
{
|
|
||||||
trace?.Info($"Fully qualified path: '{command}'");
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
string path = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
|
string path = Environment.GetEnvironmentVariable(PathUtil.PathVariable);
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ using GitHub.Runner.Common;
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using WebApi = GitHub.DistributedTask.WebApi;
|
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants;
|
using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants;
|
||||||
|
|
||||||
@@ -395,12 +394,6 @@ namespace GitHub.Runner.Worker
|
|||||||
Trace.Info($"Action cleanup plugin: {plugin.PluginTypeName}.");
|
Trace.Info($"Action cleanup plugin: {plugin.PluginTypeName}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (definition.Data.Execution.ExecutionType == ActionExecutionType.Composite && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
var compositeAction = definition.Data.Execution as CompositeActionExecutionData;
|
|
||||||
Trace.Info($"Load {compositeAction.Steps.Count} action steps.");
|
|
||||||
Trace.Verbose($"Details: {StringUtil.ConvertToJson(compositeAction.Steps)}");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(definition.Data.Execution.ExecutionType.ToString());
|
throw new NotSupportedException(definition.Data.Execution.ExecutionType.ToString());
|
||||||
@@ -552,77 +545,124 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This implementation is temporary and will be replaced with a REST API call to the service to resolve
|
// This implementation is temporary and will be removed when we switch to a REST API call to the service to resolve the download info
|
||||||
private async Task<IDictionary<string, WebApi.ActionDownloadInfo>> GetDownloadInfoAsync(IExecutionContext executionContext, List<Pipelines.ActionStep> actions)
|
private async Task<bool> RepoExistsAsync(IExecutionContext executionContext, Pipelines.RepositoryPathReference repositoryReference, string authorization)
|
||||||
{
|
{
|
||||||
executionContext.Output("Getting action download info");
|
var apiUrl = GetApiUrl(executionContext);
|
||||||
|
var repoUrl = $"{apiUrl}/repos/{repositoryReference.Name}";
|
||||||
// Convert to action reference
|
|
||||||
var actionReferences = actions
|
|
||||||
.GroupBy(x => GetDownloadInfoLookupKey(x))
|
|
||||||
.Where(x => !string.IsNullOrEmpty(x.Key))
|
|
||||||
.Select(x =>
|
|
||||||
{
|
|
||||||
var action = x.First();
|
|
||||||
var repositoryReference = action.Reference as Pipelines.RepositoryPathReference;
|
|
||||||
ArgUtil.NotNull(repositoryReference, nameof(repositoryReference));
|
|
||||||
return new WebApi.ActionReference
|
|
||||||
{
|
|
||||||
NameWithOwner = repositoryReference.Name,
|
|
||||||
Ref = repositoryReference.Ref,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Nothing to resolve?
|
|
||||||
if (actionReferences.Count == 0)
|
|
||||||
{
|
|
||||||
return new Dictionary<string, WebApi.ActionDownloadInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve download info
|
|
||||||
var jobServer = HostContext.GetService<IJobServer>();
|
|
||||||
var actionDownloadInfos = default(WebApi.ActionDownloadInfoCollection);
|
|
||||||
for (var attempt = 1; attempt <= 3; attempt++)
|
for (var attempt = 1; attempt <= 3; attempt++)
|
||||||
{
|
{
|
||||||
|
executionContext.Debug($"Checking whether repo exists: {repoUrl}");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
actionDownloadInfos = await jobServer.ResolveActionDownloadInfoAsync(executionContext.Plan.ScopeIdentifier, executionContext.Plan.PlanType, executionContext.Plan.PlanId, new WebApi.ActionReferenceList { Actions = actionReferences }, executionContext.CancellationToken);
|
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||||
break;
|
using (var httpClient = new HttpClient(httpClientHandler))
|
||||||
}
|
|
||||||
catch (Exception ex) when (attempt < 3)
|
|
||||||
{
|
|
||||||
executionContext.Output($"Failed to resolve action download info. Error: {ex.Message}");
|
|
||||||
executionContext.Debug(ex.ToString());
|
|
||||||
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GITHUB_ACTION_DOWNLOAD_NO_BACKOFF")))
|
|
||||||
{
|
{
|
||||||
var backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
|
httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(authorization);
|
||||||
executionContext.Output($"Retrying in {backoff.TotalSeconds} seconds");
|
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
await Task.Delay(backoff);
|
using (var response = await httpClient.GetAsync(repoUrl))
|
||||||
|
{
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (response.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Throw
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (attempt < 3)
|
||||||
|
{
|
||||||
|
executionContext.Debug($"Failed checking whether repo '{repositoryReference.Name}' exists: {ex.Message}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
executionContext.Error($"Failed checking whether repo '{repositoryReference.Name}' exists: {ex.Message}");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgUtil.NotNull(actionDownloadInfos, nameof(actionDownloadInfos));
|
return false; // Never reaches here
|
||||||
ArgUtil.NotNull(actionDownloadInfos.Actions, nameof(actionDownloadInfos.Actions));
|
}
|
||||||
var apiUrl = GetApiUrl(executionContext);
|
|
||||||
var defaultAccessToken = executionContext.GetGitHubContext("token");
|
// This implementation is temporary and will be replaced with a REST API call to the service to resolve
|
||||||
|
private async Task<Dictionary<string, ActionDownloadInfo>> GetDownloadInfoAsync(IExecutionContext executionContext, List<Pipelines.ActionStep> actions)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, ActionDownloadInfo>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||||
var runnerSettings = configurationStore.GetSettings();
|
var runnerSettings = configurationStore.GetSettings();
|
||||||
|
var apiUrl = GetApiUrl(executionContext);
|
||||||
|
var accessToken = executionContext.GetGitHubContext("token");
|
||||||
|
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{accessToken}"));
|
||||||
|
var authorization = $"Basic {base64EncodingToken}";
|
||||||
|
|
||||||
foreach (var actionDownloadInfo in actionDownloadInfos.Actions.Values)
|
foreach (var action in actions)
|
||||||
{
|
{
|
||||||
// Add secret
|
var lookupKey = GetDownloadInfoLookupKey(action);
|
||||||
HostContext.SecretMasker.AddValue(actionDownloadInfo.Authentication?.Token);
|
if (string.IsNullOrEmpty(lookupKey) || result.ContainsKey(lookupKey))
|
||||||
|
|
||||||
// Default auth token
|
|
||||||
if (string.IsNullOrEmpty(actionDownloadInfo.Authentication?.Token))
|
|
||||||
{
|
{
|
||||||
actionDownloadInfo.Authentication = new WebApi.ActionDownloadAuthentication { Token = defaultAccessToken };
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var repositoryReference = action.Reference as Pipelines.RepositoryPathReference;
|
||||||
|
ArgUtil.NotNull(repositoryReference, nameof(repositoryReference));
|
||||||
|
|
||||||
|
var downloadInfo = default(ActionDownloadInfo);
|
||||||
|
|
||||||
|
if (runnerSettings.IsHostedServer)
|
||||||
|
{
|
||||||
|
downloadInfo = new ActionDownloadInfo
|
||||||
|
{
|
||||||
|
NameWithOwner = repositoryReference.Name,
|
||||||
|
Ref = repositoryReference.Ref,
|
||||||
|
ArchiveLink = BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref),
|
||||||
|
Authorization = authorization,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Test whether the repo exists in the instance
|
||||||
|
else if (await RepoExistsAsync(executionContext, repositoryReference, authorization))
|
||||||
|
{
|
||||||
|
downloadInfo = new ActionDownloadInfo
|
||||||
|
{
|
||||||
|
NameWithOwner = repositoryReference.Name,
|
||||||
|
Ref = repositoryReference.Ref,
|
||||||
|
ArchiveLink = BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref),
|
||||||
|
Authorization = authorization,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Fallback to dotcom
|
||||||
|
else
|
||||||
|
{
|
||||||
|
downloadInfo = new ActionDownloadInfo
|
||||||
|
{
|
||||||
|
NameWithOwner = repositoryReference.Name,
|
||||||
|
Ref = repositoryReference.Ref,
|
||||||
|
ArchiveLink = BuildLinkToActionArchive(_dotcomApiUrl, repositoryReference.Name, repositoryReference.Ref),
|
||||||
|
Authorization = null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(lookupKey, downloadInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionDownloadInfos.Actions;
|
// Register secrets
|
||||||
|
foreach (var downloadInfo in result.Values)
|
||||||
|
{
|
||||||
|
HostContext.SecretMasker.AddValue(downloadInfo.Authorization);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Remove when feature flag DistributedTask.NewActionMetadata is removed
|
// todo: Remove when feature flag DistributedTask.NewActionMetadata is removed
|
||||||
@@ -669,6 +709,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
string apiUrl = GetApiUrl(executionContext);
|
string apiUrl = GetApiUrl(executionContext);
|
||||||
string archiveLink = BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref);
|
string archiveLink = BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref);
|
||||||
|
Trace.Info($"Download archive '{archiveLink}' to '{destDirectory}'.");
|
||||||
var downloadDetails = new ActionDownloadDetails(archiveLink, ConfigureAuthorizationFromContext);
|
var downloadDetails = new ActionDownloadDetails(archiveLink, ConfigureAuthorizationFromContext);
|
||||||
await DownloadRepositoryActionAsync(executionContext, downloadDetails, null, destDirectory);
|
await DownloadRepositoryActionAsync(executionContext, downloadDetails, null, destDirectory);
|
||||||
return;
|
return;
|
||||||
@@ -694,6 +735,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
foreach (var downloadAttempt in downloadAttempts)
|
foreach (var downloadAttempt in downloadAttempts)
|
||||||
{
|
{
|
||||||
|
Trace.Info($"Download archive '{downloadAttempt.ArchiveLink}' to '{destDirectory}'.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await DownloadRepositoryActionAsync(executionContext, downloadAttempt, null, destDirectory);
|
await DownloadRepositoryActionAsync(executionContext, downloadAttempt, null, destDirectory);
|
||||||
@@ -709,7 +751,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, WebApi.ActionDownloadInfo downloadInfo)
|
private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, ActionDownloadInfo downloadInfo)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||||
@@ -732,6 +774,7 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Output($"Download action repository '{downloadInfo.NameWithOwner}@{downloadInfo.Ref}'");
|
executionContext.Output($"Download action repository '{downloadInfo.NameWithOwner}@{downloadInfo.Ref}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Trace.Info($"Download archive '{downloadInfo.ArchiveLink}' to '{destDirectory}'.");
|
||||||
await DownloadRepositoryActionAsync(executionContext, null, downloadInfo, destDirectory);
|
await DownloadRepositoryActionAsync(executionContext, null, downloadInfo, destDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -756,7 +799,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo: Remove the parameter "actionDownloadDetails" when feature flag DistributedTask.NewActionMetadata is removed
|
// todo: Remove the parameter "actionDownloadDetails" when feature flag DistributedTask.NewActionMetadata is removed
|
||||||
private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, ActionDownloadDetails actionDownloadDetails, WebApi.ActionDownloadInfo downloadInfo, string destDirectory)
|
private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, ActionDownloadDetails actionDownloadDetails, ActionDownloadInfo downloadInfo, string destDirectory)
|
||||||
{
|
{
|
||||||
//download and extract action in a temp folder and rename it on success
|
//download and extract action in a temp folder and rename it on success
|
||||||
string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), "_temp_" + Guid.NewGuid());
|
string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), "_temp_" + Guid.NewGuid());
|
||||||
@@ -764,12 +807,11 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.zip");
|
string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.zip");
|
||||||
string link = downloadInfo?.ZipballUrl ?? actionDownloadDetails.ArchiveLink;
|
|
||||||
#else
|
#else
|
||||||
string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.tar.gz");
|
string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.tar.gz");
|
||||||
string link = downloadInfo?.TarballUrl ?? actionDownloadDetails.ArchiveLink;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
string link = downloadInfo != null ? downloadInfo.ArchiveLink : actionDownloadDetails.ArchiveLink;
|
||||||
Trace.Info($"Save archive '{link}' into {archiveFile}.");
|
Trace.Info($"Save archive '{link}' into {archiveFile}.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -797,7 +839,7 @@ namespace GitHub.Runner.Worker
|
|||||||
// FF DistributedTask.NewActionMetadata
|
// FF DistributedTask.NewActionMetadata
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(downloadInfo.Authentication?.Token);
|
httpClient.DefaultRequestHeaders.Authorization = CreateAuthHeader(downloadInfo.Authorization);
|
||||||
}
|
}
|
||||||
|
|
||||||
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||||
@@ -1044,11 +1086,6 @@ namespace GitHub.Runner.Worker
|
|||||||
Trace.Info($"Action plugin: {(actionDefinitionData.Execution as PluginActionExecutionData).Plugin}, no more preparation.");
|
Trace.Info($"Action plugin: {(actionDefinitionData.Execution as PluginActionExecutionData).Plugin}, no more preparation.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (actionDefinitionData.Execution.ExecutionType == ActionExecutionType.Composite && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
Trace.Info($"Action composite: {(actionDefinitionData.Execution as CompositeActionExecutionData).Steps}, no more preparation.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(actionDefinitionData.Execution.ExecutionType.ToString());
|
throw new NotSupportedException(actionDefinitionData.Execution.ExecutionType.ToString());
|
||||||
@@ -1100,23 +1137,20 @@ namespace GitHub.Runner.Worker
|
|||||||
return $"{repositoryReference.Name}@{repositoryReference.Ref}";
|
return $"{repositoryReference.Name}@{repositoryReference.Ref}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDownloadInfoLookupKey(WebApi.ActionDownloadInfo info)
|
private static AuthenticationHeaderValue CreateAuthHeader(string authorization)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNullOrEmpty(info.NameWithOwner, nameof(info.NameWithOwner));
|
if (string.IsNullOrEmpty(authorization))
|
||||||
ArgUtil.NotNullOrEmpty(info.Ref, nameof(info.Ref));
|
|
||||||
return $"{info.NameWithOwner}@{info.Ref}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private AuthenticationHeaderValue CreateAuthHeader(string token)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(token))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{token}"));
|
var split = authorization.Split(new char[] { ' ' }, 2);
|
||||||
HostContext.SecretMasker.AddValue(base64EncodingToken);
|
if (split.Length != 2 || string.IsNullOrWhiteSpace(split[0]) || string.IsNullOrWhiteSpace(split[1]))
|
||||||
return new AuthenticationHeaderValue("Basic", base64EncodingToken);
|
{
|
||||||
|
throw new Exception("Unexpected authorization header format");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AuthenticationHeaderValue(split[0].Trim(), split[1].Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Remove when feature flag DistributedTask.NewActionMetadata is removed
|
// todo: Remove when feature flag DistributedTask.NewActionMetadata is removed
|
||||||
@@ -1132,6 +1166,17 @@ namespace GitHub.Runner.Worker
|
|||||||
ConfigureAuthorization = configureAuthorization;
|
ConfigureAuthorization = configureAuthorization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ActionDownloadInfo
|
||||||
|
{
|
||||||
|
public string NameWithOwner { get; set; }
|
||||||
|
|
||||||
|
public string Ref { get; set; }
|
||||||
|
|
||||||
|
public string ArchiveLink { get; set; }
|
||||||
|
|
||||||
|
public string Authorization { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class Definition
|
public sealed class Definition
|
||||||
@@ -1159,7 +1204,6 @@ namespace GitHub.Runner.Worker
|
|||||||
NodeJS,
|
NodeJS,
|
||||||
Plugin,
|
Plugin,
|
||||||
Script,
|
Script,
|
||||||
Composite,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ContainerActionExecutionData : ActionExecutionData
|
public sealed class ContainerActionExecutionData : ActionExecutionData
|
||||||
@@ -1216,14 +1260,6 @@ namespace GitHub.Runner.Worker
|
|||||||
public override bool HasPost => false;
|
public override bool HasPost => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class CompositeActionExecutionData : ActionExecutionData
|
|
||||||
{
|
|
||||||
public override ActionExecutionType ExecutionType => ActionExecutionType.Composite;
|
|
||||||
public override bool HasPre => false;
|
|
||||||
public override bool HasPost => false;
|
|
||||||
public List<Pipelines.ActionStep> Steps { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class ActionExecutionData
|
public abstract class ActionExecutionData
|
||||||
{
|
{
|
||||||
private string _initCondition = $"{Constants.Expressions.Always}()";
|
private string _initCondition = $"{Constants.Expressions.Always}()";
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ using YamlDotNet.Core;
|
|||||||
using YamlDotNet.Core.Events;
|
using YamlDotNet.Core.Events;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker
|
namespace GitHub.Runner.Worker
|
||||||
{
|
{
|
||||||
@@ -33,6 +32,8 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class ActionManifestManager : RunnerService, IActionManifestManager
|
public sealed class ActionManifestManager : RunnerService, IActionManifestManager
|
||||||
{
|
{
|
||||||
private TemplateSchema _actionManifestSchema;
|
private TemplateSchema _actionManifestSchema;
|
||||||
|
private IReadOnlyList<String> _fileTable;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
base.Initialize(hostContext);
|
base.Initialize(hostContext);
|
||||||
@@ -53,39 +54,22 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public ActionDefinitionData Load(IExecutionContext executionContext, string manifestFile)
|
public ActionDefinitionData Load(IExecutionContext executionContext, string manifestFile)
|
||||||
{
|
{
|
||||||
var templateContext = CreateContext(executionContext);
|
var context = CreateContext(executionContext);
|
||||||
ActionDefinitionData actionDefinition = new ActionDefinitionData();
|
ActionDefinitionData actionDefinition = new ActionDefinitionData();
|
||||||
|
|
||||||
// Clean up file name real quick
|
|
||||||
// Instead of using Regex which can be computationally expensive,
|
|
||||||
// we can just remove the # of characters from the fileName according to the length of the basePath
|
|
||||||
string basePath = HostContext.GetDirectory(WellKnownDirectory.Actions);
|
|
||||||
string fileRelativePath = manifestFile;
|
|
||||||
if (manifestFile.Contains(basePath))
|
|
||||||
{
|
|
||||||
fileRelativePath = manifestFile.Remove(0, basePath.Length + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var token = default(TemplateToken);
|
var token = default(TemplateToken);
|
||||||
|
|
||||||
// Get the file ID
|
// Get the file ID
|
||||||
var fileId = templateContext.GetFileId(fileRelativePath);
|
var fileId = context.GetFileId(manifestFile);
|
||||||
|
_fileTable = context.GetFileTable();
|
||||||
// Add this file to the FileTable in executionContext if it hasn't been added already
|
|
||||||
// we use > since fileID is 1 indexed
|
|
||||||
if (fileId > executionContext.FileTable.Count)
|
|
||||||
{
|
|
||||||
executionContext.FileTable.Add(fileRelativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the file
|
// Read the file
|
||||||
var fileContent = File.ReadAllText(manifestFile);
|
var fileContent = File.ReadAllText(manifestFile);
|
||||||
using (var stringReader = new StringReader(fileContent))
|
using (var stringReader = new StringReader(fileContent))
|
||||||
{
|
{
|
||||||
var yamlObjectReader = new YamlObjectReader(fileId, stringReader);
|
var yamlObjectReader = new YamlObjectReader(null, stringReader);
|
||||||
token = TemplateReader.Read(templateContext, "action-root", yamlObjectReader, fileId, out _);
|
token = TemplateReader.Read(context, "action-root", yamlObjectReader, fileId, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionMapping = token.AssertMapping("action manifest root");
|
var actionMapping = token.AssertMapping("action manifest root");
|
||||||
@@ -104,11 +88,11 @@ namespace GitHub.Runner.Worker
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "inputs":
|
case "inputs":
|
||||||
ConvertInputs(templateContext, actionPair.Value, actionDefinition);
|
ConvertInputs(context, actionPair.Value, actionDefinition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "runs":
|
case "runs":
|
||||||
actionDefinition.Execution = ConvertRuns(executionContext, templateContext, actionPair.Value);
|
actionDefinition.Execution = ConvertRuns(context, actionPair.Value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Trace.Info($"Ignore action property {propertyName}.");
|
Trace.Info($"Ignore action property {propertyName}.");
|
||||||
@@ -119,24 +103,24 @@ namespace GitHub.Runner.Worker
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Trace.Error(ex);
|
Trace.Error(ex);
|
||||||
templateContext.Errors.Add(ex);
|
context.Errors.Add(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (templateContext.Errors.Count > 0)
|
if (context.Errors.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var error in templateContext.Errors)
|
foreach (var error in context.Errors)
|
||||||
{
|
{
|
||||||
Trace.Error($"Action.yml load error: {error.Message}");
|
Trace.Error($"Action.yml load error: {error.Message}");
|
||||||
executionContext.Error(error.Message);
|
executionContext.Error(error.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Fail to load {fileRelativePath}");
|
throw new ArgumentException($"Fail to load {manifestFile}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionDefinition.Execution == null)
|
if (actionDefinition.Execution == null)
|
||||||
{
|
{
|
||||||
executionContext.Debug($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}");
|
executionContext.Debug($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}");
|
||||||
throw new ArgumentException($"Top level 'runs:' section is required for {fileRelativePath}");
|
throw new ArgumentException($"Top level 'runs:' section is required for {manifestFile}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -297,17 +281,19 @@ namespace GitHub.Runner.Worker
|
|||||||
result.ExpressionFunctions.Add(item);
|
result.ExpressionFunctions.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the file table from the Execution Context
|
// Add the file table
|
||||||
for (var i = 0; i < executionContext.FileTable.Count; i++)
|
if (_fileTable?.Count > 0)
|
||||||
{
|
{
|
||||||
result.GetFileId(executionContext.FileTable[i]);
|
for (var i = 0 ; i < _fileTable.Count ; i++)
|
||||||
|
{
|
||||||
|
result.GetFileId(_fileTable[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionExecutionData ConvertRuns(
|
private ActionExecutionData ConvertRuns(
|
||||||
IExecutionContext executionContext,
|
|
||||||
TemplateContext context,
|
TemplateContext context,
|
||||||
TemplateToken inputsToken)
|
TemplateToken inputsToken)
|
||||||
{
|
{
|
||||||
@@ -325,8 +311,6 @@ namespace GitHub.Runner.Worker
|
|||||||
var postToken = default(StringToken);
|
var postToken = default(StringToken);
|
||||||
var postEntrypointToken = default(StringToken);
|
var postEntrypointToken = default(StringToken);
|
||||||
var postIfToken = default(StringToken);
|
var postIfToken = default(StringToken);
|
||||||
var stepsLoaded = default(List<Pipelines.ActionStep>);
|
|
||||||
|
|
||||||
foreach (var run in runsMapping)
|
foreach (var run in runsMapping)
|
||||||
{
|
{
|
||||||
var runsKey = run.Key.AssertString("runs key").Value;
|
var runsKey = run.Key.AssertString("runs key").Value;
|
||||||
@@ -371,15 +355,6 @@ namespace GitHub.Runner.Worker
|
|||||||
case "pre-if":
|
case "pre-if":
|
||||||
preIfToken = run.Value.AssertString("pre-if");
|
preIfToken = run.Value.AssertString("pre-if");
|
||||||
break;
|
break;
|
||||||
case "steps":
|
|
||||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
var steps = run.Value.AssertSequence("steps");
|
|
||||||
var evaluator = executionContext.ToPipelineTemplateEvaluator();
|
|
||||||
stepsLoaded = evaluator.LoadCompositeSteps(steps);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
throw new Exception("You aren't supposed to be using Composite Actions yet!");
|
|
||||||
default:
|
default:
|
||||||
Trace.Info($"Ignore run property {runsKey}.");
|
Trace.Info($"Ignore run property {runsKey}.");
|
||||||
break;
|
break;
|
||||||
@@ -427,21 +402,6 @@ namespace GitHub.Runner.Worker
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (string.Equals(usingToken.Value, "composite", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
if (stepsLoaded == null)
|
|
||||||
{
|
|
||||||
// TODO: Add a more helpful error message + including file name, etc. to show user that it's because of their yaml file
|
|
||||||
throw new ArgumentNullException($"No steps provided.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new CompositeActionExecutionData()
|
|
||||||
{
|
|
||||||
Steps = stepsLoaded,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker' or 'node12' instead.");
|
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker' or 'node12' instead.");
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace GitHub.Runner.Worker
|
|||||||
TaskResult? CommandResult { get; set; }
|
TaskResult? CommandResult { get; set; }
|
||||||
CancellationToken CancellationToken { get; }
|
CancellationToken CancellationToken { get; }
|
||||||
List<ServiceEndpoint> Endpoints { get; }
|
List<ServiceEndpoint> Endpoints { get; }
|
||||||
TaskOrchestrationPlanReference Plan { get; }
|
|
||||||
|
|
||||||
PlanFeatures Features { get; }
|
PlanFeatures Features { get; }
|
||||||
Variables Variables { get; }
|
Variables Variables { get; }
|
||||||
@@ -63,7 +62,7 @@ namespace GitHub.Runner.Worker
|
|||||||
JobContext JobContext { get; }
|
JobContext JobContext { get; }
|
||||||
|
|
||||||
// Only job level ExecutionContext has JobSteps
|
// Only job level ExecutionContext has JobSteps
|
||||||
List<IStep> JobSteps { get; }
|
Queue<IStep> JobSteps { get; }
|
||||||
|
|
||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
Stack<IStep> PostJobSteps { get; }
|
Stack<IStep> PostJobSteps { get; }
|
||||||
@@ -105,7 +104,6 @@ namespace GitHub.Runner.Worker
|
|||||||
// others
|
// others
|
||||||
void ForceTaskComplete();
|
void ForceTaskComplete();
|
||||||
void RegisterPostJobStep(IStep step);
|
void RegisterPostJobStep(IStep step);
|
||||||
void RegisterNestedStep(IStep step, DictionaryContextData inputsData, int location, Dictionary<string, string> envData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
||||||
@@ -143,7 +141,6 @@ namespace GitHub.Runner.Worker
|
|||||||
public Task ForceCompleted => _forceCompleted.Task;
|
public Task ForceCompleted => _forceCompleted.Task;
|
||||||
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
|
||||||
public List<ServiceEndpoint> Endpoints { get; private set; }
|
public List<ServiceEndpoint> Endpoints { get; private set; }
|
||||||
public TaskOrchestrationPlanReference Plan { get; private set; }
|
|
||||||
public Variables Variables { get; private set; }
|
public Variables Variables { get; private set; }
|
||||||
public Dictionary<string, string> IntraActionState { get; private set; }
|
public Dictionary<string, string> IntraActionState { get; private set; }
|
||||||
public IDictionary<String, IDictionary<String, String>> JobDefaults { get; private set; }
|
public IDictionary<String, IDictionary<String, String>> JobDefaults { get; private set; }
|
||||||
@@ -160,7 +157,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public List<ContainerInfo> ServiceContainers { get; private set; }
|
public List<ContainerInfo> ServiceContainers { get; private set; }
|
||||||
|
|
||||||
// Only job level ExecutionContext has JobSteps
|
// Only job level ExecutionContext has JobSteps
|
||||||
public List<IStep> JobSteps { get; private set; }
|
public Queue<IStep> JobSteps { get; private set; }
|
||||||
|
|
||||||
// Only job level ExecutionContext has PostJobSteps
|
// Only job level ExecutionContext has PostJobSteps
|
||||||
public Stack<IStep> PostJobSteps { get; private set; }
|
public Stack<IStep> PostJobSteps { get; private set; }
|
||||||
@@ -170,6 +167,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
public bool EchoOnActionCommand { get; set; }
|
public bool EchoOnActionCommand { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public TaskResult? Result
|
public TaskResult? Result
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -266,35 +264,6 @@ namespace GitHub.Runner.Worker
|
|||||||
Root.PostJobSteps.Push(step);
|
Root.PostJobSteps.Push(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper function used in CompositeActionHandler::RunAsync to
|
|
||||||
/// add a child node, aka a step, to the current job to the Root.JobSteps based on the location.
|
|
||||||
/// </summary>
|
|
||||||
public void RegisterNestedStep(IStep step, DictionaryContextData inputsData, int location, Dictionary<string, string> envData)
|
|
||||||
{
|
|
||||||
// TODO: For UI purposes, look at figuring out how to condense steps in one node => maybe use the same previous GUID
|
|
||||||
var newGuid = Guid.NewGuid();
|
|
||||||
step.ExecutionContext = Root.CreateChild(newGuid, step.DisplayName, newGuid.ToString("N"), null, null);
|
|
||||||
step.ExecutionContext.ExpressionValues["inputs"] = inputsData;
|
|
||||||
|
|
||||||
// Add the composite action environment variables to each step.
|
|
||||||
// If the key already exists, we override it since the composite action env variables will have higher precedence
|
|
||||||
// Note that for each composite action step, it's environment variables will be set in the StepRunner automatically
|
|
||||||
// step.ExecutionContext.SetEnvironmentVariables(envData);
|
|
||||||
#if OS_WINDOWS
|
|
||||||
var envContext = new DictionaryContextData();
|
|
||||||
#else
|
|
||||||
var envContext = new CaseSensitiveDictionaryContextData();
|
|
||||||
#endif
|
|
||||||
foreach (var pair in envData)
|
|
||||||
{
|
|
||||||
envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty);
|
|
||||||
}
|
|
||||||
step.ExecutionContext.ExpressionValues["env"] = envContext;
|
|
||||||
|
|
||||||
Root.JobSteps.Insert(location, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
@@ -306,7 +275,6 @@ namespace GitHub.Runner.Worker
|
|||||||
child.Features = Features;
|
child.Features = Features;
|
||||||
child.Variables = Variables;
|
child.Variables = Variables;
|
||||||
child.Endpoints = Endpoints;
|
child.Endpoints = Endpoints;
|
||||||
child.Plan = Plan;
|
|
||||||
if (intraActionState == null)
|
if (intraActionState == null)
|
||||||
{
|
{
|
||||||
child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
child.IntraActionState = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -608,8 +576,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
|
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
|
||||||
|
|
||||||
// Plan
|
// Features
|
||||||
Plan = message.Plan;
|
|
||||||
Features = PlanUtil.GetFeatures(message.Plan);
|
Features = PlanUtil.GetFeatures(message.Plan);
|
||||||
|
|
||||||
// Endpoints
|
// Endpoints
|
||||||
@@ -689,7 +656,7 @@ namespace GitHub.Runner.Worker
|
|||||||
PrependPath = new List<string>();
|
PrependPath = new List<string>();
|
||||||
|
|
||||||
// JobSteps for job ExecutionContext
|
// JobSteps for job ExecutionContext
|
||||||
JobSteps = new List<IStep>();
|
JobSteps = new Queue<IStep>();
|
||||||
|
|
||||||
// PostJobSteps for job ExecutionContext
|
// PostJobSteps for job ExecutionContext
|
||||||
PostJobSteps = new Stack<IStep>();
|
PostJobSteps = new Stack<IStep>();
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Runner.Common;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
|
||||||
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker.Handlers
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(CompositeActionHandler))]
|
|
||||||
public interface ICompositeActionHandler : IHandler
|
|
||||||
{
|
|
||||||
CompositeActionExecutionData Data { get; set; }
|
|
||||||
}
|
|
||||||
public sealed class CompositeActionHandler : Handler, ICompositeActionHandler
|
|
||||||
{
|
|
||||||
public CompositeActionExecutionData Data { get; set; }
|
|
||||||
|
|
||||||
public Task RunAsync(ActionRunStage stage)
|
|
||||||
{
|
|
||||||
// Validate args.
|
|
||||||
Trace.Entering();
|
|
||||||
ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));
|
|
||||||
ArgUtil.NotNull(Inputs, nameof(Inputs));
|
|
||||||
|
|
||||||
var githubContext = ExecutionContext.ExpressionValues["github"] as GitHubContext;
|
|
||||||
ArgUtil.NotNull(githubContext, nameof(githubContext));
|
|
||||||
|
|
||||||
var tempDirectory = HostContext.GetDirectory(WellKnownDirectory.Temp);
|
|
||||||
|
|
||||||
// Resolve action steps
|
|
||||||
var actionSteps = Data.Steps;
|
|
||||||
|
|
||||||
// Create Context Data to reuse for each composite action step
|
|
||||||
var inputsData = new DictionaryContextData();
|
|
||||||
foreach (var i in Inputs)
|
|
||||||
{
|
|
||||||
inputsData[i.Key] = new StringContextData(i.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add each composite action step to the front of the queue
|
|
||||||
int location = 0;
|
|
||||||
foreach (Pipelines.ActionStep aStep in actionSteps)
|
|
||||||
{
|
|
||||||
// Ex:
|
|
||||||
// runs:
|
|
||||||
// using: "composite"
|
|
||||||
// steps:
|
|
||||||
// - uses: example/test-composite@v2 (a)
|
|
||||||
// - run echo hello world (b)
|
|
||||||
// - run echo hello world 2 (c)
|
|
||||||
//
|
|
||||||
// ethanchewy/test-composite/action.yaml
|
|
||||||
// runs:
|
|
||||||
// using: "composite"
|
|
||||||
// steps:
|
|
||||||
// - run echo hello world 3 (d)
|
|
||||||
// - run echo hello world 4 (e)
|
|
||||||
//
|
|
||||||
// Steps processed as follow:
|
|
||||||
// | a |
|
|
||||||
// | a | => | d |
|
|
||||||
// (Run step d)
|
|
||||||
// | a |
|
|
||||||
// | a | => | e |
|
|
||||||
// (Run step e)
|
|
||||||
// | a |
|
|
||||||
// (Run step a)
|
|
||||||
// | b |
|
|
||||||
// (Run step b)
|
|
||||||
// | c |
|
|
||||||
// (Run step c)
|
|
||||||
// Done.
|
|
||||||
|
|
||||||
var actionRunner = HostContext.CreateService<IActionRunner>();
|
|
||||||
actionRunner.Action = aStep;
|
|
||||||
actionRunner.Stage = stage;
|
|
||||||
actionRunner.Condition = aStep.Condition;
|
|
||||||
actionRunner.DisplayName = aStep.DisplayName;
|
|
||||||
|
|
||||||
ExecutionContext.RegisterNestedStep(actionRunner, inputsData, location, Environment);
|
|
||||||
location++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -66,11 +66,6 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
handler = HostContext.CreateService<IRunnerPluginHandler>();
|
handler = HostContext.CreateService<IRunnerPluginHandler>();
|
||||||
(handler as IRunnerPluginHandler).Data = data as PluginActionExecutionData;
|
(handler as IRunnerPluginHandler).Data = data as PluginActionExecutionData;
|
||||||
}
|
}
|
||||||
else if (data.ExecutionType == ActionExecutionType.Composite)
|
|
||||||
{
|
|
||||||
handler = HostContext.CreateService<ICompositeActionHandler>();
|
|
||||||
(handler as ICompositeActionHandler).Data = data as CompositeActionExecutionData;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
|
|||||||
@@ -64,20 +64,6 @@ namespace GitHub.Runner.Worker
|
|||||||
context.Debug($"Starting: Set up job");
|
context.Debug($"Starting: Set up job");
|
||||||
context.Output($"Current runner version: '{BuildConstants.RunnerPackage.Version}'");
|
context.Output($"Current runner version: '{BuildConstants.RunnerPackage.Version}'");
|
||||||
|
|
||||||
var setting = HostContext.GetService<IConfigurationStore>().GetSettings();
|
|
||||||
var credFile = HostContext.GetConfigFile(WellKnownConfigFile.Credentials);
|
|
||||||
if (File.Exists(credFile))
|
|
||||||
{
|
|
||||||
var credData = IOUtil.LoadObject<CredentialData>(credFile);
|
|
||||||
if (credData != null &&
|
|
||||||
credData.Data.TryGetValue("clientId", out var clientId))
|
|
||||||
{
|
|
||||||
// print out HostName for self-hosted runner
|
|
||||||
context.Output($"Runner name: '{setting.AgentName}'");
|
|
||||||
context.Output($"Machine name: '{Environment.MachineName}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var setupInfoFile = HostContext.GetConfigFile(WellKnownConfigFile.SetupInfo);
|
var setupInfoFile = HostContext.GetConfigFile(WellKnownConfigFile.SetupInfo);
|
||||||
if (File.Exists(setupInfoFile))
|
if (File.Exists(setupInfoFile))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
foreach (var step in jobSteps)
|
foreach (var step in jobSteps)
|
||||||
{
|
{
|
||||||
jobContext.JobSteps.Add(step);
|
jobContext.JobSteps.Enqueue(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
await stepsRunner.RunAsync(jobContext);
|
await stepsRunner.RunAsync(jobContext);
|
||||||
|
|||||||
@@ -59,15 +59,14 @@ namespace GitHub.Runner.Worker
|
|||||||
checkPostJobActions = true;
|
checkPostJobActions = true;
|
||||||
while (jobContext.PostJobSteps.TryPop(out var postStep))
|
while (jobContext.PostJobSteps.TryPop(out var postStep))
|
||||||
{
|
{
|
||||||
jobContext.JobSteps.Add(postStep);
|
jobContext.JobSteps.Enqueue(postStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var step = jobContext.JobSteps[0];
|
var step = jobContext.JobSteps.Dequeue();
|
||||||
jobContext.JobSteps.RemoveAt(0);
|
var nextStep = jobContext.JobSteps.Count > 0 ? jobContext.JobSteps.Peek() : null;
|
||||||
var nextStep = jobContext.JobSteps.Count > 0 ? jobContext.JobSteps[0] : null;
|
|
||||||
|
|
||||||
Trace.Info($"Processing step: DisplayName='{step.DisplayName}'");
|
Trace.Info($"Processing step: DisplayName='{step.DisplayName}'");
|
||||||
ArgUtil.NotNull(step.ExecutionContext, nameof(step.ExecutionContext));
|
ArgUtil.NotNull(step.ExecutionContext, nameof(step.ExecutionContext));
|
||||||
@@ -93,28 +92,12 @@ namespace GitHub.Runner.Worker
|
|||||||
#else
|
#else
|
||||||
var envContext = new CaseSensitiveDictionaryContextData();
|
var envContext = new CaseSensitiveDictionaryContextData();
|
||||||
#endif
|
#endif
|
||||||
// Global env
|
step.ExecutionContext.ExpressionValues["env"] = envContext;
|
||||||
foreach (var pair in step.ExecutionContext.EnvironmentVariables)
|
foreach (var pair in step.ExecutionContext.EnvironmentVariables)
|
||||||
{
|
{
|
||||||
envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty);
|
envContext[pair.Key] = new StringContextData(pair.Value ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stomps over with outside step env
|
|
||||||
if (step.ExecutionContext.ExpressionValues.TryGetValue("env", out var envContextData))
|
|
||||||
{
|
|
||||||
#if OS_WINDOWS
|
|
||||||
var dict = envContextData as DictionaryContextData;
|
|
||||||
#else
|
|
||||||
var dict = envContextData as CaseSensitiveDictionaryContextData;
|
|
||||||
#endif
|
|
||||||
foreach (var pair in dict)
|
|
||||||
{
|
|
||||||
envContext[pair.Key] = pair.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
step.ExecutionContext.ExpressionValues["env"] = envContext;
|
|
||||||
|
|
||||||
bool evaluateStepEnvFailed = false;
|
bool evaluateStepEnvFailed = false;
|
||||||
if (step is IActionRunner actionStep)
|
if (step is IActionRunner actionStep)
|
||||||
{
|
{
|
||||||
@@ -426,11 +409,7 @@ namespace GitHub.Runner.Worker
|
|||||||
scope = scopesToInitialize.Pop();
|
scope = scopesToInitialize.Pop();
|
||||||
executionContext.Debug($"Initializing scope '{scope.Name}'");
|
executionContext.Debug($"Initializing scope '{scope.Name}'");
|
||||||
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.ParentName);
|
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.ParentName);
|
||||||
// TODO: Fix this temporary workaround for Composite Actions
|
executionContext.ExpressionValues["inputs"] = !String.IsNullOrEmpty(scope.ParentName) ? scopeInputs[scope.ParentName] : null;
|
||||||
if (!executionContext.ExpressionValues.ContainsKey("inputs") && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
executionContext.ExpressionValues["inputs"] = !String.IsNullOrEmpty(scope.ParentName) ? scopeInputs[scope.ParentName] : null;
|
|
||||||
}
|
|
||||||
var templateEvaluator = executionContext.ToPipelineTemplateEvaluator();
|
var templateEvaluator = executionContext.ToPipelineTemplateEvaluator();
|
||||||
var inputs = default(DictionaryContextData);
|
var inputs = default(DictionaryContextData);
|
||||||
try
|
try
|
||||||
@@ -453,11 +432,7 @@ namespace GitHub.Runner.Worker
|
|||||||
// Setup expression values
|
// Setup expression values
|
||||||
var scopeName = executionContext.ScopeName;
|
var scopeName = executionContext.ScopeName;
|
||||||
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scopeName);
|
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scopeName);
|
||||||
// TODO: Fix this temporary workaround for Composite Actions
|
executionContext.ExpressionValues["inputs"] = string.IsNullOrEmpty(scopeName) ? null : scopeInputs[scopeName];
|
||||||
if (!executionContext.ExpressionValues.ContainsKey("inputs") && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
|
|
||||||
{
|
|
||||||
executionContext.ExpressionValues["inputs"] = string.IsNullOrEmpty(scopeName) ? null : scopeInputs[scopeName];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,7 @@
|
|||||||
"one-of": [
|
"one-of": [
|
||||||
"container-runs",
|
"container-runs",
|
||||||
"node12-runs",
|
"node12-runs",
|
||||||
"plugin-runs",
|
"plugin-runs"
|
||||||
"composite-runs"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"container-runs": {
|
"container-runs": {
|
||||||
@@ -84,36 +83,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"composite-runs": {
|
|
||||||
"mapping": {
|
|
||||||
"properties": {
|
|
||||||
"using": "non-empty-string",
|
|
||||||
"steps": "composite-steps"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"composite-steps": {
|
|
||||||
"context": [
|
|
||||||
"github",
|
|
||||||
"needs",
|
|
||||||
"strategy",
|
|
||||||
"matrix",
|
|
||||||
"secrets",
|
|
||||||
"steps",
|
|
||||||
"inputs",
|
|
||||||
"job",
|
|
||||||
"runner",
|
|
||||||
"env",
|
|
||||||
"always(0,0)",
|
|
||||||
"failure(0,0)",
|
|
||||||
"cancelled(0,0)",
|
|
||||||
"success(0,0)",
|
|
||||||
"hashFiles(1,255)"
|
|
||||||
],
|
|
||||||
"sequence": {
|
|
||||||
"item-type": "any"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"container-runs-context": {
|
"container-runs-context": {
|
||||||
"context": [
|
"context": [
|
||||||
"inputs"
|
"inputs"
|
||||||
|
|||||||
@@ -317,37 +317,5 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
userState: userState,
|
userState: userState,
|
||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// [Preview API] Resolves information required to download actions (URL, token) defined in an orchestration.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="scopeIdentifier">The project GUID to scope the request</param>
|
|
||||||
/// <param name="hubName">The name of the server hub: "build" for the Build server or "rm" for the Release Management server</param>
|
|
||||||
/// <param name="planId"></param>
|
|
||||||
/// <param name="actionReferenceList"></param>
|
|
||||||
/// <param name="userState"></param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
|
||||||
public virtual Task<ActionDownloadInfoCollection> ResolveActionDownloadInfoAsync(
|
|
||||||
Guid scopeIdentifier,
|
|
||||||
string hubName,
|
|
||||||
Guid planId,
|
|
||||||
ActionReferenceList actionReferenceList,
|
|
||||||
object userState = null,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
HttpMethod httpMethod = new HttpMethod("POST");
|
|
||||||
Guid locationId = new Guid("27d7f831-88c1-4719-8ca1-6a061dad90eb");
|
|
||||||
object routeValues = new { scopeIdentifier = scopeIdentifier, hubName = hubName, planId = planId };
|
|
||||||
HttpContent content = new ObjectContent<ActionReferenceList>(actionReferenceList, new VssJsonMediaTypeFormatter(true));
|
|
||||||
|
|
||||||
return SendAsync<ActionDownloadInfoCollection>(
|
|
||||||
httpMethod,
|
|
||||||
locationId,
|
|
||||||
routeValues: routeValues,
|
|
||||||
version: new ApiResourceVersion(6.0, 1),
|
|
||||||
userState: userState,
|
|
||||||
cancellationToken: cancellationToken,
|
|
||||||
content: content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,12 +42,7 @@ namespace GitHub.DistributedTask.Pipelines.ContextData
|
|||||||
var floored = Math.Floor(m_value);
|
var floored = Math.Floor(m_value);
|
||||||
if (m_value == floored && m_value <= (Double)Int32.MaxValue && m_value >= (Double)Int32.MinValue)
|
if (m_value == floored && m_value <= (Double)Int32.MaxValue && m_value >= (Double)Int32.MinValue)
|
||||||
{
|
{
|
||||||
var flooredInt = (Int32)floored;
|
Int32 flooredInt = (Int32)floored;
|
||||||
return (JToken)flooredInt;
|
|
||||||
}
|
|
||||||
else if (m_value == floored && m_value <= (Double)Int64.MaxValue && m_value >= (Double)Int64.MinValue)
|
|
||||||
{
|
|
||||||
var flooredInt = (Int64)floored;
|
|
||||||
return (JToken)flooredInt;
|
return (JToken)flooredInt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
public const String StepEnv = "step-env";
|
public const String StepEnv = "step-env";
|
||||||
public const String StepIfResult = "step-if-result";
|
public const String StepIfResult = "step-if-result";
|
||||||
public const String Steps = "steps";
|
public const String Steps = "steps";
|
||||||
public const String StepsInTemplate = "steps-in-template";
|
|
||||||
public const String StepsScopeInputs = "steps-scope-inputs";
|
public const String StepsScopeInputs = "steps-scope-inputs";
|
||||||
public const String StepsScopeOutputs = "steps-scope-outputs";
|
public const String StepsScopeOutputs = "steps-scope-outputs";
|
||||||
public const String StepsTemplateRoot = "steps-template-root";
|
public const String StepsTemplateRoot = "steps-template-root";
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
var evaluationResult = EvaluationResult.CreateIntermediateResult(null, ifResult);
|
var evaluationResult = EvaluationResult.CreateIntermediateResult(null, ifResult);
|
||||||
return evaluationResult.IsTruthy;
|
return evaluationResult.IsTruthy;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Boolean? ConvertToStepContinueOnError(
|
internal static Boolean? ConvertToStepContinueOnError(
|
||||||
TemplateContext context,
|
TemplateContext context,
|
||||||
TemplateToken token,
|
TemplateToken token,
|
||||||
@@ -263,351 +264,5 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Note: originally was List<Step> but we need to change to List<ActionStep> to use the "Inputs" attribute
|
|
||||||
internal static List<ActionStep> ConvertToSteps(
|
|
||||||
TemplateContext context,
|
|
||||||
TemplateToken steps)
|
|
||||||
{
|
|
||||||
var stepsSequence = steps.AssertSequence($"job {PipelineTemplateConstants.Steps}");
|
|
||||||
|
|
||||||
var result = new List<ActionStep>();
|
|
||||||
foreach (var stepsItem in stepsSequence)
|
|
||||||
{
|
|
||||||
var step = ConvertToStep(context, stepsItem);
|
|
||||||
if (step != null) // step = null means we are hitting error during step conversion, there should be an error in context.errors
|
|
||||||
{
|
|
||||||
if (step.Enabled)
|
|
||||||
{
|
|
||||||
result.Add(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ActionStep ConvertToStep(
|
|
||||||
TemplateContext context,
|
|
||||||
TemplateToken stepsItem)
|
|
||||||
{
|
|
||||||
var step = stepsItem.AssertMapping($"{PipelineTemplateConstants.Steps} item");
|
|
||||||
var continueOnError = default(ScalarToken);
|
|
||||||
var env = default(TemplateToken);
|
|
||||||
var id = default(StringToken);
|
|
||||||
var ifCondition = default(String);
|
|
||||||
var ifToken = default(ScalarToken);
|
|
||||||
var name = default(ScalarToken);
|
|
||||||
var run = default(ScalarToken);
|
|
||||||
var scope = default(StringToken);
|
|
||||||
var timeoutMinutes = default(ScalarToken);
|
|
||||||
var uses = default(StringToken);
|
|
||||||
var with = default(TemplateToken);
|
|
||||||
var workingDir = default(ScalarToken);
|
|
||||||
var path = default(ScalarToken);
|
|
||||||
var clean = default(ScalarToken);
|
|
||||||
var fetchDepth = default(ScalarToken);
|
|
||||||
var lfs = default(ScalarToken);
|
|
||||||
var submodules = default(ScalarToken);
|
|
||||||
var shell = default(ScalarToken);
|
|
||||||
|
|
||||||
foreach (var stepProperty in step)
|
|
||||||
{
|
|
||||||
var propertyName = stepProperty.Key.AssertString($"{PipelineTemplateConstants.Steps} item key");
|
|
||||||
|
|
||||||
switch (propertyName.Value)
|
|
||||||
{
|
|
||||||
case PipelineTemplateConstants.Clean:
|
|
||||||
clean = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Clean}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.ContinueOnError:
|
|
||||||
ConvertToStepContinueOnError(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
|
|
||||||
continueOnError = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} {PipelineTemplateConstants.ContinueOnError}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Env:
|
|
||||||
ConvertToStepEnvironment(context, stepProperty.Value, StringComparer.Ordinal, allowExpressions: true); // Validate early if possible
|
|
||||||
env = stepProperty.Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.FetchDepth:
|
|
||||||
fetchDepth = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.FetchDepth}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Id:
|
|
||||||
id = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Id}");
|
|
||||||
if (!NameValidation.IsValid(id.Value, true))
|
|
||||||
{
|
|
||||||
context.Error(id, $"Step id {id.Value} is invalid. Ids must start with a letter or '_' and contain only alphanumeric characters, '-', or '_'");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.If:
|
|
||||||
ifToken = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.If}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Lfs:
|
|
||||||
lfs = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Lfs}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Name:
|
|
||||||
name = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Name}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Path:
|
|
||||||
path = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Path}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Run:
|
|
||||||
run = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Run}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Shell:
|
|
||||||
shell = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Shell}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Scope:
|
|
||||||
scope = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Scope}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Submodules:
|
|
||||||
submodules = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Submodules}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.TimeoutMinutes:
|
|
||||||
ConvertToStepTimeout(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
|
|
||||||
timeoutMinutes = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.TimeoutMinutes}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.Uses:
|
|
||||||
uses = stepProperty.Value.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Uses}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.With:
|
|
||||||
ConvertToStepInputs(context, stepProperty.Value, allowExpressions: true); // Validate early if possible
|
|
||||||
with = stepProperty.Value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PipelineTemplateConstants.WorkingDirectory:
|
|
||||||
workingDir = stepProperty.Value.AssertScalar($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.WorkingDirectory}");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
propertyName.AssertUnexpectedValue($"{PipelineTemplateConstants.Steps} item key"); // throws
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixup the if-condition
|
|
||||||
var isDefaultScope = String.IsNullOrEmpty(scope?.Value);
|
|
||||||
ifCondition = ConvertToIfCondition(context, ifToken, false, isDefaultScope);
|
|
||||||
|
|
||||||
if (run != null)
|
|
||||||
{
|
|
||||||
var result = new ActionStep
|
|
||||||
{
|
|
||||||
ScopeName = scope?.Value,
|
|
||||||
ContextName = id?.Value,
|
|
||||||
ContinueOnError = continueOnError,
|
|
||||||
DisplayNameToken = name,
|
|
||||||
Condition = ifCondition,
|
|
||||||
TimeoutInMinutes = timeoutMinutes,
|
|
||||||
Environment = env,
|
|
||||||
Reference = new ScriptReference(),
|
|
||||||
};
|
|
||||||
|
|
||||||
var inputs = new MappingToken(null, null, null);
|
|
||||||
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Script), run);
|
|
||||||
|
|
||||||
if (workingDir != null)
|
|
||||||
{
|
|
||||||
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.WorkingDirectory), workingDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shell != null)
|
|
||||||
{
|
|
||||||
inputs.Add(new StringToken(null, null, null, PipelineConstants.ScriptStepInputs.Shell), shell);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Inputs = inputs;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uses.AssertString($"{PipelineTemplateConstants.Steps} item {PipelineTemplateConstants.Uses}");
|
|
||||||
var result = new ActionStep
|
|
||||||
{
|
|
||||||
ScopeName = scope?.Value,
|
|
||||||
ContextName = id?.Value,
|
|
||||||
ContinueOnError = continueOnError,
|
|
||||||
DisplayNameToken = name,
|
|
||||||
Condition = ifCondition,
|
|
||||||
TimeoutInMinutes = timeoutMinutes,
|
|
||||||
Inputs = with,
|
|
||||||
Environment = env,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (uses.Value.StartsWith("docker://", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var image = uses.Value.Substring("docker://".Length);
|
|
||||||
result.Reference = new ContainerRegistryReference { Image = image };
|
|
||||||
}
|
|
||||||
else if (uses.Value.StartsWith("./") || uses.Value.StartsWith(".\\"))
|
|
||||||
{
|
|
||||||
result.Reference = new RepositoryPathReference
|
|
||||||
{
|
|
||||||
RepositoryType = PipelineConstants.SelfAlias,
|
|
||||||
Path = uses.Value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var usesSegments = uses.Value.Split('@');
|
|
||||||
var pathSegments = usesSegments[0].Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
var gitRef = usesSegments.Length == 2 ? usesSegments[1] : String.Empty;
|
|
||||||
|
|
||||||
if (usesSegments.Length != 2 ||
|
|
||||||
pathSegments.Length < 2 ||
|
|
||||||
String.IsNullOrEmpty(pathSegments[0]) ||
|
|
||||||
String.IsNullOrEmpty(pathSegments[1]) ||
|
|
||||||
String.IsNullOrEmpty(gitRef))
|
|
||||||
{
|
|
||||||
// todo: loc
|
|
||||||
context.Error(uses, $"Expected format {{org}}/{{repo}}[/path]@ref. Actual '{uses.Value}'");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var repositoryName = $"{pathSegments[0]}/{pathSegments[1]}";
|
|
||||||
var directoryPath = pathSegments.Length > 2 ? String.Join("/", pathSegments.Skip(2)) : String.Empty;
|
|
||||||
|
|
||||||
result.Reference = new RepositoryPathReference
|
|
||||||
{
|
|
||||||
RepositoryType = RepositoryTypes.GitHub,
|
|
||||||
Name = repositoryName,
|
|
||||||
Ref = gitRef,
|
|
||||||
Path = directoryPath,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// When empty, default to "success()".
|
|
||||||
/// When a status function is not referenced, format as "success() && <CONDITION>".
|
|
||||||
/// </summary>
|
|
||||||
private static String ConvertToIfCondition(
|
|
||||||
TemplateContext context,
|
|
||||||
TemplateToken token,
|
|
||||||
Boolean isJob,
|
|
||||||
Boolean isDefaultScope)
|
|
||||||
{
|
|
||||||
String condition;
|
|
||||||
if (token is null)
|
|
||||||
{
|
|
||||||
condition = null;
|
|
||||||
}
|
|
||||||
else if (token is BasicExpressionToken expressionToken)
|
|
||||||
{
|
|
||||||
condition = expressionToken.Expression;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var stringToken = token.AssertString($"{(isJob ? "job" : "step")} {PipelineTemplateConstants.If}");
|
|
||||||
condition = stringToken.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (String.IsNullOrWhiteSpace(condition))
|
|
||||||
{
|
|
||||||
return $"{PipelineTemplateConstants.Success}()";
|
|
||||||
}
|
|
||||||
|
|
||||||
var expressionParser = new ExpressionParser();
|
|
||||||
var functions = default(IFunctionInfo[]);
|
|
||||||
var namedValues = default(INamedValueInfo[]);
|
|
||||||
if (isJob)
|
|
||||||
{
|
|
||||||
namedValues = s_jobIfNamedValues;
|
|
||||||
// TODO: refactor into seperate functions
|
|
||||||
// functions = PhaseCondition.FunctionInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
namedValues = isDefaultScope ? s_stepNamedValues : s_stepInTemplateNamedValues;
|
|
||||||
functions = s_stepConditionFunctions;
|
|
||||||
}
|
|
||||||
|
|
||||||
var node = default(ExpressionNode);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
node = expressionParser.CreateTree(condition, null, namedValues, functions) as ExpressionNode;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
context.Error(token, ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node == null)
|
|
||||||
{
|
|
||||||
return $"{PipelineTemplateConstants.Success}()";
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasStatusFunction = node.Traverse().Any(x =>
|
|
||||||
{
|
|
||||||
if (x is Function function)
|
|
||||||
{
|
|
||||||
return String.Equals(function.Name, PipelineTemplateConstants.Always, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
String.Equals(function.Name, PipelineTemplateConstants.Cancelled, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
String.Equals(function.Name, PipelineTemplateConstants.Failure, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
String.Equals(function.Name, PipelineTemplateConstants.Success, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return hasStatusFunction ? condition : $"{PipelineTemplateConstants.Success}() && ({condition})";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly INamedValueInfo[] s_jobIfNamedValues = new INamedValueInfo[]
|
|
||||||
{
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Needs),
|
|
||||||
};
|
|
||||||
private static readonly INamedValueInfo[] s_stepNamedValues = new INamedValueInfo[]
|
|
||||||
{
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Strategy),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Needs),
|
|
||||||
};
|
|
||||||
private static readonly INamedValueInfo[] s_stepInTemplateNamedValues = new INamedValueInfo[]
|
|
||||||
{
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Strategy),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Matrix),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Steps),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Inputs),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.GitHub),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Job),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Runner),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Env),
|
|
||||||
new NamedValueInfo<NoOperationNamedValue>(PipelineTemplateConstants.Needs),
|
|
||||||
};
|
|
||||||
private static readonly IFunctionInfo[] s_stepConditionFunctions = new IFunctionInfo[]
|
|
||||||
{
|
|
||||||
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Always, 0, 0),
|
|
||||||
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Cancelled, 0, 0),
|
|
||||||
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Failure, 0, 0),
|
|
||||||
new FunctionInfo<NoOperation>(PipelineTemplateConstants.Success, 0, 0),
|
|
||||||
new FunctionInfo<NoOperation>(PipelineTemplateConstants.HashFiles, 1, Byte.MaxValue),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,31 +159,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ActionStep> LoadCompositeSteps(
|
|
||||||
TemplateToken token)
|
|
||||||
{
|
|
||||||
var result = default(List<ActionStep>);
|
|
||||||
if (token != null && token.Type != TokenType.Null)
|
|
||||||
{
|
|
||||||
var context = CreateContext(null, null, setMissingContext: false);
|
|
||||||
// TODO: we might want to to have a bool to prevent it from filling in with missing context w/ dummy variables
|
|
||||||
try
|
|
||||||
{
|
|
||||||
token = TemplateEvaluator.Evaluate(context, PipelineTemplateConstants.StepsInTemplate, token, 0, null, omitHeader: true);
|
|
||||||
context.Errors.Check();
|
|
||||||
result = PipelineTemplateConverter.ConvertToSteps(context, token);
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (!(ex is TemplateValidationException))
|
|
||||||
{
|
|
||||||
context.Errors.Add(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Errors.Check();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Dictionary<String, String> EvaluateStepEnvironment(
|
public Dictionary<String, String> EvaluateStepEnvironment(
|
||||||
TemplateToken token,
|
TemplateToken token,
|
||||||
DictionaryContextData contextData,
|
DictionaryContextData contextData,
|
||||||
@@ -425,8 +400,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
private TemplateContext CreateContext(
|
private TemplateContext CreateContext(
|
||||||
DictionaryContextData contextData,
|
DictionaryContextData contextData,
|
||||||
IList<IFunctionInfo> expressionFunctions,
|
IList<IFunctionInfo> expressionFunctions,
|
||||||
IEnumerable<KeyValuePair<String, Object>> expressionState = null,
|
IEnumerable<KeyValuePair<String, Object>> expressionState = null)
|
||||||
bool setMissingContext = true)
|
|
||||||
{
|
{
|
||||||
var result = new TemplateContext
|
var result = new TemplateContext
|
||||||
{
|
{
|
||||||
@@ -475,21 +449,18 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
// - Evaluating early when all referenced contexts are available, even though all allowed
|
// - Evaluating early when all referenced contexts are available, even though all allowed
|
||||||
// contexts may not yet be available. For example, evaluating step display name can often
|
// contexts may not yet be available. For example, evaluating step display name can often
|
||||||
// be performed early.
|
// be performed early.
|
||||||
if (setMissingContext)
|
foreach (var name in s_expressionValueNames)
|
||||||
{
|
{
|
||||||
foreach (var name in s_expressionValueNames)
|
if (!result.ExpressionValues.ContainsKey(name))
|
||||||
{
|
{
|
||||||
if (!result.ExpressionValues.ContainsKey(name))
|
result.ExpressionValues[name] = null;
|
||||||
{
|
|
||||||
result.ExpressionValues[name] = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach (var name in s_expressionFunctionNames)
|
}
|
||||||
|
foreach (var name in s_expressionFunctionNames)
|
||||||
|
{
|
||||||
|
if (!functionNames.Contains(name))
|
||||||
{
|
{
|
||||||
if (!functionNames.Contains(name))
|
result.ExpressionFunctions.Add(new FunctionInfo<NoOperation>(name, 0, Int32.MaxValue));
|
||||||
{
|
|
||||||
result.ExpressionFunctions.Add(new FunctionInfo<NoOperation>(name, 0, Int32.MaxValue));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,12 +94,5 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
public static readonly String Resources = "resources";
|
public static readonly String Resources = "resources";
|
||||||
public static readonly String All = "all";
|
public static readonly String All = "all";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ScriptStepInputs
|
|
||||||
{
|
|
||||||
public static readonly String Script = "script";
|
|
||||||
public static readonly String WorkingDirectory = "workingDirectory";
|
|
||||||
public static readonly String Shell = "shell";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
[DataContract]
|
|
||||||
public class ActionDownloadInfo
|
|
||||||
{
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public ActionDownloadAuthentication Authentication { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string NameWithOwner { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string ResolvedNameWithOwner { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string ResolvedSha { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string TarballUrl { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string Ref { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string ZipballUrl { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataContract]
|
|
||||||
public class ActionDownloadAuthentication
|
|
||||||
{
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public DateTime ExpiresAt { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string Token { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
[DataContract]
|
|
||||||
public class ActionDownloadInfoCollection
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public IDictionary<string, ActionDownloadInfo> Actions
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
[DataContract]
|
|
||||||
public class ActionReference
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public string NameWithOwner
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataMember]
|
|
||||||
public string Ref
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace GitHub.DistributedTask.WebApi
|
|
||||||
{
|
|
||||||
[DataContract]
|
|
||||||
public class ActionReferenceList
|
|
||||||
{
|
|
||||||
[DataMember]
|
|
||||||
public IList<ActionReference> Actions
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,7 +39,7 @@ namespace GitHub.Services.OAuth
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the error description for the response.
|
/// Gets or sets the error description for the response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataMember(Name = "error_description", EmitDefaultValue = false)]
|
[DataMember(Name = "errordescription", EmitDefaultValue = false)]
|
||||||
public String ErrorDescription
|
public String ErrorDescription
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
|
|||||||
@@ -70,24 +70,5 @@ namespace GitHub.Runner.Common.Tests.Util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Common")]
|
|
||||||
public void WhichHandleFullyQualifiedPath()
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = new TestHostContext(this))
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
Tracing trace = hc.GetTrace();
|
|
||||||
|
|
||||||
// Act.
|
|
||||||
var gitPath = WhichUtil.Which("git", require: true, trace: trace);
|
|
||||||
var gitPath2 = WhichUtil.Which(gitPath, require: true, trace: trace);
|
|
||||||
|
|
||||||
// Assert.
|
|
||||||
Assert.Equal(gitPath, gitPath2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
private Mock<IConfigurationStore> _configurationStore;
|
private Mock<IConfigurationStore> _configurationStore;
|
||||||
private Mock<IDockerCommandManager> _dockerManager;
|
private Mock<IDockerCommandManager> _dockerManager;
|
||||||
private Mock<IExecutionContext> _ec;
|
private Mock<IExecutionContext> _ec;
|
||||||
private Mock<IJobServer> _jobServer;
|
|
||||||
private Mock<IRunnerPluginManager> _pluginManager;
|
private Mock<IRunnerPluginManager> _pluginManager;
|
||||||
private TestHostContext _hc;
|
private TestHostContext _hc;
|
||||||
private ActionManager _actionManager;
|
private ActionManager _actionManager;
|
||||||
@@ -3584,8 +3583,6 @@ runs:
|
|||||||
_ec.Setup(x => x.Variables).Returns(new Variables(_hc, variables));
|
_ec.Setup(x => x.Variables).Returns(new Variables(_hc, variables));
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
_ec.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
||||||
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
||||||
_ec.Setup(x => x.FileTable).Returns(new List<String>());
|
|
||||||
_ec.Setup(x => x.Plan).Returns(new TaskOrchestrationPlanReference());
|
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { _hc.GetTrace().Info($"[{tag}]{message}"); });
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { _hc.GetTrace().Info($"[{tag}]{message}"); });
|
||||||
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())).Callback((Issue issue, string message) => { _hc.GetTrace().Info($"[{issue.Type}]{issue.Message ?? message}"); });
|
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())).Callback((Issue issue, string message) => { _hc.GetTrace().Info($"[{issue.Type}]{issue.Message ?? message}"); });
|
||||||
_ec.Setup(x => x.GetGitHubContext("workspace")).Returns(Path.Combine(_workFolder, "actions", "actions"));
|
_ec.Setup(x => x.GetGitHubContext("workspace")).Returns(Path.Combine(_workFolder, "actions", "actions"));
|
||||||
@@ -3596,25 +3593,6 @@ runs:
|
|||||||
|
|
||||||
_dockerManager.Setup(x => x.DockerBuild(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(0));
|
_dockerManager.Setup(x => x.DockerBuild(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(Task.FromResult(0));
|
||||||
|
|
||||||
_jobServer = new Mock<IJobServer>();
|
|
||||||
_jobServer.Setup(x => x.ResolveActionDownloadInfoAsync(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<Guid>(), It.IsAny<ActionReferenceList>(), It.IsAny<CancellationToken>()))
|
|
||||||
.Returns((Guid scopeIdentifier, string hubName, Guid planId, ActionReferenceList actions, CancellationToken cancellationToken) =>
|
|
||||||
{
|
|
||||||
var result = new ActionDownloadInfoCollection { Actions = new Dictionary<string, ActionDownloadInfo>() };
|
|
||||||
foreach (var action in actions.Actions)
|
|
||||||
{
|
|
||||||
var key = $"{action.NameWithOwner}@{action.Ref}";
|
|
||||||
result.Actions[key] = new ActionDownloadInfo
|
|
||||||
{
|
|
||||||
NameWithOwner = action.NameWithOwner,
|
|
||||||
Ref = action.Ref,
|
|
||||||
TarballUrl = $"https://api.github.com/repos/{action.NameWithOwner}/tarball/{action.Ref}",
|
|
||||||
ZipballUrl = $"https://api.github.com/repos/{action.NameWithOwner}/zipball/{action.Ref}",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return Task.FromResult(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
_pluginManager = new Mock<IRunnerPluginManager>();
|
_pluginManager = new Mock<IRunnerPluginManager>();
|
||||||
_pluginManager.Setup(x => x.GetPluginAction(It.IsAny<string>())).Returns(new RunnerPluginActionInfo() { PluginTypeName = "plugin.class, plugin", PostPluginTypeName = "plugin.cleanup, plugin" });
|
_pluginManager.Setup(x => x.GetPluginAction(It.IsAny<string>())).Returns(new RunnerPluginActionInfo() { PluginTypeName = "plugin.class, plugin", PostPluginTypeName = "plugin.cleanup, plugin" });
|
||||||
|
|
||||||
@@ -3622,7 +3600,6 @@ runs:
|
|||||||
actionManifest.Initialize(_hc);
|
actionManifest.Initialize(_hc);
|
||||||
|
|
||||||
_hc.SetSingleton<IDockerCommandManager>(_dockerManager.Object);
|
_hc.SetSingleton<IDockerCommandManager>(_dockerManager.Object);
|
||||||
_hc.SetSingleton<IJobServer>(_jobServer.Object);
|
|
||||||
_hc.SetSingleton<IRunnerPluginManager>(_pluginManager.Object);
|
_hc.SetSingleton<IRunnerPluginManager>(_pluginManager.Object);
|
||||||
_hc.SetSingleton<IActionManifestManager>(actionManifest);
|
_hc.SetSingleton<IActionManifestManager>(actionManifest);
|
||||||
_hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
_hc.SetSingleton<IHttpClientHandlerFactory>(new HttpClientHandlerFactory());
|
||||||
|
|||||||
@@ -759,7 +759,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_ec.Setup(x => x.Variables).Returns(new Variables(_hc, new Dictionary<string, VariableValue>()));
|
_ec.Setup(x => x.Variables).Returns(new Variables(_hc, new Dictionary<string, VariableValue>()));
|
||||||
_ec.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
_ec.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
||||||
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
||||||
_ec.Setup(x => x.FileTable).Returns(new List<String>());
|
|
||||||
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { _hc.GetTrace().Info($"{tag}{message}"); });
|
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())).Callback((string tag, string message) => { _hc.GetTrace().Info($"{tag}{message}"); });
|
||||||
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())).Callback((Issue issue, string message) => { _hc.GetTrace().Info($"[{issue.Type}]{issue.Message ?? message}"); });
|
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())).Callback((Issue issue, string message) => { _hc.GetTrace().Info($"[{issue.Type}]{issue.Message ?? message}"); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -379,7 +379,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
_ec.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
||||||
_ec.Setup(x => x.IntraActionState).Returns(new Dictionary<string, string>());
|
_ec.Setup(x => x.IntraActionState).Returns(new Dictionary<string, string>());
|
||||||
_ec.Setup(x => x.EnvironmentVariables).Returns(new Dictionary<string, string>());
|
_ec.Setup(x => x.EnvironmentVariables).Returns(new Dictionary<string, string>());
|
||||||
_ec.Setup(x => x.FileTable).Returns(new List<String>());
|
|
||||||
_ec.Setup(x => x.SetGitHubContext(It.IsAny<string>(), It.IsAny<string>()));
|
_ec.Setup(x => x.SetGitHubContext(It.IsAny<string>(), It.IsAny<string>()));
|
||||||
_ec.Setup(x => x.GetGitHubContext(It.IsAny<string>())).Returns("{\"foo\":\"bar\"}");
|
_ec.Setup(x => x.GetGitHubContext(It.IsAny<string>())).Returns("{\"foo\":\"bar\"}");
|
||||||
_ec.Setup(x => x.CancellationToken).Returns(_ecTokenSource.Token);
|
_ec.Setup(x => x.CancellationToken).Returns(_ecTokenSource.Token);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -115,7 +115,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -154,7 +154,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -208,7 +208,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -287,7 +287,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Steps.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -330,7 +330,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Step.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Step.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -361,7 +361,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -391,7 +391,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
{
|
{
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(variableSet.Select(x => x.Object).ToList()));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(variableSet.Select(x => x.Object).ToList()));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -417,7 +417,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(new[] { step1.Object }));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(new[] { step1.Object }));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -426,11 +426,11 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
Assert.Equal("100", step1.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("100"));
|
Assert.Equal("100", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("100"));
|
||||||
Assert.Equal("github_actions", step1.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env2"].AssertString("github_actions"));
|
Assert.Equal("github_actions", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env2"].AssertString("github_actions"));
|
||||||
#else
|
#else
|
||||||
Assert.Equal("100", step1.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("100"));
|
Assert.Equal("100", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("100"));
|
||||||
Assert.Equal("github_actions", step1.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env2"].AssertString("github_actions"));
|
Assert.Equal("github_actions", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env2"].AssertString("github_actions"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(new[] { step1.Object, step2.Object }));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(new[] { step1.Object, step2.Object }));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -463,13 +463,13 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
Assert.Equal("1000", step2.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("1000"));
|
Assert.Equal("1000", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("1000"));
|
||||||
Assert.Equal("github_actions", step2.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env3"].AssertString("github_actions"));
|
Assert.Equal("github_actions", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env3"].AssertString("github_actions"));
|
||||||
Assert.False(step2.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env").ContainsKey("env2"));
|
Assert.False(_ec.Object.ExpressionValues["env"].AssertDictionary("env").ContainsKey("env2"));
|
||||||
#else
|
#else
|
||||||
Assert.Equal("1000", step2.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("1000"));
|
Assert.Equal("1000", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("1000"));
|
||||||
Assert.Equal("github_actions", step2.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env3"].AssertString("github_actions"));
|
Assert.Equal("github_actions", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env3"].AssertString("github_actions"));
|
||||||
Assert.False(step2.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env").ContainsKey("env2"));
|
Assert.False(_ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env").ContainsKey("env2"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,7 +493,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(new[] { step1.Object, step2.Object }));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(new[] { step1.Object, step2.Object }));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -501,11 +501,11 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
// Assert.
|
// Assert.
|
||||||
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
Assert.Equal("1000", step2.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("1000"));
|
Assert.Equal("1000", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env1"].AssertString("1000"));
|
||||||
Assert.Equal("something", step2.Object.ExecutionContext.ExpressionValues["env"].AssertDictionary("env")["env2"].AssertString("something"));
|
Assert.Equal("something", _ec.Object.ExpressionValues["env"].AssertDictionary("env")["env2"].AssertString("something"));
|
||||||
#else
|
#else
|
||||||
Assert.Equal("1000", step2.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("1000"));
|
Assert.Equal("1000", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env1"].AssertString("1000"));
|
||||||
Assert.Equal("something", step2.Object.ExecutionContext.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env2"].AssertString("something"));
|
Assert.Equal("something", _ec.Object.ExpressionValues["env"].AssertCaseSensitiveDictionary("env")["env2"].AssertString("something"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -524,7 +524,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(new[] { step1.Object, step2.Object, step3.Object }));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(new[] { step1.Object, step2.Object, step3.Object }));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -560,7 +560,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
_ec.Object.Result = null;
|
_ec.Object.Result = null;
|
||||||
|
|
||||||
_ec.Setup(x => x.JobSteps).Returns(new List<IStep>(new[] { step1.Object, step2.Object, step3.Object }));
|
_ec.Setup(x => x.JobSteps).Returns(new Queue<IStep>(new[] { step1.Object, step2.Object, step3.Object }));
|
||||||
|
|
||||||
// Act.
|
// Act.
|
||||||
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
await _stepsRunner.RunAsync(jobContext: _ec.Object);
|
||||||
@@ -602,7 +602,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
stepContext.Setup(x => x.WriteDebug).Returns(true);
|
stepContext.Setup(x => x.WriteDebug).Returns(true);
|
||||||
stepContext.Setup(x => x.Variables).Returns(_variables);
|
stepContext.Setup(x => x.Variables).Returns(_variables);
|
||||||
stepContext.Setup(x => x.EnvironmentVariables).Returns(_env);
|
stepContext.Setup(x => x.EnvironmentVariables).Returns(_env);
|
||||||
stepContext.Setup(x => x.ExpressionValues).Returns(new DictionaryContextData());
|
stepContext.Setup(x => x.ExpressionValues).Returns(_contexts);
|
||||||
stepContext.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
stepContext.Setup(x => x.ExpressionFunctions).Returns(new List<IFunctionInfo>());
|
||||||
stepContext.Setup(x => x.JobContext).Returns(_jobContext);
|
stepContext.Setup(x => x.JobContext).Returns(_jobContext);
|
||||||
stepContext.Setup(x => x.StepsContext).Returns(_stepContext);
|
stepContext.Setup(x => x.StepsContext).Returns(_stepContext);
|
||||||
|
|||||||
51
src/dev.sh
51
src/dev.sh
@@ -173,6 +173,57 @@ function package ()
|
|||||||
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "Add-Type -Assembly \"System.IO.Compression.FileSystem\"; [System.IO.Compression.ZipFile]::CreateFromDirectory(\"${window_path}\", \"${zip_name}\")"
|
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "Add-Type -Assembly \"System.IO.Compression.FileSystem\"; [System.IO.Compression.ZipFile]::CreateFromDirectory(\"${window_path}\", \"${zip_name}\")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
runner_patch_pkg_name="actions-runner-${RUNTIME_ID}-${runner_ver}-patch"
|
||||||
|
|
||||||
|
heading "Packaging Patch Version ${runner_patch_pkg_name}"
|
||||||
|
|
||||||
|
echo "Downloading latest runner ..."
|
||||||
|
|
||||||
|
mkdir -p "_temp"
|
||||||
|
pushd "_temp" > /dev/null
|
||||||
|
|
||||||
|
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
|
||||||
|
latest_version=$(echo ${latest_version_label:1})
|
||||||
|
latest_version_runner_file=""
|
||||||
|
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then
|
||||||
|
latest_version_runner_file="actions-runner-${RUNTIME_ID}-${latest_version}.tar.gz"
|
||||||
|
elif [[ ("$CURRENT_PLATFORM" == "windows") ]]; then
|
||||||
|
latest_version_runner_file="actions-runner-${RUNTIME_ID}-${latest_version}.zip"
|
||||||
|
fi
|
||||||
|
|
||||||
|
latest_version_download_url="https://github.com/actions/runner/releases/download/${latest_version_label}/${latest_version_runner_file}"
|
||||||
|
|
||||||
|
echo "Downloading ${latest_version_label} for ${RUNTIME_ID} ..."
|
||||||
|
echo $latest_version_download_url
|
||||||
|
|
||||||
|
curl -O -L ${latest_version_download_url}
|
||||||
|
|
||||||
|
mkdir -p "latest_runner"
|
||||||
|
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then
|
||||||
|
tar xzf "./${latest_version_runner_file}" -C latest_runner
|
||||||
|
elif [[ ("$CURRENT_PLATFORM" == "windows") ]]; then
|
||||||
|
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "Add-Type -Assembly \"System.IO.Compression.FileSystem\"; [System.IO.Compression.ZipFile]::ExtractToDirectory(\"./${latest_version_runner_file}\", \"latest_runner\")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "_patch"
|
||||||
|
diff -qrN "${LAYOUT_DIR}" "latest_runner" | cut -d " " -f 2 | xargs -t -I file cp file "_patch/"$(echo file | cut -c ${#LAYOUT_DIR}- | cut -c 3-)
|
||||||
|
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then
|
||||||
|
patch_tar_name="${runner_patch_pkg_name}.tar.gz"
|
||||||
|
echo "Creating $patch_tar_name in ${PACKAGE_DIR}/_temp/_patch"
|
||||||
|
tar -czf "${patch_tar_name}" -C "${PACKAGE_DIR}/_temp/_patch" .
|
||||||
|
elif [[ ("$CURRENT_PLATFORM" == "windows") ]]; then
|
||||||
|
patch_zip_name="${runner_patch_pkg_name}.zip"
|
||||||
|
echo "Convert ${PACKAGE_DIR} to Windows style path"
|
||||||
|
window_path=${PACKAGE_DIR:1}
|
||||||
|
window_path=${window_path:0:1}:${window_path:1}
|
||||||
|
echo "Creating $patch_zip_name in ${window_path}/_temp/_patch"
|
||||||
|
powershell -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "Add-Type -Assembly \"System.IO.Compression.FileSystem\"; [System.IO.Compression.ZipFile]::CreateFromDirectory(\"${window_path}\", \"${patch_zip_name}\")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -Rf "${PACKAGE_DIR}/_temp"
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.267.0
|
2.263.0
|
||||||
|
|||||||
Reference in New Issue
Block a user