mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
10 Commits
users/tihu
...
v2.283.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
436989949b | ||
|
|
06f7d8a4a3 | ||
|
|
06e1773933 | ||
|
|
844595b1b3 | ||
|
|
98a1935e50 | ||
|
|
4d908df4b2 | ||
|
|
b53b520498 | ||
|
|
e6baf0d275 | ||
|
|
e7ad4652b6 | ||
|
|
b03ca604ff |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: win-x64
|
||||
os: windows-latest
|
||||
os: windows-2019
|
||||
devScript: ./dev
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -72,7 +72,7 @@ jobs:
|
||||
devScript: ./dev.sh
|
||||
|
||||
- runtime: win-x64
|
||||
os: windows-latest
|
||||
os: windows-2019
|
||||
devScript: ./dev
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -164,6 +164,7 @@ jobs:
|
||||
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
||||
body: |
|
||||
${{ steps.releaseNote.outputs.note }}
|
||||
prerelease: true
|
||||
|
||||
# Upload release assets
|
||||
- name: Upload Release Asset (win-x64)
|
||||
|
||||
74
job.yml
74
job.yml
@@ -1,74 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: pod-admin
|
||||
namespace: default
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "pods/log", "pods/attach", "pods/exec"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: default-pod-admin
|
||||
namespace: default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: pod-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: default
|
||||
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
namespace: default
|
||||
name: actions-runners
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
# hostNetwork: true
|
||||
volumes:
|
||||
- name: runner-working
|
||||
emptyDir: {}
|
||||
containers:
|
||||
- name: k8srunner
|
||||
image: huangtingluo/kube-runner:v0
|
||||
imagePullPolicy: Always
|
||||
volumeMounts:
|
||||
- mountPath: /actions-runner/_work
|
||||
name: runner-working
|
||||
env:
|
||||
- name: GITHUB_PAT
|
||||
value: ghp_
|
||||
- name: RUNNER_CONFIG_URL
|
||||
value: https://github.com/bbq-beets/ting-test
|
||||
- name: K8S_NODE_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.nodeName
|
||||
- name: K8S_POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: K8S_POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: K8S_POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
- name: K8S_POD_SERVICE_ACCOUNT
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: spec.serviceAccountName
|
||||
restartPolicy: Never
|
||||
backoffLimit: 1
|
||||
completions: 1
|
||||
parallelism: 1
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Bugs
|
||||
|
||||
- Fixed an issue where ephemeral runners did not restart after upgrading (#1396)
|
||||
- Fixed an issue where container environment variables names or values could escape the docker command (#2108)
|
||||
|
||||
## Misc
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
<Update to ./src/runnerversion when creating release>
|
||||
2.283.4
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS Build
|
||||
|
||||
# ENV RUNNER_CONFIG_URL=""
|
||||
# ENV GITHUB_PAT=""
|
||||
# ENV RUNNER_NAME=""
|
||||
# ENV RUNNER_GROUP=""
|
||||
# ENV RUNNER_LABELS=""
|
||||
# ENV GITHUB_RUNNER_SCOPE=""
|
||||
# ENV GITHUB_SERVER_URL=""
|
||||
# ENV GITHUB_API_URL=""
|
||||
# ENV K8S_HOST_IP=""
|
||||
|
||||
RUN apt-get update --fix-missing \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
# jq \
|
||||
# git \
|
||||
apt-utils \
|
||||
apt-transport-https \
|
||||
unzip \
|
||||
net-tools\
|
||||
gnupg2\
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install kubectl
|
||||
# RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
|
||||
# echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list && \
|
||||
# apt-get update && apt-get -y install --no-install-recommends kubectl
|
||||
|
||||
# Install docker
|
||||
# RUN curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
# RUN sh get-docker.sh
|
||||
|
||||
# Allow runner to run as root
|
||||
# ENV RUNNER_ALLOW_RUNASROOT=1
|
||||
|
||||
# Directory for runner to operate in
|
||||
RUN mkdir /actions-runner
|
||||
RUN mkdir /actions-runner/src
|
||||
WORKDIR /actions-runner/src
|
||||
|
||||
COPY ./ /actions-runner/src
|
||||
|
||||
RUN /actions-runner/src/dev.sh l
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1
|
||||
|
||||
ENV RUNNER_CONFIG_URL=""
|
||||
ENV GITHUB_PAT=""
|
||||
|
||||
RUN apt-get update --fix-missing \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
# jq \
|
||||
# git \
|
||||
# apt-utils \
|
||||
# apt-transport-https \
|
||||
# unzip \
|
||||
# net-tools\
|
||||
gnupg2\
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install kubectl
|
||||
RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
|
||||
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list && \
|
||||
apt-get update && apt-get -y install --no-install-recommends kubectl
|
||||
|
||||
|
||||
# Allow runner to run as root
|
||||
ENV RUNNER_ALLOW_RUNASROOT=1
|
||||
|
||||
# Directory for runner to operate in
|
||||
RUN mkdir /actions-runner
|
||||
WORKDIR /actions-runner
|
||||
COPY --from=Build /actions-runner/_layout /actions-runner
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-console": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
To update kubeInnerHandler under `Misc/layoutbin` run `npm install && npm run all`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "kubeInnerHandler",
|
||||
"version": "1.0.0",
|
||||
"description": "GitHub Actions",
|
||||
"main": "lib/kubeInnerHandler.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"pack": "ncc build -o ../../layoutbin/kubeInnerHandler",
|
||||
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/actions/runner.git"
|
||||
},
|
||||
"keywords": [
|
||||
"actions"
|
||||
],
|
||||
"author": "GitHub Actions",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/core": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.6.4"
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import * as exec from '@actions/exec'
|
||||
import * as core from '@actions/core'
|
||||
import * as events from 'events'
|
||||
import * as readline from 'readline'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
let input = ''
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin
|
||||
})
|
||||
|
||||
rl.on('line', line => {
|
||||
core.debug(`Line from STDIN: ${line}`)
|
||||
input = line
|
||||
})
|
||||
|
||||
await events.once(rl, 'close')
|
||||
|
||||
core.debug(input)
|
||||
|
||||
const execInput = JSON.parse(input)
|
||||
core.debug(JSON.stringify(execInput))
|
||||
|
||||
// podman exec -i --workdir /__w/canary/canary
|
||||
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||
|
||||
const execArgs = []
|
||||
const args = (<string>execInput.arguments).split(' ')
|
||||
core.debug(JSON.stringify(args))
|
||||
execArgs.push(...args)
|
||||
|
||||
core.debug(JSON.stringify(execArgs))
|
||||
|
||||
await exec.exec(execInput.fileName, execArgs, {
|
||||
env: execInput.environmentVariables
|
||||
})
|
||||
}
|
||||
|
||||
run()
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-console": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
To update kubectlHandler under `Misc/layoutbin` run `npm install && npm run all`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "kubectlHandler",
|
||||
"version": "1.0.0",
|
||||
"description": "GitHub Actions",
|
||||
"main": "lib/kubectlHandler.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"pack": "ncc build -o ../../layoutbin/kubectlHandler",
|
||||
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/actions/runner.git"
|
||||
},
|
||||
"keywords": [
|
||||
"actions"
|
||||
],
|
||||
"author": "GitHub Actions",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/core": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.6.4"
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
import * as exec from '@actions/exec'
|
||||
import * as core from '@actions/core'
|
||||
import * as events from 'events'
|
||||
import * as readline from 'readline'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
let input = ''
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin
|
||||
})
|
||||
|
||||
rl.on('line', line => {
|
||||
core.debug(`Line from STDIN: ${line}`)
|
||||
input = line
|
||||
})
|
||||
|
||||
await events.once(rl, 'close')
|
||||
|
||||
core.debug(input)
|
||||
|
||||
const inputJson = JSON.parse(input)
|
||||
core.debug(JSON.stringify(inputJson))
|
||||
|
||||
const command = inputJson.command
|
||||
if (command === 'Create') {
|
||||
const creationInput = inputJson.creationInput
|
||||
core.debug(JSON.stringify(creationInput))
|
||||
const containers = creationInput.containers
|
||||
const jobContainer = containers[0]
|
||||
|
||||
// const networkName = 'actions_podman_network'
|
||||
// // podman network create {network} -> track and return `network` for ${{job.container.network}}
|
||||
// await exec.exec('podman', ['network', 'create', networkName])
|
||||
|
||||
const containerImage = `${jobContainer.containerImage}`
|
||||
// podman pull docker.io/library/{image}
|
||||
// await exec.exec('podman', ['pull', containerImage])
|
||||
|
||||
// kubectl run e088c842be1f46b394212618408aaba0_node1016jessie_6196c9
|
||||
// --image=node:10.16-jessie
|
||||
// -- tail -f /dev/null
|
||||
const runArgs = ['run', 'job-container']
|
||||
// runArgs.push(`--workdir=${jobContainer.containerWorkDirectory}`)
|
||||
// runArgs.push(`--network=${networkName}`)
|
||||
|
||||
// for (const mountVolume of jobContainer.mountVolumes) {
|
||||
// runArgs.push(
|
||||
// `-v=${mountVolume.sourceVolumePath}:${mountVolume.targetVolumePath}`
|
||||
// )
|
||||
// }
|
||||
runArgs.push(`--image=${containerImage}`)
|
||||
runArgs.push(`--`)
|
||||
runArgs.push(`tail`)
|
||||
runArgs.push(`-f`)
|
||||
runArgs.push(`/dev/null`)
|
||||
|
||||
core.debug(JSON.stringify(runArgs))
|
||||
|
||||
// const containerId = await exec.getExecOutput('podman', [
|
||||
// 'create',
|
||||
// // `--workdir ${jobContainer.containerWorkDirectory}`,
|
||||
// `--network=${networkName}`,
|
||||
// // `-v=/Users/ting/Desktop/runner/_layout/_work:/__w`,
|
||||
// `--entrypoint=${jobContainer.containerEntryPoint}`,
|
||||
// `${containerImage}`,
|
||||
// `${jobContainer.containerEntryPointArgs}`
|
||||
// ])
|
||||
|
||||
await exec.exec('kubectl', runArgs)
|
||||
|
||||
// get PATH inside the container
|
||||
|
||||
const waitArgs = ['wait', '--for=condition=Ready', 'pod/job-container']
|
||||
await exec.exec('kubectl', waitArgs)
|
||||
|
||||
// output containerId for ${{job.container.id}}
|
||||
|
||||
// copy over node.js
|
||||
const cpNodeArgs = [
|
||||
'cp',
|
||||
'/actions-runner/externals/node12/bin',
|
||||
'job-container:/__runner_util/'
|
||||
]
|
||||
await exec.exec('kubectl', cpNodeArgs)
|
||||
|
||||
// copy over innerhandler
|
||||
const cpKubeInnerArgs = [
|
||||
'cp',
|
||||
'/actions-runner/bin/kubeInnerHandler',
|
||||
'job-container:/__runner_util/kubeInnerHandler'
|
||||
]
|
||||
await exec.exec('kubectl', cpKubeInnerArgs)
|
||||
|
||||
// copy over _work
|
||||
const cpWorkArgs = ['cp', '/actions-runner/_work', 'job-container:/__w/']
|
||||
await exec.exec('kubectl', cpWorkArgs)
|
||||
|
||||
const creationOutput = {
|
||||
JobContainerId: 'job-container',
|
||||
Network: 'job-container'
|
||||
}
|
||||
|
||||
const output = JSON.stringify({CreationOutput: creationOutput})
|
||||
core.debug(output)
|
||||
|
||||
process.stderr.write(
|
||||
`___CONTAINER_ENGINE_HANDLER_OUTPUT___${output}___CONTAINER_ENGINE_HANDLER_OUTPUT___`
|
||||
)
|
||||
} else if (command === 'Remove') {
|
||||
const removeInput = inputJson.removeInput
|
||||
core.debug(JSON.stringify(removeInput))
|
||||
// const jobContainerId = removeInput.jobContainerId
|
||||
|
||||
// await exec.exec('kubectl', ['delete', 'pod', jobContainerId, '--force'])
|
||||
// await exec.exec('podman', ['network', 'rm', '-f', network])
|
||||
} else if (command === 'Exec') {
|
||||
const execInput = inputJson.execInput
|
||||
core.debug(JSON.stringify(execInput))
|
||||
|
||||
// podman exec -i --workdir /__w/canary/canary
|
||||
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||
|
||||
const cpTempArgs = [
|
||||
'cp',
|
||||
'/actions-runner/_work/_temp',
|
||||
'job-container:/__w/'
|
||||
]
|
||||
await exec.exec('kubectl', cpTempArgs)
|
||||
|
||||
const execArgs = ['exec']
|
||||
execArgs.push(execInput.jobContainer.containerId)
|
||||
execArgs.push('-i')
|
||||
execArgs.push('-t')
|
||||
execArgs.push('--')
|
||||
execArgs.push('/__runner_util/node')
|
||||
execArgs.push('/__runner_util/kubeInnerHandler')
|
||||
|
||||
core.debug(JSON.stringify(execArgs))
|
||||
|
||||
await exec.exec('kubectl', execArgs, {
|
||||
input: Buffer.from(JSON.stringify(execInput))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-console": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
To update podmanHandler under `Misc/layoutbin` run `npm install && npm run all`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "podmanHandler",
|
||||
"version": "1.0.0",
|
||||
"description": "GitHub Actions",
|
||||
"main": "lib/podmanHandler.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"pack": "ncc build -o ../../layoutbin/podmanHandler",
|
||||
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/actions/runner.git"
|
||||
},
|
||||
"keywords": [
|
||||
"actions"
|
||||
],
|
||||
"author": "GitHub Actions",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/core": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.7.12",
|
||||
"@typescript-eslint/parser": "^2.8.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-github": "^2.0.0",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.6.4"
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
import * as exec from '@actions/exec'
|
||||
import * as core from '@actions/core'
|
||||
import * as events from 'events'
|
||||
import * as readline from 'readline'
|
||||
|
||||
async function run(): Promise<void> {
|
||||
let input = ''
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin
|
||||
})
|
||||
|
||||
rl.on('line', line => {
|
||||
core.debug(`Line from STDIN: ${line}`)
|
||||
input = line
|
||||
})
|
||||
|
||||
await events.once(rl, 'close')
|
||||
|
||||
core.debug(input)
|
||||
|
||||
const inputJson = JSON.parse(input)
|
||||
core.debug(JSON.stringify(inputJson))
|
||||
|
||||
const command = inputJson.command
|
||||
if (command === 'Create') {
|
||||
const creationInput = inputJson.creationInput
|
||||
core.debug(JSON.stringify(creationInput))
|
||||
const containers = creationInput.containers
|
||||
const jobContainer = containers[0]
|
||||
|
||||
const networkName = 'actions_podman_network'
|
||||
// podman network create {network} -> track and return `network` for ${{job.container.network}}
|
||||
await exec.exec('podman', ['network', 'create', networkName])
|
||||
|
||||
const containerImage = `docker.io/library/${jobContainer.containerImage}`
|
||||
// podman pull docker.io/library/{image}
|
||||
await exec.exec('podman', ['pull', containerImage])
|
||||
|
||||
// podman create --name e088c842be1f46b394212618408aaba0_node1016jessie_6196c9
|
||||
// --label fa4e14
|
||||
// --workdir /__w/canary/canary
|
||||
// --network github_network_f98a6e1e96e74d919d814c165641cba3
|
||||
// -e "HOME=/github/home" -e GITHUB_ACTIONS=true -e CI=true
|
||||
// -v "/var/run/docker.sock":"/var/run/docker.sock"
|
||||
// -v "/home/runner/work":"/__w"
|
||||
// -v "/home/runner/runners/2.283.2/externals":"/__e":ro
|
||||
// -v "/home/runner/work/_temp":"/__w/_temp"
|
||||
// -v "/home/runner/work/_actions":"/__w/_actions"
|
||||
// -v "/opt/hostedtoolcache":"/__t"
|
||||
// -v "/home/runner/work/_temp/_github_home":"/github/home"
|
||||
// -v "/home/runner/work/_temp/_github_workflow":"/github/workflow"
|
||||
// --entrypoint "tail" node:10.16-jessie "-f" "/dev/null"
|
||||
const creatArgs = ['create']
|
||||
creatArgs.push(`--workdir=${jobContainer.containerWorkDirectory}`)
|
||||
creatArgs.push(`--network=${networkName}`)
|
||||
|
||||
for (const mountVolume of jobContainer.mountVolumes) {
|
||||
creatArgs.push(
|
||||
`-v=${mountVolume.sourceVolumePath}:${mountVolume.targetVolumePath}`
|
||||
)
|
||||
}
|
||||
|
||||
creatArgs.push(`--entrypoint=tail`)
|
||||
creatArgs.push(containerImage)
|
||||
creatArgs.push(`-f`)
|
||||
creatArgs.push(`/dev/null`)
|
||||
|
||||
core.debug(JSON.stringify(creatArgs))
|
||||
|
||||
// const containerId = await exec.getExecOutput('podman', [
|
||||
// 'create',
|
||||
// // `--workdir ${jobContainer.containerWorkDirectory}`,
|
||||
// `--network=${networkName}`,
|
||||
// // `-v=/Users/ting/Desktop/runner/_layout/_work:/__w`,
|
||||
// `--entrypoint=${jobContainer.containerEntryPoint}`,
|
||||
// `${containerImage}`,
|
||||
// `${jobContainer.containerEntryPointArgs}`
|
||||
// ])
|
||||
|
||||
const containerId = await exec.getExecOutput('podman', creatArgs)
|
||||
|
||||
core.debug(JSON.stringify(containerId))
|
||||
|
||||
// podman start {containerId}
|
||||
await exec.exec('podman', ['start', containerId.stdout.trim()])
|
||||
|
||||
// get PATH inside the container
|
||||
|
||||
// output containerId for ${{job.container.id}}
|
||||
|
||||
const creationOutput = {
|
||||
JobContainerId: containerId.stdout.trim(),
|
||||
Network: networkName
|
||||
}
|
||||
|
||||
const output = JSON.stringify({CreationOutput: creationOutput})
|
||||
core.debug(output)
|
||||
|
||||
process.stderr.write(
|
||||
`___CONTAINER_ENGINE_HANDLER_OUTPUT___${output}___CONTAINER_ENGINE_HANDLER_OUTPUT___`
|
||||
)
|
||||
} else if (command === 'Remove') {
|
||||
const removeInput = inputJson.removeInput
|
||||
core.debug(JSON.stringify(removeInput))
|
||||
const jobContainerId = removeInput.jobContainerId
|
||||
const network = removeInput.network
|
||||
|
||||
await exec.exec('podman', ['rm', '-f', jobContainerId])
|
||||
await exec.exec('podman', ['network', 'rm', '-f', network])
|
||||
} else if (command === 'Exec') {
|
||||
const execInput = inputJson.execInput
|
||||
core.debug(JSON.stringify(execInput))
|
||||
|
||||
// podman exec -i --workdir /__w/canary/canary
|
||||
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||
|
||||
const execArgs = ['exec']
|
||||
execArgs.push('-i')
|
||||
execArgs.push(`--workdir=${execInput.workingDirectory}`)
|
||||
for (const envKey of execInput.environmentKeys) {
|
||||
execArgs.push(`-e=${envKey}`)
|
||||
}
|
||||
execArgs.push(execInput.jobContainer.containerId)
|
||||
execArgs.push(execInput.fileName)
|
||||
|
||||
const args = (<string>execInput.arguments).split(' ')
|
||||
core.debug(JSON.stringify(args))
|
||||
|
||||
execArgs.push(...args)
|
||||
|
||||
core.debug(JSON.stringify(execArgs))
|
||||
|
||||
await exec.exec('podman', execArgs)
|
||||
}
|
||||
|
||||
await exec.exec('podman', ['network', 'ls'])
|
||||
await exec.exec('podman', ['ps', '-a'])
|
||||
}
|
||||
|
||||
run()
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
@@ -25,7 +25,5 @@
|
||||
</dict>
|
||||
<key>ProcessType</key>
|
||||
<string>Interactive</string>
|
||||
<key>SessionCreate</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
||||
// Job container creation
|
||||
|
||||
// podman network create {network} -> track and return `network` for ${{job.container.network}}
|
||||
|
||||
// podman pull docker.io/library/{image}
|
||||
|
||||
// podman create --name e088c842be1f46b394212618408aaba0_node1016jessie_6196c9
|
||||
// --label fa4e14
|
||||
// --workdir /__w/canary/canary
|
||||
// --network github_network_f98a6e1e96e74d919d814c165641cba3
|
||||
// -e "HOME=/github/home" -e GITHUB_ACTIONS=true -e CI=true
|
||||
// -v "/var/run/docker.sock":"/var/run/docker.sock"
|
||||
// -v "/home/runner/work":"/__w"
|
||||
// -v "/home/runner/runners/2.283.2/externals":"/__e":ro
|
||||
// -v "/home/runner/work/_temp":"/__w/_temp"
|
||||
// -v "/home/runner/work/_actions":"/__w/_actions"
|
||||
// -v "/opt/hostedtoolcache":"/__t"
|
||||
// -v "/home/runner/work/_temp/_github_home":"/github/home"
|
||||
// -v "/home/runner/work/_temp/_github_workflow":"/github/workflow"
|
||||
// --entrypoint "tail" node:10.16-jessie "-f" "/dev/null"
|
||||
|
||||
// podman start {containerId}
|
||||
|
||||
// get PATH inside the container
|
||||
|
||||
// output containerId for ${{job.container.id}}
|
||||
|
||||
|
||||
|
||||
// Job container stop
|
||||
|
||||
// podman rm --force {containerId}
|
||||
|
||||
// podman network rm {network}
|
||||
|
||||
|
||||
// Run step
|
||||
|
||||
// podman exec -i --workdir /__w/canary/canary
|
||||
// -e GITHUB_JOB -e GITHUB_REF -e GITHUB_SHA -e GITHUB_REPOSITORY
|
||||
// -e GITHUB_REPOSITORY_OWNER -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER
|
||||
// -e GITHUB_RETENTION_DAYS -e GITHUB_RUN_ATTEMPT -e GITHUB_ACTOR
|
||||
// -e GITHUB_WORKFLOW -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GITHUB_EVENT_NAME
|
||||
// -e GITHUB_SERVER_URL -e GITHUB_API_URL -e GITHUB_GRAPHQL_URL
|
||||
// -e GITHUB_WORKSPACE -e GITHUB_ACTION -e GITHUB_EVENT_PATH -e GITHUB_ACTION_REPOSITORY
|
||||
// -e GITHUB_ACTION_REF -e GITHUB_PATH -e GITHUB_ENV -e RUNNER_DEBUG
|
||||
// -e RUNNER_OS -e RUNNER_NAME -e RUNNER_TOOL_CACHE
|
||||
// -e RUNNER_TEMP -e RUNNER_WORKSPACE
|
||||
// eccdf520697a035599d6e8c8dc801f004fdd3797cdce88f590aba3669a88d9bc sh -e /__w/_temp/d3b30383-719c-4e76-a16f-8f85443352be.sh
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function fatal() {
|
||||
echo "error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -n "${GITHUB_PAT:-""}" ] || fatal "GITHUB_PAT variable must be set"
|
||||
[ -n "${RUNNER_CONFIG_URL:-""}" ] || fatal "RUNNER_CONFIG_URL variable must be set"
|
||||
# [ -n "${RUNNER_NAME:-""}" ] || fatal "RUNNER_NAME variable must be set"
|
||||
|
||||
# if [ -n "${RUNNER_NAME}" ]; then
|
||||
# # Use container id to gen unique runner name if name not provide
|
||||
# CONTAINER_ID=$(cat /proc/self/cgroup | head -n 1 | tr '/' '\n' | tail -1 | cut -c1-12)
|
||||
# RUNNER_NAME="actions-runner-${CONTAINER_ID}"
|
||||
# fi
|
||||
|
||||
# if the scope has a slash, it's a repo runner
|
||||
# orgs_or_repos="orgs"
|
||||
# if [[ "$GITHUB_RUNNER_SCOPE" == *\/* ]]; then
|
||||
# orgs_or_repos="repos"
|
||||
# fi
|
||||
|
||||
# RUNNER_REG_URL="${GITHUB_SERVER_URL:=https://github.com}/${GITHUB_RUNNER_SCOPE}"
|
||||
|
||||
# echo "Runner Name : ${RUNNER_NAME}"
|
||||
echo "Registration URL : ${RUNNER_CONFIG_URL}"
|
||||
# echo "GitHub API URL : ${GITHUB_API_URL:=https://api.github.com}"
|
||||
# echo "Runner Labels : ${RUNNER_LABELS:=""}"
|
||||
|
||||
# TODO: if api url is not default, validate it ends in /api/v3
|
||||
|
||||
# RUNNER_LABELS_ARG=""
|
||||
# if [ -n "${RUNNER_LABELS}" ]; then
|
||||
# RUNNER_LABELS_ARG="--labels ${RUNNER_LABELS}"
|
||||
# fi
|
||||
|
||||
# RUNNER_GROUP_ARG=""
|
||||
# if [ -n "${RUNNER_GROUP}" ]; then
|
||||
# RUNNER_GROUP_ARG="--runnergroup ${RUNNER_GROUP}"
|
||||
# fi
|
||||
|
||||
# if [ -n "${K8S_HOST_IP}" ]; then
|
||||
# export http_proxy=http://$K8S_HOST_IP:9090
|
||||
# fi
|
||||
|
||||
# curl -v -s -X POST ${GITHUB_API_URL}/${orgs_or_repos}/${GITHUB_RUNNER_SCOPE}/actions/runners/registration-token -H "authorization: token $GITHUB_PAT" -H "accept: application/vnd.github.everest-preview+json"
|
||||
|
||||
# Generate registration token
|
||||
# RUNNER_REG_TOKEN=$(curl -s -X POST ${GITHUB_API_URL}/${orgs_or_repos}/${GITHUB_RUNNER_SCOPE}/actions/runners/registration-token -H "authorization: token $GITHUB_PAT" -H "accept: application/vnd.github.everest-preview+json" | jq -r '.token')
|
||||
|
||||
# Create the runner and configure it
|
||||
./config.sh --unattended --url $RUNNER_CONFIG_URL --pat $GITHUB_PAT --replace --ephemeral
|
||||
|
||||
# while (! docker version ); do
|
||||
# # Docker takes a few seconds to initialize
|
||||
# echo "Waiting for Docker to launch..."
|
||||
# sleep 1
|
||||
# done
|
||||
|
||||
# unset env
|
||||
unset RUNNER_CONFIG_URL
|
||||
unset GITHUB_PAT
|
||||
|
||||
# Run it
|
||||
./run.sh
|
||||
@@ -2,11 +2,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using GitHub.Runner.Sdk;
|
||||
using GitHub.Services.Common;
|
||||
using GitHub.Services.WebApi;
|
||||
|
||||
namespace GitHub.Runner.Common
|
||||
@@ -39,9 +36,6 @@ namespace GitHub.Runner.Common
|
||||
{
|
||||
_connection = jobConnection;
|
||||
int attemptCount = 5;
|
||||
var configurationStore = HostContext.GetService<IConfigurationStore>();
|
||||
var runnerSettings = configurationStore.GetSettings();
|
||||
|
||||
while (!_connection.HasAuthenticated && attemptCount-- > 0)
|
||||
{
|
||||
try
|
||||
@@ -51,13 +45,8 @@ namespace GitHub.Runner.Common
|
||||
}
|
||||
catch (Exception ex) when (attemptCount > 0)
|
||||
{
|
||||
Trace.Info($"Catch exception during connect. {attemptCount} attempts left.");
|
||||
Trace.Info($"Catch exception during connect. {attemptCount} attemp left.");
|
||||
Trace.Error(ex);
|
||||
|
||||
if (runnerSettings.IsHostedServer)
|
||||
{
|
||||
await CheckNetworkEndpointsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
@@ -67,52 +56,6 @@ namespace GitHub.Runner.Common
|
||||
_hasConnection = true;
|
||||
}
|
||||
|
||||
private async Task CheckNetworkEndpointsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Trace.Info("Requesting Actions Service health endpoint status");
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var actionsClient = new HttpClient(httpClientHandler))
|
||||
{
|
||||
var baseUri = new Uri(_connection.Uri.GetLeftPart(UriPartial.Authority));
|
||||
|
||||
actionsClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
|
||||
// Call the _apis/health endpoint
|
||||
var response = await actionsClient.GetAsync(new Uri(baseUri, "_apis/health"));
|
||||
Trace.Info($"Actions health status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error, but continue as this call is best-effort
|
||||
Trace.Info($"Actions Service health endpoint failed due to {ex.GetType().Name}");
|
||||
Trace.Error(ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Trace.Info("Requesting Github API endpoint status");
|
||||
// This is a dotcom public API... just call it directly
|
||||
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
|
||||
using (var gitHubClient = new HttpClient(httpClientHandler))
|
||||
{
|
||||
gitHubClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents);
|
||||
|
||||
// Call the api.github.com endpoint
|
||||
var response = await gitHubClient.GetAsync("https://api.github.com");
|
||||
Trace.Info($"api.github.com status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log error, but continue as this call is best-effort
|
||||
Trace.Info($"Github API endpoint failed due to {ex.GetType().Name}");
|
||||
Trace.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckConnection()
|
||||
{
|
||||
if (!_hasConnection)
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace GitHub.Runner.Worker.Container
|
||||
_pathMappings.Add(new PathMapping(hostContext.GetDirectory(WellKnownDirectory.Externals), "/__e"));
|
||||
if (this.IsJobContainer)
|
||||
{
|
||||
// this.MountVolumes.Add(new MountVolume("/var/run/docker.sock", "/var/run/docker.sock"));
|
||||
this.MountVolumes.Add(new MountVolume("/var/run/docker.sock", "/var/run/docker.sock"));
|
||||
}
|
||||
#endif
|
||||
if (container.Ports?.Count > 0)
|
||||
|
||||
@@ -131,11 +131,11 @@ namespace GitHub.Runner.Worker.Container
|
||||
{
|
||||
if (String.IsNullOrEmpty(env.Value))
|
||||
{
|
||||
dockerOptions.Add($"-e \"{env.Key}\"");
|
||||
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
dockerOptions.Add($"-e \"{env.Key}={env.Value.Replace("\"", "\\\"")}\"");
|
||||
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key, env.Value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace GitHub.Runner.Worker.Container
|
||||
{
|
||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||
// the value directly in the command
|
||||
dockerOptions.Add($"-e {env.Key}");
|
||||
dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||
}
|
||||
|
||||
// Watermark for GitHub Action environment
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace GitHub.Runner.Worker.Container
|
||||
{
|
||||
public class DockerUtil
|
||||
{
|
||||
private static readonly Regex QuoteEscape = new Regex(@"(\\*)" + "\"", RegexOptions.Compiled);
|
||||
private static readonly Regex EndOfStringEscape = new Regex(@"(\\+)$", RegexOptions.Compiled);
|
||||
|
||||
public static List<PortMapping> ParseDockerPort(IList<string> portMappingLines)
|
||||
{
|
||||
const string targetPort = "targetPort";
|
||||
@@ -17,7 +20,7 @@ namespace GitHub.Runner.Worker.Container
|
||||
string pattern = $"^(?<{targetPort}>\\d+)/(?<{proto}>\\w+) -> (?<{host}>.+):(?<{hostPort}>\\d+)$";
|
||||
|
||||
List<PortMapping> portMappings = new List<PortMapping>();
|
||||
foreach(var line in portMappingLines)
|
||||
foreach (var line in portMappingLines)
|
||||
{
|
||||
Match m = Regex.Match(line, pattern, RegexOptions.None, TimeSpan.FromSeconds(1));
|
||||
if (m.Success)
|
||||
@@ -61,5 +64,44 @@ namespace GitHub.Runner.Worker.Container
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string CreateEscapedOption(string flag, string key)
|
||||
{
|
||||
if (String.IsNullOrEmpty(key))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return $"{flag} {EscapeString(key)}";
|
||||
}
|
||||
|
||||
public static string CreateEscapedOption(string flag, string key, string value)
|
||||
{
|
||||
if (String.IsNullOrEmpty(key))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var escapedString = EscapeString($"{key}={value}");
|
||||
return $"{flag} {escapedString}";
|
||||
}
|
||||
|
||||
private static string EscapeString(string value)
|
||||
{
|
||||
if (String.IsNullOrEmpty(value))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
// Dotnet escaping rules are weird here, we can only escape \ if it precedes a "
|
||||
// If a double quotation mark follows two or an even number of backslashes, each proceeding backslash pair is replaced with one backslash and the double quotation mark is removed.
|
||||
// If a double quotation mark follows an odd number of backslashes, including just one, each preceding pair is replaced with one backslash and the remaining backslash is removed; however, in this case the double quotation mark is not removed.
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs?redirectedfrom=MSDN&view=net-6.0#remarks
|
||||
|
||||
// First, find any \ followed by a " and double the number of \ + 1.
|
||||
value = QuoteEscape.Replace(value, @"$1$1\" + "\"");
|
||||
// Next, what if it ends in `\`, it would escape the end quote. So, we need to detect that at the end of the string and perform the same escape
|
||||
// Luckily, we can just use the $ character with detects the end of string in regex
|
||||
value = EndOfStringEscape.Replace(value, @"$1$1");
|
||||
// Finally, wrap it in quotes
|
||||
return $"\"{value}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,88 +12,9 @@ using GitHub.Runner.Sdk;
|
||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||
using Microsoft.Win32;
|
||||
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||
using System.Threading.Channels;
|
||||
using GitHub.Services.WebApi;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace GitHub.Runner.Worker
|
||||
{
|
||||
[DataContract]
|
||||
public class ContainerEngineHandlerInput
|
||||
{
|
||||
[DataMember]
|
||||
public string Command { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public ContainersCreationInput CreationInput { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public JobContainerExecInput ExecInput { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public ContainersRemoveInput RemoveInput { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ContainersCreationInput
|
||||
{
|
||||
[DataMember]
|
||||
public List<ContainerInfo> Containers { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class JobContainerExecInput
|
||||
{
|
||||
[DataMember]
|
||||
public ContainerInfo JobContainer { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string WorkingDirectory { get; set; }
|
||||
|
||||
|
||||
[DataMember]
|
||||
public string FileName { get; set; }
|
||||
|
||||
|
||||
[DataMember]
|
||||
public string Arguments { get; set; }
|
||||
|
||||
|
||||
[DataMember]
|
||||
public List<string> EnvironmentKeys { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public Dictionary<string, string> EnvironmentVariables { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
[DataContract]
|
||||
public class ContainersRemoveInput
|
||||
{
|
||||
[DataMember]
|
||||
public string Network { get; set; }
|
||||
[DataMember]
|
||||
public string JobContainerId { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ContainersCreationOutput
|
||||
{
|
||||
[DataMember]
|
||||
public string Network { get; set; }
|
||||
[DataMember]
|
||||
public string JobContainerId { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ContainerEngineHandlerOutput
|
||||
{
|
||||
[DataMember]
|
||||
public ContainersCreationOutput CreationOutput { get; set; }
|
||||
}
|
||||
|
||||
[ServiceLocator(Default = typeof(ContainerOperationProvider))]
|
||||
public interface IContainerOperationProvider : IRunnerService
|
||||
{
|
||||
@@ -103,57 +24,25 @@ namespace GitHub.Runner.Worker
|
||||
|
||||
public class ContainerOperationProvider : RunnerService, IContainerOperationProvider
|
||||
{
|
||||
private IDockerCommandManager _dockerManager = null;
|
||||
private IDockerCommandManager _dockerManager;
|
||||
|
||||
public override void Initialize(IHostContext hostContext)
|
||||
{
|
||||
base.Initialize(hostContext);
|
||||
// _dockerManager = HostContext.GetService<IDockerCommandManager>();
|
||||
_dockerManager = HostContext.GetService<IDockerCommandManager>();
|
||||
}
|
||||
|
||||
public async Task StartContainersAsync(IExecutionContext executionContext, object data)
|
||||
{
|
||||
Trace.Entering();
|
||||
// if (!Constants.Runner.Platform.Equals(Constants.OSPlatform.Linux))
|
||||
// {
|
||||
// throw new NotSupportedException("Container operations are only supported on Linux runners");
|
||||
// }
|
||||
if (!Constants.Runner.Platform.Equals(Constants.OSPlatform.Linux))
|
||||
{
|
||||
throw new NotSupportedException("Container operations are only supported on Linux runners");
|
||||
}
|
||||
ArgUtil.NotNull(executionContext, nameof(executionContext));
|
||||
List<ContainerInfo> containers = data as List<ContainerInfo>;
|
||||
ArgUtil.NotNull(containers, nameof(containers));
|
||||
|
||||
foreach (var container in containers)
|
||||
{
|
||||
if (container.IsJobContainer)
|
||||
{
|
||||
// Configure job container - Mount workspace and tools, set up environment, and start long running process
|
||||
var githubContext = executionContext.ExpressionValues["github"] as GitHubContext;
|
||||
ArgUtil.NotNull(githubContext, nameof(githubContext));
|
||||
var workingDirectory = githubContext["workspace"] as StringContextData;
|
||||
ArgUtil.NotNullOrEmpty(workingDirectory, nameof(workingDirectory));
|
||||
container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Work), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Work))));
|
||||
container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Externals), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Externals)), true));
|
||||
container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Temp), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Temp))));
|
||||
// container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Actions), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Actions))));
|
||||
container.MountVolumes.Add(new MountVolume(HostContext.GetDirectory(WellKnownDirectory.Tools), container.TranslateToContainerPath(HostContext.GetDirectory(WellKnownDirectory.Tools))));
|
||||
|
||||
var tempHomeDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Temp), "_github_home");
|
||||
Directory.CreateDirectory(tempHomeDirectory);
|
||||
container.MountVolumes.Add(new MountVolume(tempHomeDirectory, "/github/home"));
|
||||
container.AddPathTranslateMapping(tempHomeDirectory, "/github/home");
|
||||
container.ContainerEnvironmentVariables["HOME"] = container.TranslateToContainerPath(tempHomeDirectory);
|
||||
|
||||
var tempWorkflowDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Temp), "_github_workflow");
|
||||
Directory.CreateDirectory(tempWorkflowDirectory);
|
||||
container.MountVolumes.Add(new MountVolume(tempWorkflowDirectory, "/github/workflow"));
|
||||
container.AddPathTranslateMapping(tempWorkflowDirectory, "/github/workflow");
|
||||
|
||||
container.ContainerWorkDirectory = container.TranslateToContainerPath(workingDirectory);
|
||||
container.ContainerEntryPoint = "tail";
|
||||
container.ContainerEntryPointArgs = "-f /dev/null";
|
||||
}
|
||||
}
|
||||
|
||||
var postJobStep = new JobExtensionRunner(runAsync: this.StopContainersAsync,
|
||||
condition: $"{PipelineTemplateConstants.Always}()",
|
||||
displayName: "Stop containers",
|
||||
@@ -162,71 +51,9 @@ namespace GitHub.Runner.Worker
|
||||
executionContext.Debug($"Register post job cleanup for stopping/deleting containers.");
|
||||
executionContext.RegisterPostJobStep(postJobStep);
|
||||
|
||||
var podManHandler = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "kubectlHandler", "index.js");
|
||||
if (File.Exists(podManHandler))
|
||||
{
|
||||
var podmanInput = new ContainerEngineHandlerInput()
|
||||
{
|
||||
Command = "Create",
|
||||
CreationInput = new ContainersCreationInput()
|
||||
{
|
||||
Containers = containers
|
||||
}
|
||||
};
|
||||
|
||||
ContainerEngineHandlerOutput podmanOutput = null;
|
||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||
{
|
||||
var redirectStandardIn = Channel.CreateUnbounded<string>(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
|
||||
redirectStandardIn.Writer.TryWrite(JsonUtility.ToString(podmanInput));
|
||||
|
||||
processInvoker.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
{
|
||||
executionContext.Output(message.Data);
|
||||
};
|
||||
|
||||
processInvoker.ErrorDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
{
|
||||
executionContext.Output(message.Data);
|
||||
if (podmanOutput == null && message.Data.IndexOf("___CONTAINER_ENGINE_HANDLER_OUTPUT___") >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
podmanOutput = JsonUtility.FromString<ContainerEngineHandlerOutput>(message.Data.Replace("___CONTAINER_ENGINE_HANDLER_OUTPUT___", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
executionContext.Error(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Execute the process. Exit code 0 should always be returned.
|
||||
// A non-zero exit code indicates infrastructural failure.
|
||||
// Task failure should be communicated over STDOUT using ## commands.
|
||||
await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Bin),
|
||||
fileName: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"),
|
||||
arguments: podManHandler,
|
||||
environment: null,
|
||||
requireExitCodeZero: false,
|
||||
outputEncoding: Encoding.UTF8,
|
||||
killProcessOnCancel: false,
|
||||
redirectStandardIn: redirectStandardIn,
|
||||
cancellationToken: executionContext.CancellationToken);
|
||||
}
|
||||
|
||||
if (podmanOutput != null)
|
||||
{
|
||||
executionContext.JobContext.Container["network"] = new StringContextData(podmanOutput.CreationOutput.Network);
|
||||
executionContext.JobContext.Container["id"] = new StringContextData(podmanOutput.CreationOutput.JobContainerId);
|
||||
executionContext.Global.Container.ContainerId = podmanOutput.CreationOutput.JobContainerId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check whether we are inside a container.
|
||||
// Our container feature requires to map working directory from host to the container.
|
||||
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
||||
// Check whether we are inside a container.
|
||||
// Our container feature requires to map working directory from host to the container.
|
||||
// If we are already inside a container, we will not able to find out the real working direcotry path on the host.
|
||||
#if OS_WINDOWS
|
||||
// service CExecSvc is Container Execution Agent.
|
||||
ServiceController[] scServices = ServiceController.GetServices();
|
||||
@@ -235,11 +62,11 @@ namespace GitHub.Runner.Worker
|
||||
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
||||
}
|
||||
#else
|
||||
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
||||
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
{
|
||||
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
||||
}
|
||||
var initProcessCgroup = File.ReadLines("/proc/1/cgroup");
|
||||
if (initProcessCgroup.Any(x => x.IndexOf(":/docker/", StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
{
|
||||
throw new NotSupportedException("Container feature is not supported when runner is already running inside container.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
@@ -263,69 +90,68 @@ namespace GitHub.Runner.Worker
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check docker client/server version
|
||||
executionContext.Output("##[group]Checking docker version");
|
||||
DockerVersion dockerVersion = await _dockerManager.DockerVersion(executionContext);
|
||||
executionContext.Output("##[endgroup]");
|
||||
// Check docker client/server version
|
||||
executionContext.Output("##[group]Checking docker version");
|
||||
DockerVersion dockerVersion = await _dockerManager.DockerVersion(executionContext);
|
||||
executionContext.Output("##[endgroup]");
|
||||
|
||||
ArgUtil.NotNull(dockerVersion.ServerVersion, nameof(dockerVersion.ServerVersion));
|
||||
ArgUtil.NotNull(dockerVersion.ClientVersion, nameof(dockerVersion.ClientVersion));
|
||||
ArgUtil.NotNull(dockerVersion.ServerVersion, nameof(dockerVersion.ServerVersion));
|
||||
ArgUtil.NotNull(dockerVersion.ClientVersion, nameof(dockerVersion.ClientVersion));
|
||||
|
||||
#if OS_WINDOWS
|
||||
Version requiredDockerEngineAPIVersion = new Version(1, 30); // Docker-EE version 17.6
|
||||
#else
|
||||
Version requiredDockerEngineAPIVersion = new Version(1, 35); // Docker-CE version 17.12
|
||||
Version requiredDockerEngineAPIVersion = new Version(1, 35); // Docker-CE version 17.12
|
||||
#endif
|
||||
|
||||
if (dockerVersion.ServerVersion < requiredDockerEngineAPIVersion)
|
||||
{
|
||||
throw new NotSupportedException($"Min required docker engine API server version is '{requiredDockerEngineAPIVersion}', your docker ('{_dockerManager.DockerPath}') server version is '{dockerVersion.ServerVersion}'");
|
||||
}
|
||||
if (dockerVersion.ClientVersion < requiredDockerEngineAPIVersion)
|
||||
{
|
||||
throw new NotSupportedException($"Min required docker engine API client version is '{requiredDockerEngineAPIVersion}', your docker ('{_dockerManager.DockerPath}') client version is '{dockerVersion.ClientVersion}'");
|
||||
}
|
||||
|
||||
// Clean up containers left by previous runs
|
||||
executionContext.Output("##[group]Clean up resources from previous jobs");
|
||||
var staleContainers = await _dockerManager.DockerPS(executionContext, $"--all --quiet --no-trunc --filter \"label={_dockerManager.DockerInstanceLabel}\"");
|
||||
foreach (var staleContainer in staleContainers)
|
||||
{
|
||||
int containerRemoveExitCode = await _dockerManager.DockerRemove(executionContext, staleContainer);
|
||||
if (containerRemoveExitCode != 0)
|
||||
{
|
||||
executionContext.Warning($"Delete stale containers failed, docker rm fail with exit code {containerRemoveExitCode} for container {staleContainer}");
|
||||
}
|
||||
}
|
||||
|
||||
int networkPruneExitCode = await _dockerManager.DockerNetworkPrune(executionContext);
|
||||
if (networkPruneExitCode != 0)
|
||||
{
|
||||
executionContext.Warning($"Delete stale container networks failed, docker network prune fail with exit code {networkPruneExitCode}");
|
||||
}
|
||||
executionContext.Output("##[endgroup]");
|
||||
|
||||
// Create local docker network for this job to avoid port conflict when multiple runners run on same machine.
|
||||
// All containers within a job join the same network
|
||||
executionContext.Output("##[group]Create local container network");
|
||||
var containerNetwork = $"github_network_{Guid.NewGuid().ToString("N")}";
|
||||
await CreateContainerNetworkAsync(executionContext, containerNetwork);
|
||||
executionContext.JobContext.Container["network"] = new StringContextData(containerNetwork);
|
||||
executionContext.Output("##[endgroup]");
|
||||
|
||||
foreach (var container in containers)
|
||||
{
|
||||
container.ContainerNetwork = containerNetwork;
|
||||
await StartContainerAsync(executionContext, container);
|
||||
}
|
||||
|
||||
executionContext.Output("##[group]Waiting for all services to be ready");
|
||||
foreach (var container in containers.Where(c => !c.IsJobContainer))
|
||||
{
|
||||
await ContainerHealthcheck(executionContext, container);
|
||||
}
|
||||
executionContext.Output("##[endgroup]");
|
||||
if (dockerVersion.ServerVersion < requiredDockerEngineAPIVersion)
|
||||
{
|
||||
throw new NotSupportedException($"Min required docker engine API server version is '{requiredDockerEngineAPIVersion}', your docker ('{_dockerManager.DockerPath}') server version is '{dockerVersion.ServerVersion}'");
|
||||
}
|
||||
if (dockerVersion.ClientVersion < requiredDockerEngineAPIVersion)
|
||||
{
|
||||
throw new NotSupportedException($"Min required docker engine API client version is '{requiredDockerEngineAPIVersion}', your docker ('{_dockerManager.DockerPath}') client version is '{dockerVersion.ClientVersion}'");
|
||||
}
|
||||
|
||||
// Clean up containers left by previous runs
|
||||
executionContext.Output("##[group]Clean up resources from previous jobs");
|
||||
var staleContainers = await _dockerManager.DockerPS(executionContext, $"--all --quiet --no-trunc --filter \"label={_dockerManager.DockerInstanceLabel}\"");
|
||||
foreach (var staleContainer in staleContainers)
|
||||
{
|
||||
int containerRemoveExitCode = await _dockerManager.DockerRemove(executionContext, staleContainer);
|
||||
if (containerRemoveExitCode != 0)
|
||||
{
|
||||
executionContext.Warning($"Delete stale containers failed, docker rm fail with exit code {containerRemoveExitCode} for container {staleContainer}");
|
||||
}
|
||||
}
|
||||
|
||||
int networkPruneExitCode = await _dockerManager.DockerNetworkPrune(executionContext);
|
||||
if (networkPruneExitCode != 0)
|
||||
{
|
||||
executionContext.Warning($"Delete stale container networks failed, docker network prune fail with exit code {networkPruneExitCode}");
|
||||
}
|
||||
executionContext.Output("##[endgroup]");
|
||||
|
||||
// Create local docker network for this job to avoid port conflict when multiple runners run on same machine.
|
||||
// All containers within a job join the same network
|
||||
executionContext.Output("##[group]Create local container network");
|
||||
var containerNetwork = $"github_network_{Guid.NewGuid().ToString("N")}";
|
||||
await CreateContainerNetworkAsync(executionContext, containerNetwork);
|
||||
executionContext.JobContext.Container["network"] = new StringContextData(containerNetwork);
|
||||
executionContext.Output("##[endgroup]");
|
||||
|
||||
foreach (var container in containers)
|
||||
{
|
||||
container.ContainerNetwork = containerNetwork;
|
||||
await StartContainerAsync(executionContext, container);
|
||||
}
|
||||
|
||||
executionContext.Output("##[group]Waiting for all services to be ready");
|
||||
foreach (var container in containers.Where(c => !c.IsJobContainer))
|
||||
{
|
||||
await ContainerHealthcheck(executionContext, container);
|
||||
}
|
||||
executionContext.Output("##[endgroup]");
|
||||
}
|
||||
|
||||
public async Task StopContainersAsync(IExecutionContext executionContext, object data)
|
||||
@@ -336,69 +162,12 @@ namespace GitHub.Runner.Worker
|
||||
List<ContainerInfo> containers = data as List<ContainerInfo>;
|
||||
ArgUtil.NotNull(containers, nameof(containers));
|
||||
|
||||
var podManHandler = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "kubectlHandler", "index.js");
|
||||
if (File.Exists(podManHandler))
|
||||
foreach (var container in containers)
|
||||
{
|
||||
var podmanInput = new ContainerEngineHandlerInput()
|
||||
{
|
||||
Command = "Remove",
|
||||
RemoveInput = new ContainersRemoveInput()
|
||||
{
|
||||
Network = executionContext.JobContext.Container["network"].ToString(),
|
||||
JobContainerId = executionContext.JobContext.Container["id"].ToString()
|
||||
}
|
||||
};
|
||||
|
||||
ContainerEngineHandlerOutput podmanOutput = null;
|
||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||
{
|
||||
var redirectStandardIn = Channel.CreateUnbounded<string>(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
|
||||
redirectStandardIn.Writer.TryWrite(JsonUtility.ToString(podmanInput));
|
||||
|
||||
processInvoker.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
{
|
||||
executionContext.Output(message.Data);
|
||||
};
|
||||
|
||||
processInvoker.ErrorDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
{
|
||||
executionContext.Output(message.Data);
|
||||
if (podmanOutput == null && message.Data.IndexOf("___CONTAINER_ENGINE_HANDLER_OUTPUT___") >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
podmanOutput = JsonUtility.FromString<ContainerEngineHandlerOutput>(message.Data.Replace("___CONTAINER_ENGINE_HANDLER_OUTPUT___", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
executionContext.Error(ex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Execute the process. Exit code 0 should always be returned.
|
||||
// A non-zero exit code indicates infrastructural failure.
|
||||
// Task failure should be communicated over STDOUT using ## commands.
|
||||
await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||
fileName: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"),
|
||||
arguments: podManHandler,
|
||||
environment: null,
|
||||
requireExitCodeZero: false,
|
||||
outputEncoding: Encoding.UTF8,
|
||||
killProcessOnCancel: false,
|
||||
redirectStandardIn: redirectStandardIn,
|
||||
cancellationToken: executionContext.CancellationToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var container in containers)
|
||||
{
|
||||
await StopContainerAsync(executionContext, container);
|
||||
}
|
||||
// Remove the container network
|
||||
await RemoveContainerNetworkAsync(executionContext, containers.First().ContainerNetwork);
|
||||
await StopContainerAsync(executionContext, container);
|
||||
}
|
||||
// Remove the container network
|
||||
await RemoveContainerNetworkAsync(executionContext, containers.First().ContainerNetwork);
|
||||
}
|
||||
|
||||
private async Task StartContainerAsync(IExecutionContext executionContext, ContainerInfo container)
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace GitHub.Runner.Worker
|
||||
"job",
|
||||
"path",
|
||||
"ref",
|
||||
"ref_name",
|
||||
"ref_protected",
|
||||
"ref_type",
|
||||
"repository",
|
||||
"repository_owner",
|
||||
"retention_days",
|
||||
@@ -42,16 +39,9 @@ namespace GitHub.Runner.Worker
|
||||
{
|
||||
foreach (var data in this)
|
||||
{
|
||||
if (_contextEnvAllowlist.Contains(data.Key))
|
||||
if (_contextEnvAllowlist.Contains(data.Key) && data.Value is StringContextData value)
|
||||
{
|
||||
if (data.Value is StringContextData value)
|
||||
{
|
||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
|
||||
}
|
||||
else if (data.Value is BooleanContextData booleanValue)
|
||||
{
|
||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", booleanValue.ToString());
|
||||
}
|
||||
yield return new KeyValuePair<string, string>($"GITHUB_{data.Key.ToUpperInvariant()}", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||
event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||
|
||||
IExecutionContext ExecutionContext { get; set; }
|
||||
|
||||
string ResolvePathForStepHost(string path);
|
||||
|
||||
Task<string> DetermineNodeRuntimeVersion(IExecutionContext executionContext);
|
||||
@@ -55,8 +53,6 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||
|
||||
public IExecutionContext ExecutionContext { get; set; }
|
||||
|
||||
public string ResolvePathForStepHost(string path)
|
||||
{
|
||||
return path;
|
||||
@@ -103,8 +99,6 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
public event EventHandler<ProcessDataReceivedEventArgs> OutputDataReceived;
|
||||
public event EventHandler<ProcessDataReceivedEventArgs> ErrorDataReceived;
|
||||
|
||||
public IExecutionContext ExecutionContext { get; set; }
|
||||
|
||||
public string ResolvePathForStepHost(string path)
|
||||
{
|
||||
// make sure container exist.
|
||||
@@ -180,138 +174,69 @@ namespace GitHub.Runner.Worker.Handlers
|
||||
ArgUtil.NotNull(Container, nameof(Container));
|
||||
ArgUtil.NotNullOrEmpty(Container.ContainerId, nameof(Container.ContainerId));
|
||||
|
||||
var podManHandler = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "kubectlHandler", "index.js");
|
||||
if (File.Exists(podManHandler))
|
||||
var dockerManager = HostContext.GetService<IDockerCommandManager>();
|
||||
string dockerClientPath = dockerManager.DockerPath;
|
||||
|
||||
// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
|
||||
IList<string> dockerCommandArgs = new List<string>();
|
||||
dockerCommandArgs.Add($"exec");
|
||||
|
||||
// [OPTIONS]
|
||||
dockerCommandArgs.Add($"-i");
|
||||
dockerCommandArgs.Add($"--workdir {workingDirectory}");
|
||||
foreach (var env in environment)
|
||||
{
|
||||
var podmanInput = new ContainerEngineHandlerInput()
|
||||
{
|
||||
Command = "Exec",
|
||||
ExecInput = new JobContainerExecInput()
|
||||
{
|
||||
JobContainer = this.Container,
|
||||
WorkingDirectory = workingDirectory,
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
EnvironmentKeys = environment.Keys.ToList(),
|
||||
EnvironmentVariables = environment.ToDictionary(x => x.Key, y => y.Value)
|
||||
}
|
||||
};
|
||||
|
||||
// make sure all env are using container path
|
||||
foreach (var envKey in environment.Keys.ToList())
|
||||
{
|
||||
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
||||
}
|
||||
|
||||
// ContainerEngineHandlerOutput podmanOutput = null;
|
||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||
{
|
||||
var redirectStandardIn = Channel.CreateUnbounded<string>(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
|
||||
redirectStandardIn.Writer.TryWrite(JsonUtility.ToString(podmanInput));
|
||||
|
||||
// processInvoker.OutputDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
// {
|
||||
// ExecutionContext.Output(message.Data);
|
||||
// };
|
||||
|
||||
// processInvoker.ErrorDataReceived += delegate (object sender, ProcessDataReceivedEventArgs message)
|
||||
// {
|
||||
// executionContext.Output(message.Data);
|
||||
// if (podmanOutput == null && message.Data.IndexOf("___CONTAINER_ENGINE_HANDLER_OUTPUT___") >= 0)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// podmanOutput = JsonUtility.FromString<ContainerEngineHandlerOutput>(message.Data.Replace("___CONTAINER_ENGINE_HANDLER_OUTPUT___", ""));
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// executionContext.Error(ex);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
processInvoker.OutputDataReceived += OutputDataReceived;
|
||||
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
||||
|
||||
// Execute the process. Exit code 0 should always be returned.
|
||||
// A non-zero exit code indicates infrastructural failure.
|
||||
// Task failure should be communicated over STDOUT using ## commands.
|
||||
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||
fileName: Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"),
|
||||
arguments: podManHandler,
|
||||
environment: environment,
|
||||
requireExitCodeZero: requireExitCodeZero,
|
||||
outputEncoding: Encoding.UTF8,
|
||||
killProcessOnCancel: killProcessOnCancel,
|
||||
redirectStandardIn: redirectStandardIn,
|
||||
cancellationToken: cancellationToken);
|
||||
}
|
||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||
// the value directly in the command
|
||||
dockerCommandArgs.Add(DockerUtil.CreateEscapedOption("-e", env.Key));
|
||||
}
|
||||
else
|
||||
if (!string.IsNullOrEmpty(PrependPath))
|
||||
{
|
||||
var dockerManager = HostContext.GetService<IDockerCommandManager>();
|
||||
string dockerClientPath = dockerManager.DockerPath;
|
||||
// Prepend tool paths to container's PATH
|
||||
var fullPath = !string.IsNullOrEmpty(Container.ContainerRuntimePath) ? $"{PrependPath}:{Container.ContainerRuntimePath}" : PrependPath;
|
||||
dockerCommandArgs.Add($"-e PATH=\"{fullPath}\"");
|
||||
}
|
||||
|
||||
// Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
|
||||
IList<string> dockerCommandArgs = new List<string>();
|
||||
dockerCommandArgs.Add($"exec");
|
||||
// CONTAINER
|
||||
dockerCommandArgs.Add($"{Container.ContainerId}");
|
||||
|
||||
// [OPTIONS]
|
||||
dockerCommandArgs.Add($"-i");
|
||||
dockerCommandArgs.Add($"--workdir {workingDirectory}");
|
||||
foreach (var env in environment)
|
||||
{
|
||||
// e.g. -e MY_SECRET maps the value into the exec'ed process without exposing
|
||||
// the value directly in the command
|
||||
dockerCommandArgs.Add($"-e {env.Key}");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(PrependPath))
|
||||
{
|
||||
// Prepend tool paths to container's PATH
|
||||
var fullPath = !string.IsNullOrEmpty(Container.ContainerRuntimePath) ? $"{PrependPath}:{Container.ContainerRuntimePath}" : PrependPath;
|
||||
dockerCommandArgs.Add($"-e PATH=\"{fullPath}\"");
|
||||
}
|
||||
// COMMAND
|
||||
dockerCommandArgs.Add(fileName);
|
||||
|
||||
// CONTAINER
|
||||
dockerCommandArgs.Add($"{Container.ContainerId}");
|
||||
// [ARG...]
|
||||
dockerCommandArgs.Add(arguments);
|
||||
|
||||
// COMMAND
|
||||
dockerCommandArgs.Add(fileName);
|
||||
string dockerCommandArgstring = string.Join(" ", dockerCommandArgs);
|
||||
|
||||
// [ARG...]
|
||||
dockerCommandArgs.Add(arguments);
|
||||
// make sure all env are using container path
|
||||
foreach (var envKey in environment.Keys.ToList())
|
||||
{
|
||||
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
||||
}
|
||||
|
||||
string dockerCommandArgstring = string.Join(" ", dockerCommandArgs);
|
||||
|
||||
// make sure all env are using container path
|
||||
foreach (var envKey in environment.Keys.ToList())
|
||||
{
|
||||
environment[envKey] = this.Container.TranslateToContainerPath(environment[envKey]);
|
||||
}
|
||||
|
||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||
{
|
||||
processInvoker.OutputDataReceived += OutputDataReceived;
|
||||
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
||||
using (var processInvoker = HostContext.CreateService<IProcessInvoker>())
|
||||
{
|
||||
processInvoker.OutputDataReceived += OutputDataReceived;
|
||||
processInvoker.ErrorDataReceived += ErrorDataReceived;
|
||||
|
||||
#if OS_WINDOWS
|
||||
// It appears that node.exe outputs UTF8 when not in TTY mode.
|
||||
outputEncoding = Encoding.UTF8;
|
||||
#else
|
||||
// Let .NET choose the default.
|
||||
outputEncoding = null;
|
||||
// Let .NET choose the default.
|
||||
outputEncoding = null;
|
||||
#endif
|
||||
|
||||
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||
fileName: dockerClientPath,
|
||||
arguments: dockerCommandArgstring,
|
||||
environment: environment,
|
||||
requireExitCodeZero: requireExitCodeZero,
|
||||
outputEncoding: outputEncoding,
|
||||
killProcessOnCancel: killProcessOnCancel,
|
||||
redirectStandardIn: null,
|
||||
inheritConsoleHandler: inheritConsoleHandler,
|
||||
cancellationToken: cancellationToken);
|
||||
}
|
||||
return await processInvoker.ExecuteAsync(workingDirectory: HostContext.GetDirectory(WellKnownDirectory.Work),
|
||||
fileName: dockerClientPath,
|
||||
arguments: dockerCommandArgstring,
|
||||
environment: environment,
|
||||
requireExitCodeZero: requireExitCodeZero,
|
||||
outputEncoding: outputEncoding,
|
||||
killProcessOnCancel: killProcessOnCancel,
|
||||
redirectStandardIn: null,
|
||||
inheritConsoleHandler: inheritConsoleHandler,
|
||||
cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,5 +144,54 @@ namespace GitHub.Runner.Common.Tests.Worker.Container
|
||||
var actual = DockerUtil.ParseRegistryHostnameFromImageName(input);
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
[InlineData("", "")]
|
||||
[InlineData("foo", "foo")]
|
||||
[InlineData("foo \\ bar", "foo \\ bar")]
|
||||
[InlineData("foo \\", "foo \\\\")]
|
||||
[InlineData("foo \\\\", "foo \\\\\\\\")]
|
||||
[InlineData("foo \\\" bar", "foo \\\\\\\" bar")]
|
||||
[InlineData("foo \\\\\" bar", "foo \\\\\\\\\\\" bar")]
|
||||
public void CreateEscapedOption_keyOnly(string input, string escaped)
|
||||
{
|
||||
var flag = "--example";
|
||||
var actual = DockerUtil.CreateEscapedOption(flag, input);
|
||||
string expected;
|
||||
if (String.IsNullOrEmpty(input))
|
||||
{
|
||||
expected = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
expected = $"{flag} \"{escaped}\"";
|
||||
}
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
[InlineData("foo", "bar", "foo=bar")]
|
||||
[InlineData("foo\\", "bar", "foo\\=bar")]
|
||||
[InlineData("foo\\", "bar\\", "foo\\=bar\\\\")]
|
||||
[InlineData("foo \\","bar \\", "foo \\=bar \\\\")]
|
||||
public void CreateEscapedOption_keyValue(string keyInput, string valueInput, string escapedString)
|
||||
{
|
||||
var flag = "--example";
|
||||
var actual = DockerUtil.CreateEscapedOption(flag, keyInput, valueInput);
|
||||
string expected;
|
||||
if (String.IsNullOrEmpty(keyInput))
|
||||
{
|
||||
expected = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
expected = $"{flag} \"{escapedString}\"";
|
||||
}
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="GenerateConstant">
|
||||
<!-- <Exec Command="git rev-parse HEAD" ConsoleToMSBuild="true">
|
||||
<Exec Command="git rev-parse HEAD" ConsoleToMSBuild="true">
|
||||
<Output TaskParameter="ConsoleOutput" PropertyName="GitInfoCommitHash" />
|
||||
</Exec> -->
|
||||
<Message Text="Building $(Product): --- $(PackageRuntime)" Importance="high"/>
|
||||
</Exec>
|
||||
<Message Text="Building $(Product): $(GitInfoCommitHash) --- $(PackageRuntime)" Importance="high"/>
|
||||
|
||||
<ItemGroup>
|
||||
<BuildConstants Include="namespace GitHub.Runner.Sdk"/>
|
||||
@@ -14,7 +14,7 @@
|
||||
<BuildConstants Include="%20%20%20%20{"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20public static class Source"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20{"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20%20%20%20%20public static readonly string CommitHash = %22dfcfae49e59b6dc3c2bb5295c649b33c4b49c964%22%3B"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20%20%20%20%20public static readonly string CommitHash = %22$(GitInfoCommitHash)%22%3B"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20}%0A"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20public static class RunnerPackage"/>
|
||||
<BuildConstants Include="%20%20%20%20%20%20%20%20{"/>
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
<WriteLinesToFile File="Runner.Sdk/BuildConstants.cs" Lines="@(BuildConstants)" Overwrite="true" />
|
||||
|
||||
<Exec Command="git update-index --assume-unchanged ./Runner.Sdk/BuildConstants.cs" ConsoleToMSBuild="true" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1 +1 @@
|
||||
2.283.3
|
||||
2.283.4
|
||||
|
||||
Reference in New Issue
Block a user