diff --git a/packages/docker/package-lock.json b/packages/docker/package-lock.json index 5916f71c..f43f482a 100644 --- a/packages/docker/package-lock.json +++ b/packages/docker/package-lock.json @@ -27,22 +27,6 @@ "typescript": "^4.6.3" } }, - "../hooklib": { - "version": "0.1.0", - "license": "MIT", - "dependencies": { - "@actions/core": "^1.9.1" - }, - "devDependencies": { - "@types/node": "^17.0.23", - "@typescript-eslint/parser": "^5.18.0", - "@zeit/ncc": "^0.22.3", - "eslint": "^8.12.0", - "eslint-plugin-github": "^4.3.6", - "prettier": "^2.6.2", - "typescript": "^4.6.3" - } - }, "node_modules/@actions/core": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", @@ -2853,8 +2837,12 @@ } }, "node_modules/hooklib": { - "resolved": "../hooklib", - "link": true + "version": "0.1.0", + "resolved": "file:../hooklib", + "license": "MIT", + "dependencies": { + "@actions/core": "^1.9.1" + } }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", @@ -7581,16 +7569,9 @@ "dev": true }, "hooklib": { - "version": "file:../hooklib", + "version": "0.1.0", "requires": { - "@actions/core": "^1.9.1", - "@types/node": "^17.0.23", - "@typescript-eslint/parser": "^5.18.0", - "@zeit/ncc": "^0.22.3", - "eslint": "^8.12.0", - "eslint-plugin-github": "^4.3.6", - "prettier": "^2.6.2", - "typescript": "^4.6.3" + "@actions/core": "^1.9.1" } }, "html-encoding-sniffer": { diff --git a/packages/k8s/README.md b/packages/k8s/README.md index dc35c347..c2b30487 100644 --- a/packages/k8s/README.md +++ b/packages/k8s/README.md @@ -29,6 +29,16 @@ rules: resources: ["secrets"] verbs: ["get", "list", "create", "delete"] ``` +- (Optional, recommended) Granting `events` read access lets the hooks attach + recent `Warning` events (e.g. `FailedScheduling`, `FailedMount`) to the error + message when a pod fails to come online. This permission is **not required** — + if it is missing the hooks still work, they just omit the event section from + diagnostics. +``` +- apiGroups: [""] + resources: ["events"] + verbs: ["get", "list"] +``` - The `ACTIONS_RUNNER_POD_NAME` env should be set to the name of the pod - The `ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER` env should be set to true to prevent the runner from running any jobs outside of a container - The runner pod should map a persistent volume claim into the `_work` directory @@ -36,6 +46,14 @@ rules: - Some actions runner env's are expected to be set. These are set automatically by the runner. - `RUNNER_WORKSPACE` is expected to be set to the workspace of the runner - `GITHUB_WORKSPACE` is expected to be set to the workspace of the job +- Optional tuning env's + - `ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS` — comma-separated list of + extra container `waiting` reasons that should be treated as deterministic + terminal failures (fail fast instead of waiting for the timeout). These are + *added* to the built-ins (`ImagePullBackOff`, `ErrImagePull`, + `InvalidImageName`, `CreateContainerConfigError`, `CreateContainerError`); + the built-ins can never be removed. Use with care — only list reasons that + are truly unrecoverable for your workloads (e.g. `CrashLoopBackOff`). ## Limitations diff --git a/packages/k8s/coverage/clover.xml b/packages/k8s/coverage/clover.xml new file mode 100644 index 00000000..87d6efa5 --- /dev/null +++ b/packages/k8s/coverage/clover.xml @@ -0,0 +1,870 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/k8s/coverage/coverage-final.json b/packages/k8s/coverage/coverage-final.json new file mode 100644 index 00000000..bc3332d2 --- /dev/null +++ b/packages/k8s/coverage/coverage-final.json @@ -0,0 +1,10 @@ +{"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/cleanup-job.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/cleanup-job.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":48}},"1":{"start":{"line":4,"column":2},"end":{"line":4,"column":null}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":22}}},"fnMap":{"0":{"name":"cleanupJob","decl":{"start":{"line":3,"column":22},"end":{"line":3,"column":32}},"loc":{"start":{"line":3,"column":32},"end":{"line":5,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":4,"column":2},"end":{"line":4,"column":null}},"type":"switch","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":null}}]}},"s":{"0":1,"1":0,"2":1},"f":{"0":0},"b":{"0":[0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/constants.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/constants.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}},"1":{"start":{"line":4,"column":15},"end":{"line":4,"column":50}},"2":{"start":{"line":5,"column":2},"end":{"line":9,"column":null}},"3":{"start":{"line":6,"column":4},"end":{"line":8,"column":null}},"4":{"start":{"line":10,"column":2},"end":{"line":10,"column":null}},"5":{"start":{"line":3,"column":0},"end":{"line":3,"column":16}},"6":{"start":{"line":14,"column":2},"end":{"line":17,"column":null}},"7":{"start":{"line":13,"column":0},"end":{"line":13,"column":16}},"8":{"start":{"line":21,"column":2},"end":{"line":24,"column":null}},"9":{"start":{"line":20,"column":0},"end":{"line":20,"column":16}},"10":{"start":{"line":28,"column":15},"end":{"line":28,"column":52}},"11":{"start":{"line":29,"column":2},"end":{"line":31,"column":null}},"12":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"13":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"14":{"start":{"line":27,"column":0},"end":{"line":27,"column":16}},"15":{"start":{"line":36,"column":2},"end":{"line":39,"column":null}},"16":{"start":{"line":35,"column":0},"end":{"line":35,"column":16}},"17":{"start":{"line":42,"column":13},"end":{"line":42,"column":null}},"18":{"start":{"line":43,"column":13},"end":{"line":43,"column":null}},"19":{"start":{"line":44,"column":13},"end":{"line":44,"column":null}},"20":{"start":{"line":45,"column":13},"end":{"line":45,"column":null}},"21":{"start":{"line":46,"column":13},"end":{"line":46,"column":null}},"22":{"start":{"line":48,"column":0},"end":{"line":48,"column":13}},"23":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"24":{"start":{"line":54,"column":2},"end":{"line":56,"column":null}},"25":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"26":{"start":{"line":58,"column":2},"end":{"line":60,"column":null}},"27":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"28":{"start":{"line":62,"column":2},"end":{"line":64,"column":null}},"29":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"30":{"start":{"line":65,"column":0},"end":{"line":65,"column":null}},"31":{"start":{"line":48,"column":13},"end":{"line":48,"column":32}}},"fnMap":{"0":{"name":"getRunnerPodName","decl":{"start":{"line":3,"column":16},"end":{"line":3,"column":32}},"loc":{"start":{"line":3,"column":32},"end":{"line":11,"column":1}}},"1":{"name":"getJobPodName","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":29}},"loc":{"start":{"line":13,"column":29},"end":{"line":18,"column":1}}},"2":{"name":"getStepPodName","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":30}},"loc":{"start":{"line":20,"column":30},"end":{"line":25,"column":1}}},"3":{"name":"getVolumeClaimName","decl":{"start":{"line":27,"column":16},"end":{"line":27,"column":34}},"loc":{"start":{"line":27,"column":34},"end":{"line":33,"column":1}}},"4":{"name":"getSecretName","decl":{"start":{"line":35,"column":16},"end":{"line":35,"column":29}},"loc":{"start":{"line":35,"column":29},"end":{"line":40,"column":1}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":0},"end":{"line":48,"column":13}},"loc":{"start":{"line":48,"column":0},"end":{"line":65,"column":null}}},"6":{"name":"RunnerInstanceLabel","decl":{"start":{"line":50,"column":2},"end":{"line":50,"column":null}},"loc":{"start":{"line":50,"column":2},"end":{"line":52,"column":3}}},"7":{"name":"(anonymous_7)","decl":{"start":{"line":54,"column":2},"end":{"line":54,"column":6}},"loc":{"start":{"line":54,"column":2},"end":{"line":56,"column":3}}},"8":{"name":"(anonymous_8)","decl":{"start":{"line":58,"column":2},"end":{"line":58,"column":6}},"loc":{"start":{"line":58,"column":2},"end":{"line":60,"column":3}}},"9":{"name":"(anonymous_9)","decl":{"start":{"line":62,"column":2},"end":{"line":62,"column":10}},"loc":{"start":{"line":62,"column":2},"end":{"line":64,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":5,"column":2},"end":{"line":9,"column":null}},"type":"if","locations":[{"start":{"line":5,"column":2},"end":{"line":9,"column":null}}]},"1":{"loc":{"start":{"line":29,"column":2},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":2},"end":{"line":31,"column":null}}]}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":1,"8":0,"9":1,"10":0,"11":0,"12":0,"13":0,"14":1,"15":0,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":0,"24":1,"25":0,"26":1,"27":0,"28":1,"29":0,"30":1,"31":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":1,"6":0,"7":0,"8":0,"9":0},"b":{"0":[0],"1":[0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/index.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/index.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":29}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":29}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":33}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":36}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1},"f":{},"b":{}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/prepare-job.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/prepare-job.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":null}},"3":{"start":{"line":10,"column":0},"end":{"line":10,"column":23}},"4":{"start":{"line":11,"column":0},"end":{"line":11,"column":null}},"5":{"start":{"line":19,"column":0},"end":{"line":19,"column":null}},"6":{"start":{"line":29,"column":0},"end":{"line":29,"column":76}},"7":{"start":{"line":35,"column":2},"end":{"line":37,"column":null}},"8":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"9":{"start":{"line":39,"column":2},"end":{"line":39,"column":null}},"10":{"start":{"line":41,"column":8},"end":{"line":41,"column":null}},"11":{"start":{"line":42,"column":2},"end":{"line":42,"column":null}},"12":{"start":{"line":44,"column":6},"end":{"line":44,"column":null}},"13":{"start":{"line":45,"column":2},"end":{"line":53,"column":null}},"14":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"15":{"start":{"line":47,"column":4},"end":{"line":52,"column":null}},"16":{"start":{"line":55,"column":6},"end":{"line":55,"column":null}},"17":{"start":{"line":56,"column":2},"end":{"line":66,"column":null}},"18":{"start":{"line":57,"column":4},"end":{"line":65,"column":null}},"19":{"start":{"line":58,"column":6},"end":{"line":58,"column":null}},"20":{"start":{"line":59,"column":6},"end":{"line":64,"column":null}},"21":{"start":{"line":68,"column":2},"end":{"line":70,"column":null}},"22":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"23":{"start":{"line":72,"column":6},"end":{"line":72,"column":null}},"24":{"start":{"line":74,"column":17},"end":{"line":79,"column":null}},"25":{"start":{"line":74,"column":4},"end":{"line":79,"column":null}},"26":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"27":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"28":{"start":{"line":83,"column":10},"end":{"line":83,"column":null}},"29":{"start":{"line":84,"column":4},"end":{"line":84,"column":null}},"30":{"start":{"line":87,"column":2},"end":{"line":89,"column":null}},"31":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"32":{"start":{"line":90,"column":2},"end":{"line":92,"column":null}},"33":{"start":{"line":95,"column":4},"end":{"line":100,"column":null}},"34":{"start":{"line":103,"column":6},"end":{"line":103,"column":null}},"35":{"start":{"line":105,"column":6},"end":{"line":105,"column":null}},"36":{"start":{"line":107,"column":10},"end":{"line":107,"column":null}},"37":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"38":{"start":{"line":111,"column":2},"end":{"line":111,"column":null}},"39":{"start":{"line":113,"column":6},"end":{"line":113,"column":null}},"40":{"start":{"line":115,"column":15},"end":{"line":118,"column":null}},"41":{"start":{"line":115,"column":4},"end":{"line":118,"column":null}},"42":{"start":{"line":120,"column":4},"end":{"line":122,"column":null}},"43":{"start":{"line":123,"column":10},"end":{"line":123,"column":null}},"44":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"45":{"start":{"line":126,"column":2},"end":{"line":126,"column":null}},"46":{"start":{"line":127,"column":2},"end":{"line":127,"column":null}},"47":{"start":{"line":31,"column":0},"end":{"line":31,"column":22}},"48":{"start":{"line":136,"column":2},"end":{"line":138,"column":null}},"49":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"50":{"start":{"line":139,"column":19},"end":{"line":145,"column":null}},"51":{"start":{"line":147,"column":24},"end":{"line":148,"column":null}},"52":{"start":{"line":148,"column":9},"end":{"line":148,"column":null}},"53":{"start":{"line":150,"column":2},"end":{"line":163,"column":null}},"54":{"start":{"line":151,"column":52},"end":{"line":151,"column":54}},"55":{"start":{"line":152,"column":4},"end":{"line":157,"column":null}},"56":{"start":{"line":153,"column":6},"end":{"line":156,"column":null}},"57":{"start":{"line":153,"column":25},"end":{"line":153,"column":38}},"58":{"start":{"line":153,"column":25},"end":{"line":153,"column":44}},"59":{"start":{"line":153,"column":21},"end":{"line":153,"column":25}},"60":{"start":{"line":154,"column":8},"end":{"line":155,"column":null}},"61":{"start":{"line":159,"column":4},"end":{"line":162,"column":null}},"62":{"start":{"line":165,"column":2},"end":{"line":184,"column":null}},"63":{"start":{"line":167,"column":6},"end":{"line":167,"column":67}},"64":{"start":{"line":167,"column":30},"end":{"line":167,"column":61}},"65":{"start":{"line":169,"column":4},"end":{"line":183,"column":null}},"66":{"start":{"line":170,"column":20},"end":{"line":170,"column":null}},"67":{"start":{"line":172,"column":39},"end":{"line":172,"column":41}},"68":{"start":{"line":173,"column":8},"end":{"line":177,"column":null}},"69":{"start":{"line":174,"column":10},"end":{"line":176,"column":null}},"70":{"start":{"line":174,"column":29},"end":{"line":174,"column":30}},"71":{"start":{"line":174,"column":29},"end":{"line":174,"column":36}},"72":{"start":{"line":174,"column":25},"end":{"line":174,"column":29}},"73":{"start":{"line":175,"column":12},"end":{"line":175,"column":null}},"74":{"start":{"line":179,"column":8},"end":{"line":182,"column":null}},"75":{"start":{"line":186,"column":2},"end":{"line":186,"column":null}},"76":{"start":{"line":190,"column":8},"end":{"line":190,"column":null}},"77":{"start":{"line":191,"column":6},"end":{"line":191,"column":15}},"78":{"start":{"line":192,"column":4},"end":{"line":196,"column":null}},"79":{"start":{"line":203,"column":2},"end":{"line":203,"column":null}},"80":{"start":{"line":206,"column":2},"end":{"line":209,"column":null}},"81":{"start":{"line":207,"column":4},"end":{"line":207,"column":null}},"82":{"start":{"line":208,"column":4},"end":{"line":208,"column":null}},"83":{"start":{"line":211,"column":23},"end":{"line":215,"column":null}},"84":{"start":{"line":216,"column":2},"end":{"line":218,"column":null}},"85":{"start":{"line":217,"column":4},"end":{"line":217,"column":null}},"86":{"start":{"line":220,"column":2},"end":{"line":222,"column":null}},"87":{"start":{"line":221,"column":4},"end":{"line":221,"column":null}},"88":{"start":{"line":224,"column":2},"end":{"line":226,"column":null}},"89":{"start":{"line":225,"column":4},"end":{"line":225,"column":null}},"90":{"start":{"line":228,"column":2},"end":{"line":228,"column":null}},"91":{"start":{"line":229,"column":2},"end":{"line":235,"column":null}},"92":{"start":{"line":229,"column":29},"end":{"line":229,"column":35}},"93":{"start":{"line":229,"column":29},"end":{"line":230,"column":null}},"94":{"start":{"line":229,"column":13},"end":{"line":229,"column":14}},"95":{"start":{"line":229,"column":17},"end":{"line":229,"column":19}},"96":{"start":{"line":229,"column":24},"end":{"line":229,"column":25}},"97":{"start":{"line":232,"column":4},"end":{"line":234,"column":null}},"98":{"start":{"line":233,"column":6},"end":{"line":233,"column":null}},"99":{"start":{"line":237,"column":2},"end":{"line":240,"column":null}},"100":{"start":{"line":242,"column":2},"end":{"line":247,"column":null}},"101":{"start":{"line":243,"column":4},"end":{"line":246,"column":null}},"102":{"start":{"line":249,"column":2},"end":{"line":252,"column":null}},"103":{"start":{"line":254,"column":2},"end":{"line":256,"column":null}},"104":{"start":{"line":255,"column":4},"end":{"line":255,"column":null}},"105":{"start":{"line":258,"column":15},"end":{"line":259,"column":null}},"106":{"start":{"line":259,"column":9},"end":{"line":259,"column":null}},"107":{"start":{"line":262,"column":2},"end":{"line":264,"column":null}},"108":{"start":{"line":263,"column":4},"end":{"line":263,"column":null}},"109":{"start":{"line":266,"column":2},"end":{"line":266,"column":null}},"110":{"start":{"line":200,"column":0},"end":{"line":200,"column":16}}},"fnMap":{"0":{"name":"prepareJob","decl":{"start":{"line":31,"column":22},"end":{"line":31,"column":32}},"loc":{"start":{"line":33,"column":14},"end":{"line":128,"column":null}}},"1":{"name":"(anonymous_23)","decl":{"start":{"line":57,"column":33},"end":{"line":57,"column":40}},"loc":{"start":{"line":57,"column":40},"end":{"line":65,"column":5}}},"2":{"name":"generateResponseFile","decl":{"start":{"line":130,"column":9},"end":{"line":130,"column":29}},"loc":{"start":{"line":134,"column":10},"end":{"line":187,"column":1}}},"3":{"name":"(anonymous_25)","decl":{"start":{"line":148,"column":4},"end":{"line":148,"column":5}},"loc":{"start":{"line":148,"column":5},"end":{"line":148,"column":10}}},"4":{"name":"(anonymous_26)","decl":{"start":{"line":167,"column":25},"end":{"line":167,"column":26}},"loc":{"start":{"line":167,"column":26},"end":{"line":167,"column":51}}},"5":{"name":"(anonymous_27)","decl":{"start":{"line":170,"column":15},"end":{"line":170,"column":16}},"loc":{"start":{"line":170,"column":16},"end":{"line":170,"column":41}}},"6":{"name":"(anonymous_28)","decl":{"start":{"line":171,"column":11},"end":{"line":171,"column":12}},"loc":{"start":{"line":171,"column":12},"end":{"line":183,"column":7}}},"7":{"name":"copyExternalsToRoot","decl":{"start":{"line":189,"column":15},"end":{"line":189,"column":34}},"loc":{"start":{"line":189,"column":34},"end":{"line":198,"column":null}}},"8":{"name":"createContainerSpec","decl":{"start":{"line":200,"column":16},"end":{"line":200,"column":35}},"loc":{"start":{"line":204,"column":35},"end":{"line":267,"column":1}}},"9":{"name":"(anonymous_33)","decl":{"start":{"line":259,"column":4},"end":{"line":259,"column":5}},"loc":{"start":{"line":259,"column":5},"end":{"line":259,"column":10}}}},"branchMap":{"0":{"loc":{"start":{"line":35,"column":2},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":35,"column":2},"end":{"line":37,"column":null}}]},"1":{"loc":{"start":{"line":45,"column":2},"end":{"line":53,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":53,"column":null}}]},"2":{"loc":{"start":{"line":45,"column":6},"end":{"line":45,"column":27}},"type":"cond-expr","locations":[{"start":{"line":45,"column":20},"end":{"line":45,"column":22}},{"start":{"line":45,"column":20},"end":{"line":45,"column":27}}]},"3":{"loc":{"start":{"line":45,"column":6},"end":{"line":45,"column":22}},"type":"binary-expr","locations":[{"start":{"line":45,"column":6},"end":{"line":45,"column":22}},{"start":{"line":45,"column":20},"end":{"line":45,"column":22}}]},"4":{"loc":{"start":{"line":56,"column":2},"end":{"line":66,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":66,"column":null}}]},"5":{"loc":{"start":{"line":56,"column":6},"end":{"line":56,"column":27}},"type":"cond-expr","locations":[{"start":{"line":56,"column":19},"end":{"line":56,"column":21}},{"start":{"line":56,"column":19},"end":{"line":56,"column":27}}]},"6":{"loc":{"start":{"line":56,"column":6},"end":{"line":56,"column":21}},"type":"binary-expr","locations":[{"start":{"line":56,"column":6},"end":{"line":56,"column":21}},{"start":{"line":56,"column":19},"end":{"line":56,"column":21}}]},"7":{"loc":{"start":{"line":68,"column":2},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":2},"end":{"line":70,"column":null}}]},"8":{"loc":{"start":{"line":68,"column":6},"end":{"line":68,"column":39}},"type":"binary-expr","locations":[{"start":{"line":68,"column":6},"end":{"line":68,"column":16}},{"start":{"line":68,"column":20},"end":{"line":68,"column":39}}]},"9":{"loc":{"start":{"line":68,"column":21},"end":{"line":68,"column":37}},"type":"cond-expr","locations":[{"start":{"line":68,"column":29},"end":{"line":68,"column":31}},{"start":{"line":68,"column":21},"end":{"line":68,"column":37}}]},"10":{"loc":{"start":{"line":68,"column":21},"end":{"line":68,"column":31}},"type":"binary-expr","locations":[{"start":{"line":68,"column":21},"end":{"line":68,"column":31}},{"start":{"line":68,"column":21},"end":{"line":68,"column":31}}]},"11":{"loc":{"start":{"line":83,"column":20},"end":{"line":83,"column":64}},"type":"binary-expr","locations":[{"start":{"line":83,"column":20},"end":{"line":83,"column":57}},{"start":{"line":83,"column":61},"end":{"line":83,"column":64}}]},"12":{"loc":{"start":{"line":83,"column":20},"end":{"line":83,"column":57}},"type":"cond-expr","locations":[{"start":{"line":83,"column":48},"end":{"line":83,"column":50}},{"start":{"line":83,"column":48},"end":{"line":83,"column":57}}]},"13":{"loc":{"start":{"line":83,"column":20},"end":{"line":83,"column":50}},"type":"binary-expr","locations":[{"start":{"line":83,"column":20},"end":{"line":83,"column":50}},{"start":{"line":83,"column":48},"end":{"line":83,"column":50}}]},"14":{"loc":{"start":{"line":83,"column":20},"end":{"line":83,"column":48}},"type":"cond-expr","locations":[{"start":{"line":83,"column":42},"end":{"line":83,"column":44}},{"start":{"line":83,"column":42},"end":{"line":83,"column":48}}]},"15":{"loc":{"start":{"line":83,"column":20},"end":{"line":83,"column":44}},"type":"binary-expr","locations":[{"start":{"line":83,"column":20},"end":{"line":83,"column":44}},{"start":{"line":83,"column":42},"end":{"line":83,"column":44}}]},"16":{"loc":{"start":{"line":83,"column":21},"end":{"line":83,"column":42}},"type":"cond-expr","locations":[{"start":{"line":83,"column":24},"end":{"line":83,"column":32}},{"start":{"line":83,"column":21},"end":{"line":83,"column":42}}]},"17":{"loc":{"start":{"line":83,"column":21},"end":{"line":83,"column":32}},"type":"binary-expr","locations":[{"start":{"line":83,"column":21},"end":{"line":83,"column":34}},{"start":{"line":83,"column":21},"end":{"line":83,"column":32}}]},"18":{"loc":{"start":{"line":87,"column":2},"end":{"line":89,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":2},"end":{"line":89,"column":null}}]},"19":{"loc":{"start":{"line":87,"column":7},"end":{"line":87,"column":33}},"type":"cond-expr","locations":[{"start":{"line":87,"column":27},"end":{"line":87,"column":29}},{"start":{"line":87,"column":27},"end":{"line":87,"column":33}}]},"20":{"loc":{"start":{"line":87,"column":7},"end":{"line":87,"column":29}},"type":"binary-expr","locations":[{"start":{"line":87,"column":7},"end":{"line":87,"column":29}},{"start":{"line":87,"column":27},"end":{"line":87,"column":29}}]},"21":{"loc":{"start":{"line":87,"column":7},"end":{"line":87,"column":27}},"type":"cond-expr","locations":[{"start":{"line":87,"column":17},"end":{"line":87,"column":19}},{"start":{"line":87,"column":7},"end":{"line":87,"column":27}}]},"22":{"loc":{"start":{"line":87,"column":7},"end":{"line":87,"column":19}},"type":"binary-expr","locations":[{"start":{"line":87,"column":7},"end":{"line":87,"column":19}},{"start":{"line":87,"column":7},"end":{"line":87,"column":19}}]},"23":{"loc":{"start":{"line":91,"column":54},"end":{"line":91,"column":80}},"type":"cond-expr","locations":[{"start":{"line":91,"column":74},"end":{"line":91,"column":76}},{"start":{"line":91,"column":74},"end":{"line":91,"column":80}}]},"24":{"loc":{"start":{"line":91,"column":54},"end":{"line":91,"column":76}},"type":"binary-expr","locations":[{"start":{"line":91,"column":54},"end":{"line":91,"column":76}},{"start":{"line":91,"column":74},"end":{"line":91,"column":76}}]},"25":{"loc":{"start":{"line":91,"column":54},"end":{"line":91,"column":74}},"type":"cond-expr","locations":[{"start":{"line":91,"column":64},"end":{"line":91,"column":66}},{"start":{"line":91,"column":54},"end":{"line":91,"column":74}}]},"26":{"loc":{"start":{"line":91,"column":54},"end":{"line":91,"column":66}},"type":"binary-expr","locations":[{"start":{"line":91,"column":54},"end":{"line":91,"column":66}},{"start":{"line":91,"column":54},"end":{"line":91,"column":66}}]},"27":{"loc":{"start":{"line":105,"column":42},"end":{"line":105,"column":105}},"type":"cond-expr","locations":[{"start":{"line":105,"column":70},"end":{"line":105,"column":86}},{"start":{"line":105,"column":89},"end":{"line":105,"column":105}}]},"28":{"loc":{"start":{"line":107,"column":20},"end":{"line":107,"column":68}},"type":"cond-expr","locations":[{"start":{"line":107,"column":43},"end":{"line":107,"column":54}},{"start":{"line":107,"column":57},"end":{"line":107,"column":68}}]},"29":{"loc":{"start":{"line":123,"column":20},"end":{"line":123,"column":64}},"type":"binary-expr","locations":[{"start":{"line":123,"column":20},"end":{"line":123,"column":57}},{"start":{"line":123,"column":61},"end":{"line":123,"column":64}}]},"30":{"loc":{"start":{"line":123,"column":20},"end":{"line":123,"column":57}},"type":"cond-expr","locations":[{"start":{"line":123,"column":48},"end":{"line":123,"column":50}},{"start":{"line":123,"column":48},"end":{"line":123,"column":57}}]},"31":{"loc":{"start":{"line":123,"column":20},"end":{"line":123,"column":50}},"type":"binary-expr","locations":[{"start":{"line":123,"column":20},"end":{"line":123,"column":50}},{"start":{"line":123,"column":48},"end":{"line":123,"column":50}}]},"32":{"loc":{"start":{"line":123,"column":20},"end":{"line":123,"column":48}},"type":"cond-expr","locations":[{"start":{"line":123,"column":42},"end":{"line":123,"column":44}},{"start":{"line":123,"column":42},"end":{"line":123,"column":48}}]},"33":{"loc":{"start":{"line":123,"column":20},"end":{"line":123,"column":44}},"type":"binary-expr","locations":[{"start":{"line":123,"column":20},"end":{"line":123,"column":44}},{"start":{"line":123,"column":42},"end":{"line":123,"column":44}}]},"34":{"loc":{"start":{"line":123,"column":21},"end":{"line":123,"column":42}},"type":"cond-expr","locations":[{"start":{"line":123,"column":24},"end":{"line":123,"column":32}},{"start":{"line":123,"column":21},"end":{"line":123,"column":42}}]},"35":{"loc":{"start":{"line":123,"column":21},"end":{"line":123,"column":32}},"type":"binary-expr","locations":[{"start":{"line":123,"column":21},"end":{"line":123,"column":34}},{"start":{"line":123,"column":21},"end":{"line":123,"column":32}}]},"36":{"loc":{"start":{"line":136,"column":2},"end":{"line":138,"column":null}},"type":"if","locations":[{"start":{"line":136,"column":2},"end":{"line":138,"column":null}}]},"37":{"loc":{"start":{"line":136,"column":7},"end":{"line":136,"column":28}},"type":"cond-expr","locations":[{"start":{"line":136,"column":22},"end":{"line":136,"column":24}},{"start":{"line":136,"column":22},"end":{"line":136,"column":28}}]},"38":{"loc":{"start":{"line":136,"column":7},"end":{"line":136,"column":24}},"type":"binary-expr","locations":[{"start":{"line":136,"column":7},"end":{"line":136,"column":24}},{"start":{"line":136,"column":22},"end":{"line":136,"column":24}}]},"39":{"loc":{"start":{"line":147,"column":24},"end":{"line":148,"column":null}},"type":"cond-expr","locations":[{"start":{"line":147,"column":47},"end":{"line":147,"column":49}},{"start":{"line":147,"column":47},"end":{"line":148,"column":null}}]},"40":{"loc":{"start":{"line":147,"column":24},"end":{"line":147,"column":49}},"type":"binary-expr","locations":[{"start":{"line":147,"column":24},"end":{"line":147,"column":49}},{"start":{"line":147,"column":47},"end":{"line":147,"column":49}}]},"41":{"loc":{"start":{"line":147,"column":24},"end":{"line":147,"column":47}},"type":"cond-expr","locations":[{"start":{"line":147,"column":35},"end":{"line":147,"column":37}},{"start":{"line":147,"column":35},"end":{"line":147,"column":47}}]},"42":{"loc":{"start":{"line":147,"column":24},"end":{"line":147,"column":37}},"type":"binary-expr","locations":[{"start":{"line":147,"column":24},"end":{"line":147,"column":37}},{"start":{"line":147,"column":35},"end":{"line":147,"column":37}}]},"43":{"loc":{"start":{"line":150,"column":2},"end":{"line":163,"column":null}},"type":"if","locations":[{"start":{"line":150,"column":2},"end":{"line":163,"column":null}}]},"44":{"loc":{"start":{"line":152,"column":4},"end":{"line":157,"column":null}},"type":"if","locations":[{"start":{"line":152,"column":4},"end":{"line":157,"column":null}}]},"45":{"loc":{"start":{"line":152,"column":8},"end":{"line":152,"column":28}},"type":"cond-expr","locations":[{"start":{"line":152,"column":21},"end":{"line":152,"column":23}},{"start":{"line":152,"column":8},"end":{"line":152,"column":28}}]},"46":{"loc":{"start":{"line":152,"column":8},"end":{"line":152,"column":23}},"type":"binary-expr","locations":[{"start":{"line":152,"column":8},"end":{"line":152,"column":23}},{"start":{"line":152,"column":8},"end":{"line":152,"column":23}}]},"47":{"loc":{"start":{"line":165,"column":2},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":165,"column":2},"end":{"line":184,"column":null}}]},"48":{"loc":{"start":{"line":165,"column":6},"end":{"line":165,"column":27}},"type":"cond-expr","locations":[{"start":{"line":165,"column":19},"end":{"line":165,"column":21}},{"start":{"line":165,"column":19},"end":{"line":165,"column":27}}]},"49":{"loc":{"start":{"line":165,"column":6},"end":{"line":165,"column":21}},"type":"binary-expr","locations":[{"start":{"line":165,"column":6},"end":{"line":165,"column":21}},{"start":{"line":165,"column":19},"end":{"line":165,"column":21}}]},"50":{"loc":{"start":{"line":167,"column":6},"end":{"line":167,"column":67}},"type":"binary-expr","locations":[{"start":{"line":167,"column":6},"end":{"line":167,"column":61}},{"start":{"line":167,"column":65},"end":{"line":167,"column":67}}]},"51":{"loc":{"start":{"line":167,"column":6},"end":{"line":167,"column":61}},"type":"cond-expr","locations":[{"start":{"line":167,"column":19},"end":{"line":167,"column":21}},{"start":{"line":167,"column":19},"end":{"line":167,"column":61}}]},"52":{"loc":{"start":{"line":167,"column":6},"end":{"line":167,"column":21}},"type":"binary-expr","locations":[{"start":{"line":167,"column":6},"end":{"line":167,"column":21}},{"start":{"line":167,"column":19},"end":{"line":167,"column":21}}]},"53":{"loc":{"start":{"line":169,"column":35},"end":{"line":183,"column":8}},"type":"cond-expr","locations":[{"start":{"line":169,"column":59},"end":{"line":169,"column":null}},{"start":{"line":169,"column":59},"end":{"line":183,"column":8}}]},"54":{"loc":{"start":{"line":169,"column":35},"end":{"line":169,"column":null}},"type":"binary-expr","locations":[{"start":{"line":169,"column":35},"end":{"line":169,"column":null}},{"start":{"line":169,"column":59},"end":{"line":169,"column":null}}]},"55":{"loc":{"start":{"line":169,"column":35},"end":{"line":169,"column":59}},"type":"cond-expr","locations":[{"start":{"line":169,"column":47},"end":{"line":169,"column":49}},{"start":{"line":169,"column":47},"end":{"line":169,"column":59}}]},"56":{"loc":{"start":{"line":169,"column":35},"end":{"line":169,"column":49}},"type":"binary-expr","locations":[{"start":{"line":169,"column":35},"end":{"line":169,"column":49}},{"start":{"line":169,"column":47},"end":{"line":169,"column":49}}]},"57":{"loc":{"start":{"line":169,"column":35},"end":{"line":169,"column":47}},"type":"cond-expr","locations":[{"start":{"line":169,"column":41},"end":{"line":169,"column":43}},{"start":{"line":169,"column":35},"end":{"line":169,"column":47}}]},"58":{"loc":{"start":{"line":169,"column":35},"end":{"line":169,"column":43}},"type":"binary-expr","locations":[{"start":{"line":169,"column":35},"end":{"line":169,"column":43}},{"start":{"line":169,"column":35},"end":{"line":169,"column":43}}]},"59":{"loc":{"start":{"line":173,"column":8},"end":{"line":177,"column":null}},"type":"if","locations":[{"start":{"line":173,"column":8},"end":{"line":177,"column":null}}]},"60":{"loc":{"start":{"line":173,"column":12},"end":{"line":173,"column":27}},"type":"cond-expr","locations":[{"start":{"line":173,"column":19},"end":{"line":173,"column":21}},{"start":{"line":173,"column":19},"end":{"line":173,"column":27}}]},"61":{"loc":{"start":{"line":173,"column":12},"end":{"line":173,"column":21}},"type":"binary-expr","locations":[{"start":{"line":173,"column":12},"end":{"line":173,"column":21}},{"start":{"line":173,"column":19},"end":{"line":173,"column":21}}]},"62":{"loc":{"start":{"line":191,"column":6},"end":{"line":191,"column":15}},"type":"if","locations":[{"start":{"line":191,"column":6},"end":{"line":191,"column":15}}]},"63":{"loc":{"start":{"line":203,"column":2},"end":{"line":203,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":2},"end":{"line":203,"column":null}}]},"64":{"loc":{"start":{"line":206,"column":2},"end":{"line":209,"column":null}},"type":"if","locations":[{"start":{"line":206,"column":2},"end":{"line":209,"column":null}}]},"65":{"loc":{"start":{"line":206,"column":6},"end":{"line":206,"column":43}},"type":"binary-expr","locations":[{"start":{"line":206,"column":6},"end":{"line":206,"column":27}},{"start":{"line":206,"column":31},"end":{"line":206,"column":43}}]},"66":{"loc":{"start":{"line":216,"column":2},"end":{"line":218,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":2},"end":{"line":218,"column":null}}]},"67":{"loc":{"start":{"line":220,"column":2},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":2},"end":{"line":222,"column":null}}]},"68":{"loc":{"start":{"line":224,"column":2},"end":{"line":226,"column":null}},"type":"if","locations":[{"start":{"line":224,"column":2},"end":{"line":226,"column":null}}]},"69":{"loc":{"start":{"line":224,"column":6},"end":{"line":224,"column":38}},"type":"cond-expr","locations":[{"start":{"line":224,"column":30},"end":{"line":224,"column":32}},{"start":{"line":224,"column":30},"end":{"line":224,"column":38}}]},"70":{"loc":{"start":{"line":224,"column":6},"end":{"line":224,"column":32}},"type":"binary-expr","locations":[{"start":{"line":224,"column":6},"end":{"line":224,"column":32}},{"start":{"line":224,"column":30},"end":{"line":224,"column":32}}]},"71":{"loc":{"start":{"line":232,"column":4},"end":{"line":234,"column":null}},"type":"if","locations":[{"start":{"line":232,"column":4},"end":{"line":234,"column":null}}]},"72":{"loc":{"start":{"line":232,"column":8},"end":{"line":232,"column":31}},"type":"binary-expr","locations":[{"start":{"line":232,"column":8},"end":{"line":232,"column":13}},{"start":{"line":232,"column":17},"end":{"line":232,"column":31}}]},"73":{"loc":{"start":{"line":242,"column":2},"end":{"line":247,"column":null}},"type":"if","locations":[{"start":{"line":242,"column":2},"end":{"line":247,"column":null}}]},"74":{"loc":{"start":{"line":254,"column":2},"end":{"line":256,"column":null}},"type":"if","locations":[{"start":{"line":254,"column":2},"end":{"line":256,"column":null}}]},"75":{"loc":{"start":{"line":258,"column":15},"end":{"line":259,"column":null}},"type":"cond-expr","locations":[{"start":{"line":258,"column":41},"end":{"line":258,"column":43}},{"start":{"line":258,"column":41},"end":{"line":259,"column":null}}]},"76":{"loc":{"start":{"line":258,"column":15},"end":{"line":258,"column":43}},"type":"binary-expr","locations":[{"start":{"line":258,"column":15},"end":{"line":258,"column":43}},{"start":{"line":258,"column":41},"end":{"line":258,"column":43}}]},"77":{"loc":{"start":{"line":258,"column":15},"end":{"line":258,"column":41}},"type":"cond-expr","locations":[{"start":{"line":258,"column":29},"end":{"line":258,"column":31}},{"start":{"line":258,"column":29},"end":{"line":258,"column":41}}]},"78":{"loc":{"start":{"line":258,"column":15},"end":{"line":258,"column":31}},"type":"binary-expr","locations":[{"start":{"line":258,"column":15},"end":{"line":258,"column":31}},{"start":{"line":258,"column":29},"end":{"line":258,"column":31}}]},"79":{"loc":{"start":{"line":262,"column":2},"end":{"line":264,"column":null}},"type":"if","locations":[{"start":{"line":262,"column":2},"end":{"line":264,"column":null}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":3,"8":0,"9":6,"10":3,"11":6,"12":3,"13":3,"14":3,"15":3,"16":3,"17":3,"18":0,"19":0,"20":0,"21":3,"22":0,"23":3,"24":3,"25":3,"26":0,"27":0,"28":0,"29":0,"30":3,"31":0,"32":3,"33":6,"34":6,"35":2,"36":3,"37":3,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":1,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":3,"77":6,"78":0,"79":3,"80":3,"81":3,"82":3,"83":3,"84":3,"85":0,"86":3,"87":3,"88":3,"89":3,"90":3,"91":3,"92":3,"93":3,"94":0,"95":0,"96":0,"97":0,"98":0,"99":3,"100":3,"101":3,"102":3,"103":3,"104":3,"105":0,"106":0,"107":0,"108":0,"109":0,"110":1},"f":{"0":3,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":3,"8":3,"9":0},"b":{"0":[0],"1":[3],"2":[0,3],"3":[3,3],"4":[0],"5":[0,3],"6":[3,3],"7":[0],"8":[3,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0],"19":[0,3],"20":[3,3],"21":[0,3],"22":[3,3],"23":[0,3],"24":[3,3],"25":[0,3],"26":[3,3],"27":[2,0],"28":[3,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0],"37":[0,0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0],"44":[0],"45":[0,0],"46":[0,0],"47":[0],"48":[0,0],"49":[0,0],"50":[0,0],"51":[0,0],"52":[0,0],"53":[0,0],"54":[0,0],"55":[0,0],"56":[0,0],"57":[0,0],"58":[0,0],"59":[0],"60":[0,0],"61":[0,0],"62":[3],"63":[0],"64":[3],"65":[3,3],"66":[0],"67":[3],"68":[3],"69":[0,3],"70":[3,3],"71":[0],"72":[0,0],"73":[3],"74":[3],"75":[0,0],"76":[0,0],"77":[0,0],"78":[0,0],"79":[0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/run-container-step.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/run-container-step.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":46}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":null}},"3":{"start":{"line":16,"column":0},"end":{"line":16,"column":null}},"4":{"start":{"line":23,"column":0},"end":{"line":23,"column":78}},"5":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"6":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"7":{"start":{"line":32,"column":6},"end":{"line":32,"column":null}},"8":{"start":{"line":33,"column":6},"end":{"line":33,"column":19}},"9":{"start":{"line":35,"column":12},"end":{"line":37,"column":null}},"10":{"start":{"line":38,"column":6},"end":{"line":38,"column":null}},"11":{"start":{"line":39,"column":6},"end":{"line":41,"column":null}},"12":{"start":{"line":40,"column":8},"end":{"line":40,"column":null}},"13":{"start":{"line":42,"column":19},"end":{"line":42,"column":null}},"14":{"start":{"line":42,"column":6},"end":{"line":42,"column":null}},"15":{"start":{"line":44,"column":6},"end":{"line":44,"column":null}},"16":{"start":{"line":45,"column":12},"end":{"line":45,"column":null}},"17":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"18":{"start":{"line":50,"column":8},"end":{"line":50,"column":null}},"19":{"start":{"line":52,"column":2},"end":{"line":52,"column":null}},"20":{"start":{"line":53,"column":8},"end":{"line":53,"column":null}},"21":{"start":{"line":57,"column":10},"end":{"line":57,"column":null}},"22":{"start":{"line":57,"column":4},"end":{"line":57,"column":null}},"23":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"24":{"start":{"line":60,"column":10},"end":{"line":60,"column":null}},"25":{"start":{"line":61,"column":4},"end":{"line":61,"column":null}},"26":{"start":{"line":64,"column":2},"end":{"line":70,"column":null}},"27":{"start":{"line":65,"column":4},"end":{"line":69,"column":null}},"28":{"start":{"line":71,"column":2},"end":{"line":71,"column":null}},"29":{"start":{"line":75,"column":14},"end":{"line":75,"column":null}},"30":{"start":{"line":75,"column":4},"end":{"line":75,"column":null}},"31":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"32":{"start":{"line":78,"column":10},"end":{"line":78,"column":null}},"33":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"34":{"start":{"line":82,"column":2},"end":{"line":91,"column":null}},"35":{"start":{"line":92,"column":2},"end":{"line":92,"column":null}},"36":{"start":{"line":94,"column":2},"end":{"line":94,"column":null}},"37":{"start":{"line":96,"column":2},"end":{"line":96,"column":null}},"38":{"start":{"line":97,"column":2},"end":{"line":97,"column":null}},"39":{"start":{"line":100,"column":17},"end":{"line":100,"column":null}},"40":{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},"41":{"start":{"line":101,"column":2},"end":{"line":103,"column":null}},"42":{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},"43":{"start":{"line":104,"column":2},"end":{"line":111,"column":null}},"44":{"start":{"line":105,"column":4},"end":{"line":109,"column":null}},"45":{"start":{"line":110,"column":4},"end":{"line":110,"column":null}},"46":{"start":{"line":113,"column":14},"end":{"line":113,"column":null}},"47":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}},"48":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},"49":{"start":{"line":115,"column":6},"end":{"line":115,"column":22}},"50":{"start":{"line":116,"column":20},"end":{"line":116,"column":null}},"51":{"start":{"line":116,"column":10},"end":{"line":116,"column":null}},"52":{"start":{"line":117,"column":4},"end":{"line":119,"column":null}},"53":{"start":{"line":120,"column":4},"end":{"line":120,"column":null}},"54":{"start":{"line":123,"column":8},"end":{"line":125,"column":null}},"55":{"start":{"line":126,"column":2},"end":{"line":126,"column":null}},"56":{"start":{"line":25,"column":0},"end":{"line":25,"column":22}},"57":{"start":{"line":134,"column":23},"end":{"line":134,"column":44}},"58":{"start":{"line":135,"column":2},"end":{"line":135,"column":null}},"59":{"start":{"line":136,"column":2},"end":{"line":136,"column":null}},"60":{"start":{"line":137,"column":2},"end":{"line":137,"column":null}},"61":{"start":{"line":138,"column":2},"end":{"line":140,"column":null}},"62":{"start":{"line":141,"column":2},"end":{"line":143,"column":null}},"63":{"start":{"line":145,"column":2},"end":{"line":154,"column":null}},"64":{"start":{"line":146,"column":4},"end":{"line":153,"column":null}},"65":{"start":{"line":155,"column":2},"end":{"line":155,"column":null}},"66":{"start":{"line":157,"column":2},"end":{"line":159,"column":null}},"67":{"start":{"line":158,"column":4},"end":{"line":158,"column":null}},"68":{"start":{"line":161,"column":15},"end":{"line":162,"column":null}},"69":{"start":{"line":162,"column":9},"end":{"line":162,"column":null}},"70":{"start":{"line":164,"column":2},"end":{"line":166,"column":null}},"71":{"start":{"line":165,"column":4},"end":{"line":165,"column":null}},"72":{"start":{"line":168,"column":2},"end":{"line":168,"column":null}}},"fnMap":{"0":{"name":"runContainerStep","decl":{"start":{"line":25,"column":22},"end":{"line":25,"column":38}},"loc":{"start":{"line":26,"column":37},"end":{"line":127,"column":null}}},"1":{"name":"createContainerSpec","decl":{"start":{"line":129,"column":9},"end":{"line":129,"column":28}},"loc":{"start":{"line":132,"column":35},"end":{"line":169,"column":1}}},"2":{"name":"(anonymous_23)","decl":{"start":{"line":162,"column":4},"end":{"line":162,"column":5}},"loc":{"start":{"line":162,"column":5},"end":{"line":162,"column":10}}}},"branchMap":{"0":{"loc":{"start":{"line":82,"column":2},"end":{"line":91,"column":null}},"type":"switch","locations":[{"start":{"line":82,"column":2},"end":{"line":91,"column":null}}]},"1":{"loc":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":30,"column":null}}]},"2":{"loc":{"start":{"line":33,"column":6},"end":{"line":33,"column":19}},"type":"if","locations":[{"start":{"line":33,"column":6},"end":{"line":33,"column":19}}]},"3":{"loc":{"start":{"line":39,"column":6},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":6},"end":{"line":41,"column":null}}]},"4":{"loc":{"start":{"line":45,"column":22},"end":{"line":45,"column":66}},"type":"binary-expr","locations":[{"start":{"line":45,"column":22},"end":{"line":45,"column":59}},{"start":{"line":45,"column":63},"end":{"line":45,"column":66}}]},"5":{"loc":{"start":{"line":45,"column":22},"end":{"line":45,"column":59}},"type":"cond-expr","locations":[{"start":{"line":45,"column":50},"end":{"line":45,"column":52}},{"start":{"line":45,"column":50},"end":{"line":45,"column":59}}]},"6":{"loc":{"start":{"line":45,"column":22},"end":{"line":45,"column":52}},"type":"binary-expr","locations":[{"start":{"line":45,"column":22},"end":{"line":45,"column":52}},{"start":{"line":45,"column":50},"end":{"line":45,"column":52}}]},"7":{"loc":{"start":{"line":45,"column":22},"end":{"line":45,"column":50}},"type":"cond-expr","locations":[{"start":{"line":45,"column":44},"end":{"line":45,"column":46}},{"start":{"line":45,"column":44},"end":{"line":45,"column":50}}]},"8":{"loc":{"start":{"line":45,"column":22},"end":{"line":45,"column":46}},"type":"binary-expr","locations":[{"start":{"line":45,"column":22},"end":{"line":45,"column":46}},{"start":{"line":45,"column":44},"end":{"line":45,"column":46}}]},"9":{"loc":{"start":{"line":45,"column":23},"end":{"line":45,"column":44}},"type":"cond-expr","locations":[{"start":{"line":45,"column":26},"end":{"line":45,"column":34}},{"start":{"line":45,"column":23},"end":{"line":45,"column":44}}]},"10":{"loc":{"start":{"line":45,"column":23},"end":{"line":45,"column":34}},"type":"binary-expr","locations":[{"start":{"line":45,"column":23},"end":{"line":45,"column":36}},{"start":{"line":45,"column":23},"end":{"line":45,"column":34}}]},"11":{"loc":{"start":{"line":60,"column":20},"end":{"line":60,"column":64}},"type":"binary-expr","locations":[{"start":{"line":60,"column":20},"end":{"line":60,"column":57}},{"start":{"line":60,"column":61},"end":{"line":60,"column":64}}]},"12":{"loc":{"start":{"line":60,"column":20},"end":{"line":60,"column":57}},"type":"cond-expr","locations":[{"start":{"line":60,"column":48},"end":{"line":60,"column":50}},{"start":{"line":60,"column":48},"end":{"line":60,"column":57}}]},"13":{"loc":{"start":{"line":60,"column":20},"end":{"line":60,"column":50}},"type":"binary-expr","locations":[{"start":{"line":60,"column":20},"end":{"line":60,"column":50}},{"start":{"line":60,"column":48},"end":{"line":60,"column":50}}]},"14":{"loc":{"start":{"line":60,"column":20},"end":{"line":60,"column":48}},"type":"cond-expr","locations":[{"start":{"line":60,"column":42},"end":{"line":60,"column":44}},{"start":{"line":60,"column":42},"end":{"line":60,"column":48}}]},"15":{"loc":{"start":{"line":60,"column":20},"end":{"line":60,"column":44}},"type":"binary-expr","locations":[{"start":{"line":60,"column":20},"end":{"line":60,"column":44}},{"start":{"line":60,"column":42},"end":{"line":60,"column":44}}]},"16":{"loc":{"start":{"line":60,"column":21},"end":{"line":60,"column":42}},"type":"cond-expr","locations":[{"start":{"line":60,"column":24},"end":{"line":60,"column":32}},{"start":{"line":60,"column":21},"end":{"line":60,"column":42}}]},"17":{"loc":{"start":{"line":60,"column":21},"end":{"line":60,"column":32}},"type":"binary-expr","locations":[{"start":{"line":60,"column":21},"end":{"line":60,"column":34}},{"start":{"line":60,"column":21},"end":{"line":60,"column":32}}]},"18":{"loc":{"start":{"line":64,"column":2},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":2},"end":{"line":70,"column":null}}]},"19":{"loc":{"start":{"line":64,"column":7},"end":{"line":64,"column":25}},"type":"cond-expr","locations":[{"start":{"line":64,"column":19},"end":{"line":64,"column":21}},{"start":{"line":64,"column":19},"end":{"line":64,"column":25}}]},"20":{"loc":{"start":{"line":64,"column":7},"end":{"line":64,"column":21}},"type":"binary-expr","locations":[{"start":{"line":64,"column":7},"end":{"line":64,"column":21}},{"start":{"line":64,"column":19},"end":{"line":64,"column":21}}]},"21":{"loc":{"start":{"line":71,"column":55},"end":{"line":71,"column":73}},"type":"cond-expr","locations":[{"start":{"line":71,"column":67},"end":{"line":71,"column":69}},{"start":{"line":71,"column":67},"end":{"line":71,"column":73}}]},"22":{"loc":{"start":{"line":71,"column":55},"end":{"line":71,"column":69}},"type":"binary-expr","locations":[{"start":{"line":71,"column":55},"end":{"line":71,"column":69}},{"start":{"line":71,"column":67},"end":{"line":71,"column":69}}]},"23":{"loc":{"start":{"line":78,"column":20},"end":{"line":78,"column":64}},"type":"binary-expr","locations":[{"start":{"line":78,"column":20},"end":{"line":78,"column":57}},{"start":{"line":78,"column":61},"end":{"line":78,"column":64}}]},"24":{"loc":{"start":{"line":78,"column":20},"end":{"line":78,"column":57}},"type":"cond-expr","locations":[{"start":{"line":78,"column":48},"end":{"line":78,"column":50}},{"start":{"line":78,"column":48},"end":{"line":78,"column":57}}]},"25":{"loc":{"start":{"line":78,"column":20},"end":{"line":78,"column":50}},"type":"binary-expr","locations":[{"start":{"line":78,"column":20},"end":{"line":78,"column":50}},{"start":{"line":78,"column":48},"end":{"line":78,"column":50}}]},"26":{"loc":{"start":{"line":78,"column":20},"end":{"line":78,"column":48}},"type":"cond-expr","locations":[{"start":{"line":78,"column":42},"end":{"line":78,"column":44}},{"start":{"line":78,"column":42},"end":{"line":78,"column":48}}]},"27":{"loc":{"start":{"line":78,"column":20},"end":{"line":78,"column":44}},"type":"binary-expr","locations":[{"start":{"line":78,"column":20},"end":{"line":78,"column":44}},{"start":{"line":78,"column":42},"end":{"line":78,"column":44}}]},"28":{"loc":{"start":{"line":78,"column":21},"end":{"line":78,"column":42}},"type":"cond-expr","locations":[{"start":{"line":78,"column":24},"end":{"line":78,"column":32}},{"start":{"line":78,"column":21},"end":{"line":78,"column":42}}]},"29":{"loc":{"start":{"line":78,"column":21},"end":{"line":78,"column":32}},"type":"binary-expr","locations":[{"start":{"line":78,"column":21},"end":{"line":78,"column":34}},{"start":{"line":78,"column":21},"end":{"line":78,"column":32}}]},"30":{"loc":{"start":{"line":101,"column":2},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":2},"end":{"line":103,"column":null}}]},"31":{"loc":{"start":{"line":101,"column":6},"end":{"line":101,"column":19}},"type":"cond-expr","locations":[{"start":{"line":101,"column":12},"end":{"line":101,"column":14}},{"start":{"line":101,"column":6},"end":{"line":101,"column":19}}]},"32":{"loc":{"start":{"line":101,"column":6},"end":{"line":101,"column":14}},"type":"binary-expr","locations":[{"start":{"line":101,"column":6},"end":{"line":101,"column":14}},{"start":{"line":101,"column":6},"end":{"line":101,"column":14}}]},"33":{"loc":{"start":{"line":104,"column":2},"end":{"line":111,"column":null}},"type":"if","locations":[{"start":{"line":104,"column":2},"end":{"line":111,"column":null}}]},"34":{"loc":{"start":{"line":104,"column":7},"end":{"line":104,"column":40}},"type":"cond-expr","locations":[{"start":{"line":104,"column":32},"end":{"line":104,"column":34}},{"start":{"line":104,"column":32},"end":{"line":104,"column":40}}]},"35":{"loc":{"start":{"line":104,"column":7},"end":{"line":104,"column":34}},"type":"binary-expr","locations":[{"start":{"line":104,"column":7},"end":{"line":104,"column":34}},{"start":{"line":104,"column":32},"end":{"line":104,"column":34}}]},"36":{"loc":{"start":{"line":104,"column":7},"end":{"line":104,"column":32}},"type":"cond-expr","locations":[{"start":{"line":104,"column":13},"end":{"line":104,"column":15}},{"start":{"line":104,"column":7},"end":{"line":104,"column":32}}]},"37":{"loc":{"start":{"line":104,"column":7},"end":{"line":104,"column":15}},"type":"binary-expr","locations":[{"start":{"line":104,"column":7},"end":{"line":104,"column":15}},{"start":{"line":104,"column":7},"end":{"line":104,"column":15}}]},"38":{"loc":{"start":{"line":115,"column":6},"end":{"line":115,"column":22}},"type":"if","locations":[{"start":{"line":115,"column":6},"end":{"line":115,"column":22}}]},"39":{"loc":{"start":{"line":124,"column":4},"end":{"line":125,"column":28}},"type":"cond-expr","locations":[{"start":{"line":125,"column":18},"end":{"line":125,"column":20}},{"start":{"line":125,"column":18},"end":{"line":125,"column":28}}]},"40":{"loc":{"start":{"line":124,"column":4},"end":{"line":125,"column":20}},"type":"binary-expr","locations":[{"start":{"line":124,"column":4},"end":{"line":125,"column":20}},{"start":{"line":125,"column":18},"end":{"line":125,"column":20}}]},"41":{"loc":{"start":{"line":124,"column":4},"end":{"line":125,"column":18}},"type":"cond-expr","locations":[{"start":{"line":124,"column":71},"end":{"line":124,"column":null}},{"start":{"line":124,"column":71},"end":{"line":125,"column":18}}]},"42":{"loc":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"type":"binary-expr","locations":[{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},{"start":{"line":124,"column":71},"end":{"line":124,"column":null}}]},"43":{"loc":{"start":{"line":126,"column":9},"end":{"line":126,"column":30}},"type":"binary-expr","locations":[{"start":{"line":126,"column":9},"end":{"line":126,"column":25}},{"start":{"line":126,"column":29},"end":{"line":126,"column":30}}]},"44":{"loc":{"start":{"line":138,"column":25},"end":{"line":140,"column":15}},"type":"cond-expr","locations":[{"start":{"line":139,"column":6},"end":{"line":139,"column":28}},{"start":{"line":140,"column":6},"end":{"line":140,"column":15}}]},"45":{"loc":{"start":{"line":141,"column":22},"end":{"line":143,"column":15}},"type":"cond-expr","locations":[{"start":{"line":142,"column":6},"end":{"line":142,"column":39}},{"start":{"line":143,"column":6},"end":{"line":143,"column":15}}]},"46":{"loc":{"start":{"line":141,"column":22},"end":{"line":141,"column":54}},"type":"cond-expr","locations":[{"start":{"line":141,"column":46},"end":{"line":141,"column":48}},{"start":{"line":141,"column":46},"end":{"line":141,"column":54}}]},"47":{"loc":{"start":{"line":141,"column":22},"end":{"line":141,"column":48}},"type":"binary-expr","locations":[{"start":{"line":141,"column":22},"end":{"line":141,"column":48}},{"start":{"line":141,"column":46},"end":{"line":141,"column":48}}]},"48":{"loc":{"start":{"line":145,"column":2},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":145,"column":2},"end":{"line":154,"column":null}}]},"49":{"loc":{"start":{"line":157,"column":2},"end":{"line":159,"column":null}},"type":"if","locations":[{"start":{"line":157,"column":2},"end":{"line":159,"column":null}}]},"50":{"loc":{"start":{"line":161,"column":15},"end":{"line":162,"column":null}},"type":"cond-expr","locations":[{"start":{"line":161,"column":41},"end":{"line":161,"column":43}},{"start":{"line":161,"column":41},"end":{"line":162,"column":null}}]},"51":{"loc":{"start":{"line":161,"column":15},"end":{"line":161,"column":43}},"type":"binary-expr","locations":[{"start":{"line":161,"column":15},"end":{"line":161,"column":43}},{"start":{"line":161,"column":41},"end":{"line":161,"column":43}}]},"52":{"loc":{"start":{"line":161,"column":15},"end":{"line":161,"column":41}},"type":"cond-expr","locations":[{"start":{"line":161,"column":29},"end":{"line":161,"column":31}},{"start":{"line":161,"column":29},"end":{"line":161,"column":41}}]},"53":{"loc":{"start":{"line":161,"column":15},"end":{"line":161,"column":31}},"type":"binary-expr","locations":[{"start":{"line":161,"column":15},"end":{"line":161,"column":31}},{"start":{"line":161,"column":29},"end":{"line":161,"column":31}}]},"54":{"loc":{"start":{"line":164,"column":2},"end":{"line":166,"column":null}},"type":"if","locations":[{"start":{"line":164,"column":2},"end":{"line":166,"column":null}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":1,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0,0],"24":[0,0],"25":[0,0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0],"31":[0,0],"32":[0,0],"33":[0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0,0],"44":[0,0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0],"49":[0],"50":[0,0],"51":[0,0],"52":[0,0],"53":[0,0],"54":[0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/run-script-step.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/hooks/run-script-step.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":24}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":37}},"2":{"start":{"line":5,"column":0},"end":{"line":5,"column":36}},"3":{"start":{"line":6,"column":0},"end":{"line":6,"column":52}},"4":{"start":{"line":7,"column":0},"end":{"line":7,"column":48}},"5":{"start":{"line":14,"column":10},"end":{"line":14,"column":63}},"6":{"start":{"line":15,"column":8},"end":{"line":15,"column":40}},"7":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}},"8":{"start":{"line":24,"column":2},"end":{"line":24,"column":null}},"9":{"start":{"line":26,"column":4},"end":{"line":30,"column":null}},"10":{"start":{"line":32,"column":4},"end":{"line":32,"column":null}},"11":{"start":{"line":33,"column":10},"end":{"line":33,"column":null}},"12":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"13":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"14":{"start":{"line":9,"column":0},"end":{"line":9,"column":22}}},"fnMap":{"0":{"name":"runScriptStep","decl":{"start":{"line":9,"column":22},"end":{"line":9,"column":35}},"loc":{"start":{"line":12,"column":14},"end":{"line":38,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":33,"column":20},"end":{"line":33,"column":64}},"type":"binary-expr","locations":[{"start":{"line":33,"column":20},"end":{"line":33,"column":57}},{"start":{"line":33,"column":61},"end":{"line":33,"column":64}}]},"1":{"loc":{"start":{"line":33,"column":20},"end":{"line":33,"column":57}},"type":"cond-expr","locations":[{"start":{"line":33,"column":48},"end":{"line":33,"column":50}},{"start":{"line":33,"column":48},"end":{"line":33,"column":57}}]},"2":{"loc":{"start":{"line":33,"column":20},"end":{"line":33,"column":50}},"type":"binary-expr","locations":[{"start":{"line":33,"column":20},"end":{"line":33,"column":50}},{"start":{"line":33,"column":48},"end":{"line":33,"column":50}}]},"3":{"loc":{"start":{"line":33,"column":20},"end":{"line":33,"column":48}},"type":"cond-expr","locations":[{"start":{"line":33,"column":42},"end":{"line":33,"column":44}},{"start":{"line":33,"column":42},"end":{"line":33,"column":48}}]},"4":{"loc":{"start":{"line":33,"column":20},"end":{"line":33,"column":44}},"type":"binary-expr","locations":[{"start":{"line":33,"column":20},"end":{"line":33,"column":44}},{"start":{"line":33,"column":42},"end":{"line":33,"column":44}}]},"5":{"loc":{"start":{"line":33,"column":21},"end":{"line":33,"column":42}},"type":"cond-expr","locations":[{"start":{"line":33,"column":24},"end":{"line":33,"column":32}},{"start":{"line":33,"column":21},"end":{"line":33,"column":42}}]},"6":{"loc":{"start":{"line":33,"column":21},"end":{"line":33,"column":32}},"type":"binary-expr","locations":[{"start":{"line":33,"column":21},"end":{"line":33,"column":34}},{"start":{"line":33,"column":21},"end":{"line":33,"column":32}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":1},"f":{"0":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/k8s/index.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/k8s/index.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":46}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":32}},"3":{"start":{"line":5,"column":0},"end":{"line":5,"column":null}},"4":{"start":{"line":13,"column":0},"end":{"line":13,"column":null}},"5":{"start":{"line":21,"column":11},"end":{"line":21,"column":31}},"6":{"start":{"line":23,"column":0},"end":{"line":23,"column":null}},"7":{"start":{"line":25,"column":15},"end":{"line":25,"column":46}},"8":{"start":{"line":26,"column":22},"end":{"line":26,"column":54}},"9":{"start":{"line":27,"column":30},"end":{"line":27,"column":70}},"10":{"start":{"line":29,"column":42},"end":{"line":29,"column":49}},"11":{"start":{"line":31,"column":13},"end":{"line":31,"column":null}},"12":{"start":{"line":33,"column":13},"end":{"line":64,"column":null}},"13":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"14":{"start":{"line":73,"column":2},"end":{"line":75,"column":null}},"15":{"start":{"line":74,"column":4},"end":{"line":74,"column":null}},"16":{"start":{"line":76,"column":2},"end":{"line":78,"column":null}},"17":{"start":{"line":77,"column":4},"end":{"line":77,"column":32}},"18":{"start":{"line":80,"column":8},"end":{"line":80,"column":null}},"19":{"start":{"line":82,"column":2},"end":{"line":82,"column":null}},"20":{"start":{"line":83,"column":2},"end":{"line":83,"column":null}},"21":{"start":{"line":85,"column":2},"end":{"line":85,"column":null}},"22":{"start":{"line":86,"column":2},"end":{"line":86,"column":null}},"23":{"start":{"line":88,"column":8},"end":{"line":88,"column":null}},"24":{"start":{"line":89,"column":2},"end":{"line":91,"column":null}},"25":{"start":{"line":92,"column":2},"end":{"line":92,"column":null}},"26":{"start":{"line":94,"column":2},"end":{"line":94,"column":null}},"27":{"start":{"line":95,"column":2},"end":{"line":95,"column":null}},"28":{"start":{"line":96,"column":2},"end":{"line":96,"column":null}},"29":{"start":{"line":98,"column":19},"end":{"line":98,"column":null}},"30":{"start":{"line":98,"column":8},"end":{"line":98,"column":null}},"31":{"start":{"line":99,"column":6},"end":{"line":99,"column":22}},"32":{"start":{"line":100,"column":4},"end":{"line":100,"column":16}},"33":{"start":{"line":100,"column":27},"end":{"line":100,"column":null}},"34":{"start":{"line":100,"column":4},"end":{"line":100,"column":null}},"35":{"start":{"line":102,"column":4},"end":{"line":102,"column":16}},"36":{"start":{"line":102,"column":27},"end":{"line":102,"column":null}},"37":{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},"38":{"start":{"line":104,"column":8},"end":{"line":104,"column":null}},"39":{"start":{"line":105,"column":2},"end":{"line":110,"column":null}},"40":{"start":{"line":112,"column":6},"end":{"line":112,"column":14}},"41":{"start":{"line":113,"column":19},"end":{"line":113,"column":null}},"42":{"start":{"line":113,"column":10},"end":{"line":113,"column":null}},"43":{"start":{"line":114,"column":4},"end":{"line":116,"column":null}},"44":{"start":{"line":115,"column":6},"end":{"line":115,"column":null}},"45":{"start":{"line":117,"column":10},"end":{"line":117,"column":null}},"46":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"47":{"start":{"line":119,"column":4},"end":{"line":119,"column":null}},"48":{"start":{"line":122,"column":2},"end":{"line":124,"column":null}},"49":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"50":{"start":{"line":126,"column":2},"end":{"line":128,"column":null}},"51":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"52":{"start":{"line":130,"column":19},"end":{"line":130,"column":null}},"53":{"start":{"line":130,"column":10},"end":{"line":130,"column":19}},"54":{"start":{"line":131,"column":2},"end":{"line":131,"column":null}},"55":{"start":{"line":66,"column":0},"end":{"line":66,"column":22}},"56":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"57":{"start":{"line":140,"column":8},"end":{"line":140,"column":null}},"58":{"start":{"line":141,"column":2},"end":{"line":141,"column":null}},"59":{"start":{"line":142,"column":2},"end":{"line":142,"column":null}},"60":{"start":{"line":143,"column":2},"end":{"line":143,"column":null}},"61":{"start":{"line":144,"column":2},"end":{"line":144,"column":null}},"62":{"start":{"line":145,"column":2},"end":{"line":145,"column":null}},"63":{"start":{"line":146,"column":2},"end":{"line":146,"column":null}},"64":{"start":{"line":148,"column":2},"end":{"line":148,"column":null}},"65":{"start":{"line":149,"column":2},"end":{"line":149,"column":null}},"66":{"start":{"line":150,"column":2},"end":{"line":150,"column":null}},"67":{"start":{"line":151,"column":2},"end":{"line":151,"column":null}},"68":{"start":{"line":153,"column":2},"end":{"line":153,"column":null}},"69":{"start":{"line":154,"column":2},"end":{"line":154,"column":null}},"70":{"start":{"line":155,"column":2},"end":{"line":155,"column":null}},"71":{"start":{"line":156,"column":2},"end":{"line":156,"column":null}},"72":{"start":{"line":157,"column":2},"end":{"line":157,"column":null}},"73":{"start":{"line":158,"column":2},"end":{"line":158,"column":null}},"74":{"start":{"line":160,"column":19},"end":{"line":160,"column":null}},"75":{"start":{"line":160,"column":8},"end":{"line":160,"column":null}},"76":{"start":{"line":161,"column":6},"end":{"line":161,"column":22}},"77":{"start":{"line":162,"column":4},"end":{"line":162,"column":27}},"78":{"start":{"line":162,"column":38},"end":{"line":162,"column":null}},"79":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}},"80":{"start":{"line":164,"column":4},"end":{"line":164,"column":27}},"81":{"start":{"line":164,"column":38},"end":{"line":164,"column":null}},"82":{"start":{"line":164,"column":4},"end":{"line":164,"column":null}},"83":{"start":{"line":167,"column":8},"end":{"line":167,"column":null}},"84":{"start":{"line":168,"column":2},"end":{"line":173,"column":null}},"85":{"start":{"line":175,"column":2},"end":{"line":184,"column":null}},"86":{"start":{"line":176,"column":4},"end":{"line":180,"column":null}},"87":{"start":{"line":178,"column":6},"end":{"line":178,"column":null}},"88":{"start":{"line":179,"column":6},"end":{"line":179,"column":null}},"89":{"start":{"line":181,"column":4},"end":{"line":183,"column":null}},"90":{"start":{"line":182,"column":6},"end":{"line":182,"column":null}},"91":{"start":{"line":186,"column":19},"end":{"line":186,"column":null}},"92":{"start":{"line":186,"column":10},"end":{"line":186,"column":19}},"93":{"start":{"line":187,"column":2},"end":{"line":187,"column":null}},"94":{"start":{"line":134,"column":0},"end":{"line":134,"column":22}},"95":{"start":{"line":191,"column":8},"end":{"line":191,"column":null}},"96":{"start":{"line":192,"column":8},"end":{"line":192,"column":null}},"97":{"start":{"line":193,"column":9},"end":{"line":193,"column":null}},"98":{"start":{"line":193,"column":13},"end":{"line":193,"column":null}},"99":{"start":{"line":194,"column":20},"end":{"line":202,"column":null}},"100":{"start":{"line":194,"column":10},"end":{"line":202,"column":null}},"101":{"start":{"line":204,"column":8},"end":{"line":204,"column":9}},"102":{"start":{"line":205,"column":6},"end":{"line":205,"column":null}},"103":{"start":{"line":206,"column":6},"end":{"line":206,"column":14}},"104":{"start":{"line":209,"column":4},"end":{"line":213,"column":null}},"105":{"start":{"line":210,"column":6},"end":{"line":212,"column":null}},"106":{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},"107":{"start":{"line":190,"column":0},"end":{"line":190,"column":22}},"108":{"start":{"line":219,"column":2},"end":{"line":225,"column":null}},"109":{"start":{"line":218,"column":0},"end":{"line":218,"column":22}},"110":{"start":{"line":234,"column":8},"end":{"line":234,"column":null}},"111":{"start":{"line":235,"column":2},"end":{"line":235,"column":null}},"112":{"start":{"line":237,"column":2},"end":{"line":266,"column":null}},"113":{"start":{"line":238,"column":4},"end":{"line":265,"column":null}},"114":{"start":{"line":250,"column":10},"end":{"line":260,"column":null}},"115":{"start":{"line":251,"column":12},"end":{"line":251,"column":null}},"116":{"start":{"line":253,"column":12},"end":{"line":258,"column":null}},"117":{"start":{"line":259,"column":12},"end":{"line":259,"column":null}},"118":{"start":{"line":265,"column":18},"end":{"line":265,"column":28}},"119":{"start":{"line":228,"column":0},"end":{"line":228,"column":22}},"120":{"start":{"line":270,"column":8},"end":{"line":270,"column":null}},"121":{"start":{"line":271,"column":9},"end":{"line":271,"column":null}},"122":{"start":{"line":271,"column":13},"end":{"line":271,"column":null}},"123":{"start":{"line":273,"column":10},"end":{"line":273,"column":41}},"124":{"start":{"line":273,"column":6},"end":{"line":275,"column":null}},"125":{"start":{"line":274,"column":8},"end":{"line":274,"column":14}},"126":{"start":{"line":277,"column":6},"end":{"line":277,"column":null}},"127":{"start":{"line":279,"column":4},"end":{"line":279,"column":null}},"128":{"start":{"line":269,"column":0},"end":{"line":269,"column":22}},"129":{"start":{"line":286,"column":8},"end":{"line":296,"column":null}},"130":{"start":{"line":298,"column":8},"end":{"line":298,"column":null}},"131":{"start":{"line":300,"column":8},"end":{"line":300,"column":null}},"132":{"start":{"line":301,"column":8},"end":{"line":301,"column":null}},"133":{"start":{"line":302,"column":2},"end":{"line":302,"column":null}},"134":{"start":{"line":303,"column":2},"end":{"line":303,"column":null}},"135":{"start":{"line":304,"column":2},"end":{"line":304,"column":null}},"136":{"start":{"line":305,"column":2},"end":{"line":305,"column":null}},"137":{"start":{"line":306,"column":2},"end":{"line":306,"column":null}},"138":{"start":{"line":307,"column":2},"end":{"line":309,"column":null}},"139":{"start":{"line":310,"column":2},"end":{"line":310,"column":null}},"140":{"start":{"line":311,"column":2},"end":{"line":311,"column":null}},"141":{"start":{"line":312,"column":2},"end":{"line":316,"column":null}},"142":{"start":{"line":318,"column":19},"end":{"line":318,"column":null}},"143":{"start":{"line":318,"column":10},"end":{"line":318,"column":19}},"144":{"start":{"line":319,"column":2},"end":{"line":319,"column":null}},"145":{"start":{"line":283,"column":0},"end":{"line":283,"column":22}},"146":{"start":{"line":325,"column":8},"end":{"line":325,"column":null}},"147":{"start":{"line":327,"column":8},"end":{"line":327,"column":null}},"148":{"start":{"line":328,"column":8},"end":{"line":328,"column":null}},"149":{"start":{"line":329,"column":2},"end":{"line":329,"column":null}},"150":{"start":{"line":330,"column":2},"end":{"line":330,"column":null}},"151":{"start":{"line":331,"column":2},"end":{"line":331,"column":null}},"152":{"start":{"line":332,"column":2},"end":{"line":332,"column":null}},"153":{"start":{"line":334,"column":2},"end":{"line":336,"column":null}},"154":{"start":{"line":337,"column":2},"end":{"line":337,"column":null}},"155":{"start":{"line":338,"column":2},"end":{"line":338,"column":null}},"156":{"start":{"line":339,"column":2},"end":{"line":341,"column":null}},"157":{"start":{"line":339,"column":13},"end":{"line":339,"column":25}},"158":{"start":{"line":340,"column":4},"end":{"line":340,"column":null}},"159":{"start":{"line":343,"column":2},"end":{"line":343,"column":null}},"160":{"start":{"line":344,"column":2},"end":{"line":344,"column":null}},"161":{"start":{"line":322,"column":0},"end":{"line":322,"column":22}},"162":{"start":{"line":348,"column":2},"end":{"line":348,"column":null}},"163":{"start":{"line":347,"column":0},"end":{"line":347,"column":22}},"164":{"start":{"line":352,"column":21},"end":{"line":359,"column":null}},"165":{"start":{"line":352,"column":8},"end":{"line":359,"column":null}},"166":{"start":{"line":360,"column":2},"end":{"line":362,"column":null}},"167":{"start":{"line":361,"column":4},"end":{"line":361,"column":10}},"168":{"start":{"line":364,"column":2},"end":{"line":368,"column":null}},"169":{"start":{"line":366,"column":16},"end":{"line":366,"column":null}},"170":{"start":{"line":351,"column":0},"end":{"line":351,"column":22}},"171":{"start":{"line":371,"column":13},"end":{"line":377,"column":null}},"172":{"start":{"line":379,"column":13},"end":{"line":383,"column":null}},"173":{"start":{"line":385,"column":13},"end":{"line":389,"column":null}},"174":{"start":{"line":391,"column":30},"end":{"line":391,"column":32}},"175":{"start":{"line":394,"column":16},"end":{"line":394,"column":79}},"176":{"start":{"line":395,"column":2},"end":{"line":397,"column":null}},"177":{"start":{"line":396,"column":4},"end":{"line":396,"column":null}},"178":{"start":{"line":398,"column":18},"end":{"line":398,"column":56}},"179":{"start":{"line":399,"column":2},"end":{"line":404,"column":null}},"180":{"start":{"line":399,"column":23},"end":{"line":399,"column":28}},"181":{"start":{"line":399,"column":23},"end":{"line":399,"column":39}},"182":{"start":{"line":399,"column":19},"end":{"line":399,"column":23}},"183":{"start":{"line":400,"column":20},"end":{"line":400,"column":33}},"184":{"start":{"line":401,"column":4},"end":{"line":403,"column":null}},"185":{"start":{"line":402,"column":6},"end":{"line":402,"column":null}},"186":{"start":{"line":405,"column":2},"end":{"line":405,"column":null}},"187":{"start":{"line":393,"column":0},"end":{"line":393,"column":16}},"188":{"start":{"line":409,"column":16},"end":{"line":409,"column":77}},"189":{"start":{"line":410,"column":2},"end":{"line":412,"column":null}},"190":{"start":{"line":411,"column":4},"end":{"line":411,"column":null}},"191":{"start":{"line":413,"column":18},"end":{"line":413,"column":54}},"192":{"start":{"line":414,"column":2},"end":{"line":419,"column":null}},"193":{"start":{"line":414,"column":23},"end":{"line":414,"column":28}},"194":{"start":{"line":414,"column":23},"end":{"line":414,"column":39}},"195":{"start":{"line":414,"column":19},"end":{"line":414,"column":23}},"196":{"start":{"line":415,"column":20},"end":{"line":415,"column":33}},"197":{"start":{"line":416,"column":4},"end":{"line":418,"column":null}},"198":{"start":{"line":417,"column":6},"end":{"line":417,"column":null}},"199":{"start":{"line":420,"column":2},"end":{"line":420,"column":null}},"200":{"start":{"line":408,"column":0},"end":{"line":408,"column":16}},"201":{"start":{"line":425,"column":4},"end":{"line":425,"column":70}},"202":{"start":{"line":426,"column":2},"end":{"line":428,"column":null}},"203":{"start":{"line":427,"column":4},"end":{"line":427,"column":null}},"204":{"start":{"line":429,"column":18},"end":{"line":429,"column":59}},"205":{"start":{"line":430,"column":2},"end":{"line":435,"column":null}},"206":{"start":{"line":430,"column":23},"end":{"line":430,"column":28}},"207":{"start":{"line":430,"column":23},"end":{"line":430,"column":39}},"208":{"start":{"line":430,"column":19},"end":{"line":430,"column":23}},"209":{"start":{"line":431,"column":20},"end":{"line":431,"column":33}},"210":{"start":{"line":432,"column":4},"end":{"line":434,"column":null}},"211":{"start":{"line":433,"column":6},"end":{"line":433,"column":null}},"212":{"start":{"line":436,"column":2},"end":{"line":436,"column":null}},"213":{"start":{"line":423,"column":0},"end":{"line":423,"column":16}},"214":{"start":{"line":440,"column":27},"end":{"line":440,"column":29}},"215":{"start":{"line":441,"column":31},"end":{"line":441,"column":63}},"216":{"start":{"line":442,"column":19},"end":{"line":444,"column":null}},"217":{"start":{"line":446,"column":2},"end":{"line":455,"column":null}},"218":{"start":{"line":446,"column":19},"end":{"line":446,"column":30}},"219":{"start":{"line":446,"column":15},"end":{"line":446,"column":19}},"220":{"start":{"line":447,"column":20},"end":{"line":447,"column":37}},"221":{"start":{"line":448,"column":4},"end":{"line":454,"column":null}},"222":{"start":{"line":449,"column":6},"end":{"line":453,"column":null}},"223":{"start":{"line":456,"column":2},"end":{"line":456,"column":null}},"224":{"start":{"line":439,"column":0},"end":{"line":439,"column":16}},"225":{"start":{"line":460,"column":8},"end":{"line":460,"column":null}},"226":{"start":{"line":463,"column":21},"end":{"line":469,"column":null}},"227":{"start":{"line":463,"column":12},"end":{"line":463,"column":21}},"228":{"start":{"line":470,"column":4},"end":{"line":470,"column":null}},"229":{"start":{"line":472,"column":4},"end":{"line":476,"column":null}},"230":{"start":{"line":477,"column":4},"end":{"line":477,"column":null}},"231":{"start":{"line":480,"column":8},"end":{"line":480,"column":null}},"232":{"start":{"line":481,"column":2},"end":{"line":489,"column":null}},"233":{"start":{"line":481,"column":13},"end":{"line":481,"column":18}},"234":{"start":{"line":482,"column":4},"end":{"line":488,"column":null}},"235":{"start":{"line":487,"column":6},"end":{"line":487,"column":null}},"236":{"start":{"line":490,"column":2},"end":{"line":490,"column":null}},"237":{"start":{"line":459,"column":0},"end":{"line":459,"column":22}},"238":{"start":{"line":494,"column":27},"end":{"line":494,"column":29}},"239":{"start":{"line":495,"column":2},"end":{"line":503,"column":null}},"240":{"start":{"line":495,"column":21},"end":{"line":495,"column":24}},"241":{"start":{"line":495,"column":21},"end":{"line":495,"column":49}},"242":{"start":{"line":495,"column":17},"end":{"line":495,"column":21}},"243":{"start":{"line":496,"column":4},"end":{"line":502,"column":null}},"244":{"start":{"line":497,"column":6},"end":{"line":501,"column":null}},"245":{"start":{"line":504,"column":2},"end":{"line":504,"column":null}},"246":{"start":{"line":493,"column":0},"end":{"line":493,"column":16}},"247":{"start":{"line":508,"column":27},"end":{"line":508,"column":29}},"248":{"start":{"line":509,"column":31},"end":{"line":509,"column":66}},"249":{"start":{"line":510,"column":19},"end":{"line":512,"column":null}},"250":{"start":{"line":514,"column":2},"end":{"line":523,"column":null}},"251":{"start":{"line":514,"column":19},"end":{"line":514,"column":30}},"252":{"start":{"line":514,"column":15},"end":{"line":514,"column":19}},"253":{"start":{"line":515,"column":23},"end":{"line":515,"column":43}},"254":{"start":{"line":516,"column":4},"end":{"line":522,"column":null}},"255":{"start":{"line":517,"column":6},"end":{"line":521,"column":null}},"256":{"start":{"line":524,"column":2},"end":{"line":524,"column":null}},"257":{"start":{"line":507,"column":0},"end":{"line":507,"column":16}},"258":{"start":{"line":530,"column":10},"end":{"line":530,"column":null}},"259":{"start":{"line":530,"column":4},"end":{"line":530,"column":null}},"260":{"start":{"line":532,"column":4},"end":{"line":534,"column":null}},"261":{"start":{"line":537,"column":8},"end":{"line":537,"column":null}},"262":{"start":{"line":538,"column":8},"end":{"line":538,"column":null}},"263":{"start":{"line":540,"column":2},"end":{"line":546,"column":null}},"264":{"start":{"line":541,"column":4},"end":{"line":545,"column":null}},"265":{"start":{"line":547,"column":2},"end":{"line":549,"column":null}},"266":{"start":{"line":548,"column":4},"end":{"line":548,"column":null}},"267":{"start":{"line":551,"column":8},"end":{"line":551,"column":null}},"268":{"start":{"line":552,"column":2},"end":{"line":552,"column":null}},"269":{"start":{"line":554,"column":2},"end":{"line":562,"column":null}},"270":{"start":{"line":554,"column":13},"end":{"line":554,"column":21}},"271":{"start":{"line":555,"column":4},"end":{"line":561,"column":null}},"272":{"start":{"line":556,"column":6},"end":{"line":560,"column":null}},"273":{"start":{"line":564,"column":8},"end":{"line":567,"column":null}},"274":{"start":{"line":568,"column":2},"end":{"line":587,"column":null}},"275":{"start":{"line":568,"column":13},"end":{"line":568,"column":19}},"276":{"start":{"line":569,"column":10},"end":{"line":569,"column":null}},"277":{"start":{"line":570,"column":4},"end":{"line":576,"column":null}},"278":{"start":{"line":571,"column":6},"end":{"line":575,"column":null}},"279":{"start":{"line":577,"column":10},"end":{"line":577,"column":null}},"280":{"start":{"line":578,"column":4},"end":{"line":586,"column":null}},"281":{"start":{"line":579,"column":6},"end":{"line":585,"column":null}},"282":{"start":{"line":589,"column":2},"end":{"line":589,"column":16}},"283":{"start":{"line":589,"column":2},"end":{"line":589,"column":8}},"284":{"start":{"line":589,"column":17},"end":{"line":589,"column":57}},"285":{"start":{"line":589,"column":2},"end":{"line":589,"column":58}},"286":{"start":{"line":591,"column":2},"end":{"line":593,"column":null}},"287":{"start":{"line":592,"column":4},"end":{"line":592,"column":null}},"288":{"start":{"line":594,"column":2},"end":{"line":594,"column":null}},"289":{"start":{"line":527,"column":0},"end":{"line":527,"column":22}},"290":{"start":{"line":600,"column":21},"end":{"line":606,"column":null}},"291":{"start":{"line":600,"column":12},"end":{"line":600,"column":21}},"292":{"start":{"line":607,"column":4},"end":{"line":607,"column":null}},"293":{"start":{"line":609,"column":4},"end":{"line":613,"column":null}},"294":{"start":{"line":614,"column":4},"end":{"line":614,"column":null}},"295":{"start":{"line":617,"column":8},"end":{"line":617,"column":null}},"296":{"start":{"line":617,"column":37},"end":{"line":617,"column":58}},"297":{"start":{"line":618,"column":2},"end":{"line":620,"column":null}},"298":{"start":{"line":619,"column":4},"end":{"line":619,"column":null}},"299":{"start":{"line":622,"column":8},"end":{"line":625,"column":null}},"300":{"start":{"line":623,"column":14},"end":{"line":623,"column":64}},"301":{"start":{"line":624,"column":4},"end":{"line":624,"column":null}},"302":{"start":{"line":626,"column":2},"end":{"line":626,"column":null}},"303":{"start":{"line":626,"column":26},"end":{"line":626,"column":54}},"304":{"start":{"line":628,"column":8},"end":{"line":628,"column":null}},"305":{"start":{"line":629,"column":8},"end":{"line":634,"column":null}},"306":{"start":{"line":630,"column":18},"end":{"line":630,"column":64}},"307":{"start":{"line":631,"column":4},"end":{"line":633,"column":null}},"308":{"start":{"line":635,"column":2},"end":{"line":639,"column":null}},"309":{"start":{"line":636,"column":4},"end":{"line":638,"column":null}},"310":{"start":{"line":640,"column":2},"end":{"line":640,"column":null}},"311":{"start":{"line":647,"column":2},"end":{"line":647,"column":null}},"312":{"start":{"line":649,"column":8},"end":{"line":649,"column":null}},"313":{"start":{"line":650,"column":6},"end":{"line":650,"column":null}},"314":{"start":{"line":651,"column":9},"end":{"line":651,"column":null}},"315":{"start":{"line":651,"column":13},"end":{"line":651,"column":null}},"316":{"start":{"line":652,"column":16},"end":{"line":652,"column":null}},"317":{"start":{"line":652,"column":10},"end":{"line":652,"column":null}},"318":{"start":{"line":653,"column":4},"end":{"line":653,"column":null}},"319":{"start":{"line":654,"column":4},"end":{"line":656,"column":null}},"320":{"start":{"line":655,"column":6},"end":{"line":655,"column":12}},"321":{"start":{"line":658,"column":8},"end":{"line":658,"column":9}},"322":{"start":{"line":659,"column":22},"end":{"line":659,"column":null}},"323":{"start":{"line":659,"column":12},"end":{"line":659,"column":null}},"324":{"start":{"line":660,"column":6},"end":{"line":662,"column":null}},"325":{"start":{"line":665,"column":10},"end":{"line":665,"column":null}},"326":{"start":{"line":666,"column":8},"end":{"line":666,"column":23}},"327":{"start":{"line":667,"column":22},"end":{"line":667,"column":null}},"328":{"start":{"line":667,"column":12},"end":{"line":667,"column":null}},"329":{"start":{"line":668,"column":6},"end":{"line":672,"column":null}},"330":{"start":{"line":675,"column":10},"end":{"line":675,"column":null}},"331":{"start":{"line":676,"column":8},"end":{"line":676,"column":23}},"332":{"start":{"line":677,"column":22},"end":{"line":677,"column":null}},"333":{"start":{"line":677,"column":12},"end":{"line":677,"column":null}},"334":{"start":{"line":678,"column":6},"end":{"line":682,"column":null}},"335":{"start":{"line":686,"column":6},"end":{"line":686,"column":null}},"336":{"start":{"line":688,"column":22},"end":{"line":688,"column":null}},"337":{"start":{"line":688,"column":12},"end":{"line":688,"column":null}},"338":{"start":{"line":689,"column":6},"end":{"line":691,"column":null}},"339":{"start":{"line":643,"column":0},"end":{"line":643,"column":22}},"340":{"start":{"line":698,"column":4},"end":{"line":698,"column":61}},"341":{"start":{"line":700,"column":2},"end":{"line":702,"column":null}},"342":{"start":{"line":701,"column":4},"end":{"line":701,"column":null}},"343":{"start":{"line":704,"column":25},"end":{"line":704,"column":56}},"344":{"start":{"line":705,"column":2},"end":{"line":710,"column":null}},"345":{"start":{"line":706,"column":4},"end":{"line":708,"column":null}},"346":{"start":{"line":709,"column":4},"end":{"line":709,"column":null}},"347":{"start":{"line":712,"column":2},"end":{"line":712,"column":null}},"348":{"start":{"line":696,"column":0},"end":{"line":696,"column":16}},"349":{"start":{"line":716,"column":19},"end":{"line":716,"column":null}},"350":{"start":{"line":716,"column":10},"end":{"line":716,"column":19}},"351":{"start":{"line":717,"column":2},"end":{"line":717,"column":null}},"352":{"start":{"line":720,"column":23},"end":{"line":726,"column":2}},"353":{"start":{"line":729,"column":2},"end":{"line":731,"column":null}},"354":{"start":{"line":730,"column":4},"end":{"line":730,"column":null}},"355":{"start":{"line":732,"column":2},"end":{"line":732,"column":null}},"356":{"start":{"line":728,"column":0},"end":{"line":728,"column":16}},"357":{"start":{"line":736,"column":19},"end":{"line":736,"column":null}},"358":{"start":{"line":736,"column":10},"end":{"line":736,"column":19}},"359":{"start":{"line":737,"column":8},"end":{"line":737,"column":null}},"360":{"start":{"line":738,"column":2},"end":{"line":740,"column":null}},"361":{"start":{"line":739,"column":4},"end":{"line":739,"column":null}},"362":{"start":{"line":741,"column":2},"end":{"line":741,"column":null}},"363":{"start":{"line":748,"column":8},"end":{"line":748,"column":null}},"364":{"start":{"line":749,"column":8},"end":{"line":749,"column":null}},"365":{"start":{"line":750,"column":2},"end":{"line":753,"column":null}},"366":{"start":{"line":752,"column":4},"end":{"line":752,"column":null}},"367":{"start":{"line":755,"column":2},"end":{"line":757,"column":null}},"368":{"start":{"line":756,"column":4},"end":{"line":756,"column":null}},"369":{"start":{"line":759,"column":12},"end":{"line":763,"column":null}},"370":{"start":{"line":759,"column":8},"end":{"line":763,"column":null}},"371":{"start":{"line":764,"column":2},"end":{"line":764,"column":null}},"372":{"start":{"line":764,"column":31},"end":{"line":764,"column":66}},"373":{"start":{"line":764,"column":51},"end":{"line":764,"column":65}},"374":{"start":{"line":744,"column":0},"end":{"line":744,"column":22}},"375":{"start":{"line":768,"column":18},"end":{"line":775,"column":null}},"376":{"start":{"line":768,"column":8},"end":{"line":775,"column":null}},"377":{"start":{"line":776,"column":2},"end":{"line":778,"column":null}},"378":{"start":{"line":777,"column":4},"end":{"line":777,"column":10}},"379":{"start":{"line":780,"column":2},"end":{"line":784,"column":null}},"380":{"start":{"line":782,"column":13},"end":{"line":782,"column":null}},"381":{"start":{"line":767,"column":0},"end":{"line":767,"column":22}},"382":{"start":{"line":790,"column":19},"end":{"line":790,"column":null}},"383":{"start":{"line":790,"column":10},"end":{"line":790,"column":19}},"384":{"start":{"line":791,"column":2},"end":{"line":791,"column":null}},"385":{"start":{"line":787,"column":0},"end":{"line":787,"column":22}},"386":{"start":{"line":795,"column":8},"end":{"line":795,"column":null}},"387":{"start":{"line":796,"column":8},"end":{"line":799,"column":null}},"388":{"start":{"line":800,"column":2},"end":{"line":811,"column":null}},"389":{"start":{"line":800,"column":13},"end":{"line":800,"column":25}},"390":{"start":{"line":801,"column":4},"end":{"line":810,"column":null}},"391":{"start":{"line":801,"column":15},"end":{"line":801,"column":23}},"392":{"start":{"line":802,"column":6},"end":{"line":802,"column":null}},"393":{"start":{"line":803,"column":6},"end":{"line":803,"column":null}},"394":{"start":{"line":804,"column":6},"end":{"line":804,"column":null}},"395":{"start":{"line":805,"column":6},"end":{"line":805,"column":null}},"396":{"start":{"line":806,"column":6},"end":{"line":806,"column":null}},"397":{"start":{"line":807,"column":6},"end":{"line":807,"column":null}},"398":{"start":{"line":808,"column":6},"end":{"line":808,"column":null}},"399":{"start":{"line":809,"column":6},"end":{"line":809,"column":null}},"400":{"start":{"line":812,"column":20},"end":{"line":812,"column":null}},"401":{"start":{"line":812,"column":8},"end":{"line":812,"column":null}},"402":{"start":{"line":813,"column":2},"end":{"line":813,"column":null}},"403":{"start":{"line":813,"column":33},"end":{"line":813,"column":59}},"404":{"start":{"line":794,"column":0},"end":{"line":794,"column":22}},"405":{"start":{"line":820,"column":6},"end":{"line":820,"column":null}},"406":{"start":{"line":822,"column":4},"end":{"line":830,"column":null}},"407":{"start":{"line":832,"column":4},"end":{"line":832,"column":null}},"408":{"start":{"line":835,"column":2},"end":{"line":835,"column":null}},"409":{"start":{"line":816,"column":0},"end":{"line":816,"column":22}},"410":{"start":{"line":839,"column":15},"end":{"line":839,"column":null}},"411":{"start":{"line":839,"column":8},"end":{"line":839,"column":null}},"412":{"start":{"line":841,"column":8},"end":{"line":841,"column":null}},"413":{"start":{"line":842,"column":2},"end":{"line":844,"column":null}},"414":{"start":{"line":843,"column":4},"end":{"line":843,"column":null}},"415":{"start":{"line":845,"column":2},"end":{"line":845,"column":null}},"416":{"start":{"line":849,"column":8},"end":{"line":849,"column":null}},"417":{"start":{"line":850,"column":2},"end":{"line":850,"column":null}},"418":{"start":{"line":851,"column":2},"end":{"line":852,"column":null}},"419":{"start":{"line":853,"column":2},"end":{"line":864,"column":null}},"420":{"start":{"line":865,"column":2},"end":{"line":865,"column":null}},"421":{"start":{"line":871,"column":8},"end":{"line":871,"column":null}},"422":{"start":{"line":872,"column":2},"end":{"line":872,"column":null}},"423":{"start":{"line":875,"column":8},"end":{"line":875,"column":null}},"424":{"start":{"line":876,"column":2},"end":{"line":876,"column":27}},"425":{"start":{"line":879,"column":2},"end":{"line":879,"column":null}},"426":{"start":{"line":880,"column":2},"end":{"line":886,"column":null}},"427":{"start":{"line":889,"column":2},"end":{"line":891,"column":null}},"428":{"start":{"line":893,"column":2},"end":{"line":893,"column":null}},"429":{"start":{"line":897,"column":2},"end":{"line":899,"column":null}},"430":{"start":{"line":898,"column":4},"end":{"line":898,"column":null}},"431":{"start":{"line":901,"column":18},"end":{"line":901,"column":61}},"432":{"start":{"line":901,"column":47},"end":{"line":901,"column":61}},"433":{"start":{"line":902,"column":2},"end":{"line":906,"column":null}},"434":{"start":{"line":903,"column":4},"end":{"line":905,"column":null}},"435":{"start":{"line":907,"column":2},"end":{"line":907,"column":null}},"436":{"start":{"line":896,"column":0},"end":{"line":896,"column":16}},"437":{"start":{"line":910,"column":0},"end":{"line":910,"column":null}},"438":{"start":{"line":913,"column":22},"end":{"line":913,"column":48}},"439":{"start":{"line":911,"column":10},"end":{"line":911,"column":null}},"440":{"start":{"line":912,"column":2},"end":{"line":912,"column":null}},"441":{"start":{"line":914,"column":4},"end":{"line":916,"column":null}},"442":{"start":{"line":915,"column":6},"end":{"line":915,"column":null}},"443":{"start":{"line":919,"column":8},"end":{"line":933,"column":null}},"444":{"start":{"line":920,"column":4},"end":{"line":922,"column":null}},"445":{"start":{"line":921,"column":6},"end":{"line":921,"column":null}},"446":{"start":{"line":923,"column":4},"end":{"line":923,"column":null}},"447":{"start":{"line":924,"column":4},"end":{"line":926,"column":null}},"448":{"start":{"line":925,"column":6},"end":{"line":925,"column":null}},"449":{"start":{"line":927,"column":4},"end":{"line":929,"column":null}},"450":{"start":{"line":928,"column":6},"end":{"line":928,"column":null}},"451":{"start":{"line":930,"column":4},"end":{"line":932,"column":null}},"452":{"start":{"line":931,"column":6},"end":{"line":931,"column":null}},"453":{"start":{"line":934,"column":0},"end":{"line":934,"column":null}},"454":{"start":{"line":939,"column":39},"end":{"line":939,"column":41}},"455":{"start":{"line":940,"column":2},"end":{"line":942,"column":null}},"456":{"start":{"line":941,"column":4},"end":{"line":941,"column":null}},"457":{"start":{"line":943,"column":2},"end":{"line":974,"column":null}},"458":{"start":{"line":943,"column":31},"end":{"line":943,"column":40}},"459":{"start":{"line":943,"column":31},"end":{"line":943,"column":53}},"460":{"start":{"line":943,"column":27},"end":{"line":943,"column":31}},"461":{"start":{"line":944,"column":27},"end":{"line":944,"column":52}},"462":{"start":{"line":945,"column":4},"end":{"line":947,"column":null}},"463":{"start":{"line":946,"column":6},"end":{"line":946,"column":null}},"464":{"start":{"line":949,"column":17},"end":{"line":949,"column":42}},"465":{"start":{"line":950,"column":4},"end":{"line":951,"column":null}},"466":{"start":{"line":953,"column":22},"end":{"line":953,"column":50}},"467":{"start":{"line":954,"column":4},"end":{"line":956,"column":null}},"468":{"start":{"line":955,"column":6},"end":{"line":955,"column":null}},"469":{"start":{"line":958,"column":22},"end":{"line":964,"column":5}},"470":{"start":{"line":959,"column":18},"end":{"line":959,"column":27}},"471":{"start":{"line":960,"column":6},"end":{"line":962,"column":null}},"472":{"start":{"line":961,"column":8},"end":{"line":961,"column":null}},"473":{"start":{"line":963,"column":6},"end":{"line":963,"column":null}},"474":{"start":{"line":966,"column":4},"end":{"line":971,"column":null}},"475":{"start":{"line":967,"column":6},"end":{"line":967,"column":null}},"476":{"start":{"line":969,"column":6},"end":{"line":969,"column":null}},"477":{"start":{"line":970,"column":6},"end":{"line":970,"column":null}},"478":{"start":{"line":973,"column":4},"end":{"line":973,"column":null}},"479":{"start":{"line":975,"column":2},"end":{"line":975,"column":null}},"480":{"start":{"line":936,"column":0},"end":{"line":936,"column":16}},"481":{"start":{"line":979,"column":19},"end":{"line":979,"column":null}},"482":{"start":{"line":979,"column":10},"end":{"line":979,"column":19}},"483":{"start":{"line":980,"column":2},"end":{"line":980,"column":null}},"484":{"start":{"line":978,"column":0},"end":{"line":978,"column":22}}},"fnMap":{"0":{"name":"createPod","decl":{"start":{"line":66,"column":22},"end":{"line":66,"column":31}},"loc":{"start":{"line":70,"column":35},"end":{"line":132,"column":null}}},"1":{"name":"createJob","decl":{"start":{"line":134,"column":22},"end":{"line":134,"column":31}},"loc":{"start":{"line":136,"column":35},"end":{"line":188,"column":null}}},"2":{"name":"getContainerJobPodName","decl":{"start":{"line":190,"column":22},"end":{"line":190,"column":44}},"loc":{"start":{"line":190,"column":60},"end":{"line":216,"column":null}}},"3":{"name":"deletePod","decl":{"start":{"line":218,"column":22},"end":{"line":218,"column":31}},"loc":{"start":{"line":218,"column":47},"end":{"line":226,"column":null}}},"4":{"name":"execPodStep","decl":{"start":{"line":228,"column":22},"end":{"line":228,"column":33}},"loc":{"start":{"line":232,"column":25},"end":{"line":267,"column":null}}},"5":{"name":"(anonymous_35)","decl":{"start":{"line":237,"column":20},"end":{"line":237,"column":30}},"loc":{"start":{"line":237,"column":45},"end":{"line":266,"column":3}}},"6":{"name":"(anonymous_36)","decl":{"start":{"line":248,"column":8},"end":{"line":248,"column":12}},"loc":{"start":{"line":248,"column":12},"end":{"line":261,"column":9}}},"7":{"name":"(anonymous_37)","decl":{"start":{"line":265,"column":13},"end":{"line":265,"column":14}},"loc":{"start":{"line":265,"column":14},"end":{"line":265,"column":24}}},"8":{"name":"waitForJobToComplete","decl":{"start":{"line":269,"column":22},"end":{"line":269,"column":42}},"loc":{"start":{"line":269,"column":58},"end":{"line":281,"column":null}}},"9":{"name":"createDockerSecret","decl":{"start":{"line":283,"column":22},"end":{"line":283,"column":40}},"loc":{"start":{"line":284,"column":20},"end":{"line":320,"column":null}}},"10":{"name":"createSecretForEnvs","decl":{"start":{"line":322,"column":22},"end":{"line":322,"column":41}},"loc":{"start":{"line":324,"column":1},"end":{"line":345,"column":null}}},"11":{"name":"deleteSecret","decl":{"start":{"line":347,"column":22},"end":{"line":347,"column":34}},"loc":{"start":{"line":347,"column":53},"end":{"line":349,"column":null}}},"12":{"name":"pruneSecrets","decl":{"start":{"line":351,"column":22},"end":{"line":351,"column":34}},"loc":{"start":{"line":351,"column":34},"end":{"line":369,"column":null}}},"13":{"name":"(anonymous_53)","decl":{"start":{"line":366,"column":6},"end":{"line":366,"column":12}},"loc":{"start":{"line":366,"column":12},"end":{"line":366,"column":null}}},"14":{"name":"getUnrecoverableWaitingReasons","decl":{"start":{"line":393,"column":16},"end":{"line":393,"column":46}},"loc":{"start":{"line":393,"column":46},"end":{"line":406,"column":1}}},"15":{"name":"getUnrecoverableEventReasons","decl":{"start":{"line":408,"column":16},"end":{"line":408,"column":44}},"loc":{"start":{"line":408,"column":44},"end":{"line":421,"column":1}}},"16":{"name":"getUnrecoverableTerminatedReasons","decl":{"start":{"line":423,"column":16},"end":{"line":423,"column":49}},"loc":{"start":{"line":423,"column":49},"end":{"line":437,"column":1}}},"17":{"name":"getContainerErrors","decl":{"start":{"line":439,"column":16},"end":{"line":439,"column":34}},"loc":{"start":{"line":439,"column":49},"end":{"line":457,"column":1}}},"18":{"name":"getPodEventErrors","decl":{"start":{"line":459,"column":22},"end":{"line":459,"column":39}},"loc":{"start":{"line":459,"column":55},"end":{"line":491,"column":null}}},"19":{"name":"getPodConditionErrors","decl":{"start":{"line":493,"column":16},"end":{"line":493,"column":37}},"loc":{"start":{"line":493,"column":52},"end":{"line":505,"column":1}}},"20":{"name":"getContainerTerminatedErrors","decl":{"start":{"line":507,"column":16},"end":{"line":507,"column":44}},"loc":{"start":{"line":507,"column":59},"end":{"line":525,"column":1}}},"21":{"name":"describePodFailure","decl":{"start":{"line":527,"column":22},"end":{"line":527,"column":40}},"loc":{"start":{"line":527,"column":56},"end":{"line":595,"column":null}}},"22":{"name":"describePodWarningEvents","decl":{"start":{"line":597,"column":15},"end":{"line":597,"column":39}},"loc":{"start":{"line":597,"column":55},"end":{"line":641,"column":null}}},"23":{"name":"(anonymous_69)","decl":{"start":{"line":617,"column":32},"end":{"line":617,"column":33}},"loc":{"start":{"line":617,"column":33},"end":{"line":617,"column":38}}},"24":{"name":"(anonymous_70)","decl":{"start":{"line":622,"column":20},"end":{"line":622,"column":21}},"loc":{"start":{"line":622,"column":39},"end":{"line":625,"column":3}}},"25":{"name":"(anonymous_71)","decl":{"start":{"line":626,"column":16},"end":{"line":626,"column":17}},"loc":{"start":{"line":626,"column":21},"end":{"line":626,"column":35}}},"26":{"name":"(anonymous_72)","decl":{"start":{"line":629,"column":27},"end":{"line":629,"column":28}},"loc":{"start":{"line":629,"column":28},"end":{"line":634,"column":3}}},"27":{"name":"waitForPodPhases","decl":{"start":{"line":643,"column":22},"end":{"line":643,"column":38}},"loc":{"start":{"line":647,"column":52},"end":{"line":694,"column":null}}},"28":{"name":"getPrepareJobTimeoutSeconds","decl":{"start":{"line":696,"column":16},"end":{"line":696,"column":43}},"loc":{"start":{"line":696,"column":43},"end":{"line":713,"column":1}}},"29":{"name":"readPod","decl":{"start":{"line":715,"column":15},"end":{"line":715,"column":22}},"loc":{"start":{"line":715,"column":38},"end":{"line":718,"column":null}}},"30":{"name":"parsePodPhase","decl":{"start":{"line":728,"column":16},"end":{"line":728,"column":29}},"loc":{"start":{"line":728,"column":44},"end":{"line":733,"column":1}}},"31":{"name":"isJobSucceeded","decl":{"start":{"line":735,"column":15},"end":{"line":735,"column":29}},"loc":{"start":{"line":735,"column":45},"end":{"line":742,"column":null}}},"32":{"name":"getPodLogs","decl":{"start":{"line":744,"column":22},"end":{"line":744,"column":32}},"loc":{"start":{"line":746,"column":23},"end":{"line":765,"column":null}}},"33":{"name":"(anonymous_87)","decl":{"start":{"line":750,"column":23},"end":{"line":750,"column":28}},"loc":{"start":{"line":750,"column":28},"end":{"line":753,"column":3}}},"34":{"name":"(anonymous_88)","decl":{"start":{"line":755,"column":24},"end":{"line":755,"column":27}},"loc":{"start":{"line":755,"column":27},"end":{"line":757,"column":3}}},"35":{"name":"(anonymous_89)","decl":{"start":{"line":764,"column":20},"end":{"line":764,"column":27}},"loc":{"start":{"line":764,"column":27},"end":{"line":764,"column":32}}},"36":{"name":"(anonymous_90)","decl":{"start":{"line":764,"column":45},"end":{"line":764,"column":51}},"loc":{"start":{"line":764,"column":45},"end":{"line":764,"column":58}}},"37":{"name":"prunePods","decl":{"start":{"line":767,"column":22},"end":{"line":767,"column":31}},"loc":{"start":{"line":767,"column":31},"end":{"line":785,"column":null}}},"38":{"name":"(anonymous_94)","decl":{"start":{"line":782,"column":6},"end":{"line":782,"column":9}},"loc":{"start":{"line":782,"column":9},"end":{"line":782,"column":null}}},"39":{"name":"getPodStatus","decl":{"start":{"line":787,"column":22},"end":{"line":787,"column":34}},"loc":{"start":{"line":788,"column":14},"end":{"line":792,"column":null}}},"40":{"name":"isAuthPermissionsOK","decl":{"start":{"line":794,"column":22},"end":{"line":794,"column":41}},"loc":{"start":{"line":794,"column":41},"end":{"line":814,"column":null}}},"41":{"name":"(anonymous_101)","decl":{"start":{"line":813,"column":25},"end":{"line":813,"column":29}},"loc":{"start":{"line":813,"column":29},"end":{"line":813,"column":59}}},"42":{"name":"isPodContainerAlpine","decl":{"start":{"line":816,"column":22},"end":{"line":816,"column":42}},"loc":{"start":{"line":818,"column":23},"end":{"line":836,"column":null}}},"43":{"name":"getCurrentNodeName","decl":{"start":{"line":838,"column":15},"end":{"line":838,"column":33}},"loc":{"start":{"line":838,"column":33},"end":{"line":846,"column":null}}},"44":{"name":"getPodAffinity","decl":{"start":{"line":848,"column":15},"end":{"line":848,"column":29}},"loc":{"start":{"line":848,"column":46},"end":{"line":866,"column":null}}},"45":{"name":"getPreferredPodAffinity","decl":{"start":{"line":868,"column":15},"end":{"line":868,"column":38}},"loc":{"start":{"line":869,"column":18},"end":{"line":894,"column":null}}},"46":{"name":"namespace","decl":{"start":{"line":896,"column":16},"end":{"line":896,"column":25}},"loc":{"start":{"line":896,"column":25},"end":{"line":908,"column":1}}},"47":{"name":"(anonymous_115)","decl":{"start":{"line":901,"column":40},"end":{"line":901,"column":43}},"loc":{"start":{"line":901,"column":43},"end":{"line":901,"column":50}}},"48":{"name":"(anonymous_116)","decl":{"start":{"line":910,"column":0},"end":{"line":910,"column":null}},"loc":{"start":{"line":910,"column":0},"end":{"line":934,"column":null}}},"49":{"name":"BackOffManager","decl":{"start":{"line":913,"column":2},"end":{"line":913,"column":22}},"loc":{"start":{"line":913,"column":48},"end":{"line":917,"column":3}}},"50":{"name":"(anonymous_118)","decl":{"start":{"line":919,"column":2},"end":{"line":919,"column":8}},"loc":{"start":{"line":919,"column":2},"end":{"line":933,"column":null}}},"51":{"name":"(anonymous_121)","decl":{"start":{"line":920,"column":22},"end":{"line":920,"column":29}},"loc":{"start":{"line":920,"column":29},"end":{"line":921,"column":16}}},"52":{"name":"containerPorts","decl":{"start":{"line":936,"column":16},"end":{"line":936,"column":30}},"loc":{"start":{"line":937,"column":26},"end":{"line":976,"column":1}}},"53":{"name":"(anonymous_123)","decl":{"start":{"line":958,"column":22},"end":{"line":958,"column":23}},"loc":{"start":{"line":958,"column":32},"end":{"line":964,"column":5}}},"54":{"name":"getPodByName","decl":{"start":{"line":978,"column":22},"end":{"line":978,"column":34}},"loc":{"start":{"line":978,"column":39},"end":{"line":981,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":73,"column":2},"end":{"line":75,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":2},"end":{"line":75,"column":null}}]},"1":{"loc":{"start":{"line":76,"column":2},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":2},"end":{"line":78,"column":null}}]},"2":{"loc":{"start":{"line":76,"column":6},"end":{"line":76,"column":22}},"type":"cond-expr","locations":[{"start":{"line":76,"column":14},"end":{"line":76,"column":16}},{"start":{"line":76,"column":6},"end":{"line":76,"column":22}}]},"3":{"loc":{"start":{"line":76,"column":6},"end":{"line":76,"column":16}},"type":"binary-expr","locations":[{"start":{"line":76,"column":6},"end":{"line":76,"column":16}},{"start":{"line":76,"column":6},"end":{"line":76,"column":16}}]},"4":{"loc":{"start":{"line":99,"column":6},"end":{"line":99,"column":22}},"type":"if","locations":[{"start":{"line":99,"column":6},"end":{"line":99,"column":22}}]},"5":{"loc":{"start":{"line":112,"column":6},"end":{"line":112,"column":14}},"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":112,"column":14}}]},"6":{"loc":{"start":{"line":114,"column":4},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":114,"column":4},"end":{"line":116,"column":null}}]},"7":{"loc":{"start":{"line":114,"column":9},"end":{"line":114,"column":31}},"type":"cond-expr","locations":[{"start":{"line":114,"column":25},"end":{"line":114,"column":27}},{"start":{"line":114,"column":25},"end":{"line":114,"column":31}}]},"8":{"loc":{"start":{"line":114,"column":9},"end":{"line":114,"column":27}},"type":"binary-expr","locations":[{"start":{"line":114,"column":9},"end":{"line":114,"column":27}},{"start":{"line":114,"column":25},"end":{"line":114,"column":27}}]},"9":{"loc":{"start":{"line":114,"column":9},"end":{"line":114,"column":25}},"type":"cond-expr","locations":[{"start":{"line":114,"column":15},"end":{"line":114,"column":17}},{"start":{"line":114,"column":9},"end":{"line":114,"column":25}}]},"10":{"loc":{"start":{"line":114,"column":9},"end":{"line":114,"column":17}},"type":"binary-expr","locations":[{"start":{"line":114,"column":9},"end":{"line":114,"column":17}},{"start":{"line":114,"column":9},"end":{"line":114,"column":17}}]},"11":{"loc":{"start":{"line":122,"column":2},"end":{"line":124,"column":null}},"type":"if","locations":[{"start":{"line":122,"column":2},"end":{"line":124,"column":null}}]},"12":{"loc":{"start":{"line":122,"column":6},"end":{"line":122,"column":25}},"type":"cond-expr","locations":[{"start":{"line":122,"column":15},"end":{"line":122,"column":17}},{"start":{"line":122,"column":6},"end":{"line":122,"column":25}}]},"13":{"loc":{"start":{"line":122,"column":6},"end":{"line":122,"column":17}},"type":"binary-expr","locations":[{"start":{"line":122,"column":6},"end":{"line":122,"column":17}},{"start":{"line":122,"column":6},"end":{"line":122,"column":17}}]},"14":{"loc":{"start":{"line":126,"column":2},"end":{"line":128,"column":null}},"type":"if","locations":[{"start":{"line":126,"column":2},"end":{"line":128,"column":null}}]},"15":{"loc":{"start":{"line":126,"column":6},"end":{"line":126,"column":21}},"type":"cond-expr","locations":[{"start":{"line":126,"column":15},"end":{"line":126,"column":17}},{"start":{"line":126,"column":6},"end":{"line":126,"column":21}}]},"16":{"loc":{"start":{"line":126,"column":6},"end":{"line":126,"column":17}},"type":"binary-expr","locations":[{"start":{"line":126,"column":6},"end":{"line":126,"column":17}},{"start":{"line":126,"column":6},"end":{"line":126,"column":17}}]},"17":{"loc":{"start":{"line":161,"column":6},"end":{"line":161,"column":22}},"type":"if","locations":[{"start":{"line":161,"column":6},"end":{"line":161,"column":22}}]},"18":{"loc":{"start":{"line":175,"column":2},"end":{"line":184,"column":null}},"type":"if","locations":[{"start":{"line":175,"column":2},"end":{"line":184,"column":null}}]},"19":{"loc":{"start":{"line":176,"column":4},"end":{"line":180,"column":null}},"type":"if","locations":[{"start":{"line":176,"column":4},"end":{"line":180,"column":null}}]},"20":{"loc":{"start":{"line":181,"column":4},"end":{"line":183,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":183,"column":null}}]},"21":{"loc":{"start":{"line":193,"column":9},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":193,"column":9},"end":{"line":193,"column":null}}]},"22":{"loc":{"start":{"line":204,"column":8},"end":{"line":204,"column":9}},"type":"if","locations":[{"start":{"line":204,"column":8},"end":{"line":204,"column":9}}]},"23":{"loc":{"start":{"line":204,"column":9},"end":{"line":204,"column":35}},"type":"cond-expr","locations":[{"start":{"line":204,"column":27},"end":{"line":204,"column":29}},{"start":{"line":204,"column":27},"end":{"line":204,"column":35}}]},"24":{"loc":{"start":{"line":204,"column":9},"end":{"line":204,"column":29}},"type":"binary-expr","locations":[{"start":{"line":204,"column":9},"end":{"line":204,"column":29}},{"start":{"line":204,"column":27},"end":{"line":204,"column":29}}]},"25":{"loc":{"start":{"line":209,"column":4},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":4},"end":{"line":213,"column":null}}]},"26":{"loc":{"start":{"line":209,"column":9},"end":{"line":209,"column":45}},"type":"cond-expr","locations":[{"start":{"line":209,"column":39},"end":{"line":209,"column":41}},{"start":{"line":209,"column":39},"end":{"line":209,"column":45}}]},"27":{"loc":{"start":{"line":209,"column":9},"end":{"line":209,"column":41}},"type":"binary-expr","locations":[{"start":{"line":209,"column":9},"end":{"line":209,"column":41}},{"start":{"line":209,"column":39},"end":{"line":209,"column":41}}]},"28":{"loc":{"start":{"line":219,"column":2},"end":{"line":225,"column":null}},"type":"switch","locations":[{"start":{"line":219,"column":2},"end":{"line":225,"column":null}}]},"29":{"loc":{"start":{"line":246,"column":8},"end":{"line":246,"column":21}},"type":"cond-expr","locations":[{"start":{"line":246,"column":8},"end":{"line":246,"column":13}},{"start":{"line":246,"column":17},"end":{"line":246,"column":21}}]},"30":{"loc":{"start":{"line":246,"column":8},"end":{"line":246,"column":17}},"type":"binary-expr","locations":[{"start":{"line":246,"column":8},"end":{"line":246,"column":17}},{"start":{"line":246,"column":8},"end":{"line":246,"column":17}}]},"31":{"loc":{"start":{"line":250,"column":10},"end":{"line":260,"column":null}},"type":"if","locations":[{"start":{"line":250,"column":10},"end":{"line":260,"column":null}},{"start":{"line":252,"column":17},"end":{"line":260,"column":null}}]},"32":{"loc":{"start":{"line":255,"column":25},"end":{"line":255,"column":38}},"type":"cond-expr","locations":[{"start":{"line":255,"column":29},"end":{"line":255,"column":31}},{"start":{"line":255,"column":25},"end":{"line":255,"column":38}}]},"33":{"loc":{"start":{"line":255,"column":25},"end":{"line":255,"column":31}},"type":"binary-expr","locations":[{"start":{"line":255,"column":25},"end":{"line":255,"column":31}},{"start":{"line":255,"column":25},"end":{"line":255,"column":31}}]},"34":{"loc":{"start":{"line":256,"column":25},"end":{"line":256,"column":38}},"type":"cond-expr","locations":[{"start":{"line":256,"column":29},"end":{"line":256,"column":31}},{"start":{"line":256,"column":25},"end":{"line":256,"column":38}}]},"35":{"loc":{"start":{"line":256,"column":25},"end":{"line":256,"column":31}},"type":"binary-expr","locations":[{"start":{"line":256,"column":25},"end":{"line":256,"column":31}},{"start":{"line":256,"column":25},"end":{"line":256,"column":31}}]},"36":{"loc":{"start":{"line":259,"column":19},"end":{"line":259,"column":32}},"type":"cond-expr","locations":[{"start":{"line":259,"column":23},"end":{"line":259,"column":25}},{"start":{"line":259,"column":19},"end":{"line":259,"column":32}}]},"37":{"loc":{"start":{"line":259,"column":19},"end":{"line":259,"column":25}},"type":"binary-expr","locations":[{"start":{"line":259,"column":19},"end":{"line":259,"column":25}},{"start":{"line":259,"column":19},"end":{"line":259,"column":25}}]},"38":{"loc":{"start":{"line":279,"column":4},"end":{"line":279,"column":null}},"type":"switch","locations":[{"start":{"line":279,"column":4},"end":{"line":279,"column":null}}]},"39":{"loc":{"start":{"line":271,"column":9},"end":{"line":271,"column":null}},"type":"if","locations":[{"start":{"line":271,"column":9},"end":{"line":271,"column":null}}]},"40":{"loc":{"start":{"line":273,"column":6},"end":{"line":275,"column":null}},"type":"if","locations":[{"start":{"line":273,"column":6},"end":{"line":275,"column":null}}]},"41":{"loc":{"start":{"line":288,"column":7},"end":{"line":288,"column":58}},"type":"binary-expr","locations":[{"start":{"line":288,"column":7},"end":{"line":288,"column":25}},{"start":{"line":288,"column":29},"end":{"line":288,"column":58}}]},"42":{"loc":{"start":{"line":348,"column":2},"end":{"line":348,"column":null}},"type":"switch","locations":[{"start":{"line":348,"column":2},"end":{"line":348,"column":null}}]},"43":{"loc":{"start":{"line":352,"column":21},"end":{"line":359,"column":null}},"type":"switch","locations":[{"start":{"line":352,"column":21},"end":{"line":359,"column":null}}]},"44":{"loc":{"start":{"line":360,"column":2},"end":{"line":362,"column":null}},"type":"if","locations":[{"start":{"line":360,"column":2},"end":{"line":362,"column":null}}]},"45":{"loc":{"start":{"line":366,"column":16},"end":{"line":366,"column":75}},"type":"binary-expr","locations":[{"start":{"line":366,"column":16},"end":{"line":366,"column":37}},{"start":{"line":366,"column":41},"end":{"line":366,"column":75}}]},"46":{"loc":{"start":{"line":366,"column":16},"end":{"line":366,"column":37}},"type":"cond-expr","locations":[{"start":{"line":366,"column":31},"end":{"line":366,"column":33}},{"start":{"line":366,"column":31},"end":{"line":366,"column":37}}]},"47":{"loc":{"start":{"line":366,"column":16},"end":{"line":366,"column":33}},"type":"binary-expr","locations":[{"start":{"line":366,"column":16},"end":{"line":366,"column":33}},{"start":{"line":366,"column":31},"end":{"line":366,"column":33}}]},"48":{"loc":{"start":{"line":395,"column":2},"end":{"line":397,"column":null}},"type":"if","locations":[{"start":{"line":395,"column":2},"end":{"line":397,"column":null}}]},"49":{"loc":{"start":{"line":401,"column":4},"end":{"line":403,"column":null}},"type":"if","locations":[{"start":{"line":401,"column":4},"end":{"line":403,"column":null}}]},"50":{"loc":{"start":{"line":410,"column":2},"end":{"line":412,"column":null}},"type":"if","locations":[{"start":{"line":410,"column":2},"end":{"line":412,"column":null}}]},"51":{"loc":{"start":{"line":416,"column":4},"end":{"line":418,"column":null}},"type":"if","locations":[{"start":{"line":416,"column":4},"end":{"line":418,"column":null}}]},"52":{"loc":{"start":{"line":426,"column":2},"end":{"line":428,"column":null}},"type":"if","locations":[{"start":{"line":426,"column":2},"end":{"line":428,"column":null}}]},"53":{"loc":{"start":{"line":432,"column":4},"end":{"line":434,"column":null}},"type":"if","locations":[{"start":{"line":432,"column":4},"end":{"line":434,"column":null}}]},"54":{"loc":{"start":{"line":443,"column":8},"end":{"line":443,"column":47}},"type":"cond-expr","locations":[{"start":{"line":443,"column":41},"end":{"line":443,"column":45}},{"start":{"line":443,"column":45},"end":{"line":443,"column":47}}]},"55":{"loc":{"start":{"line":443,"column":8},"end":{"line":443,"column":45}},"type":"binary-expr","locations":[{"start":{"line":443,"column":8},"end":{"line":443,"column":45}},{"start":{"line":443,"column":41},"end":{"line":443,"column":45}}]},"56":{"loc":{"start":{"line":443,"column":8},"end":{"line":443,"column":41}},"type":"cond-expr","locations":[{"start":{"line":443,"column":18},"end":{"line":443,"column":20}},{"start":{"line":443,"column":18},"end":{"line":443,"column":41}}]},"57":{"loc":{"start":{"line":443,"column":8},"end":{"line":443,"column":20}},"type":"binary-expr","locations":[{"start":{"line":443,"column":8},"end":{"line":443,"column":20}},{"start":{"line":443,"column":18},"end":{"line":443,"column":20}}]},"58":{"loc":{"start":{"line":444,"column":8},"end":{"line":444,"column":43}},"type":"cond-expr","locations":[{"start":{"line":444,"column":37},"end":{"line":444,"column":41}},{"start":{"line":444,"column":41},"end":{"line":444,"column":43}}]},"59":{"loc":{"start":{"line":444,"column":8},"end":{"line":444,"column":41}},"type":"binary-expr","locations":[{"start":{"line":444,"column":8},"end":{"line":444,"column":41}},{"start":{"line":444,"column":37},"end":{"line":444,"column":41}}]},"60":{"loc":{"start":{"line":444,"column":8},"end":{"line":444,"column":37}},"type":"cond-expr","locations":[{"start":{"line":444,"column":18},"end":{"line":444,"column":20}},{"start":{"line":444,"column":18},"end":{"line":444,"column":37}}]},"61":{"loc":{"start":{"line":444,"column":8},"end":{"line":444,"column":20}},"type":"binary-expr","locations":[{"start":{"line":444,"column":8},"end":{"line":444,"column":20}},{"start":{"line":444,"column":18},"end":{"line":444,"column":20}}]},"62":{"loc":{"start":{"line":447,"column":20},"end":{"line":447,"column":37}},"type":"cond-expr","locations":[{"start":{"line":447,"column":28},"end":{"line":447,"column":30}},{"start":{"line":447,"column":28},"end":{"line":447,"column":37}}]},"63":{"loc":{"start":{"line":447,"column":20},"end":{"line":447,"column":30}},"type":"binary-expr","locations":[{"start":{"line":447,"column":20},"end":{"line":447,"column":30}},{"start":{"line":447,"column":28},"end":{"line":447,"column":30}}]},"64":{"loc":{"start":{"line":448,"column":4},"end":{"line":454,"column":null}},"type":"if","locations":[{"start":{"line":448,"column":4},"end":{"line":454,"column":null}}]},"65":{"loc":{"start":{"line":448,"column":8},"end":{"line":448,"column":67}},"type":"binary-expr","locations":[{"start":{"line":448,"column":8},"end":{"line":448,"column":23}},{"start":{"line":448,"column":27},"end":{"line":448,"column":67}}]},"66":{"loc":{"start":{"line":448,"column":8},"end":{"line":448,"column":23}},"type":"cond-expr","locations":[{"start":{"line":448,"column":15},"end":{"line":448,"column":17}},{"start":{"line":448,"column":8},"end":{"line":448,"column":23}}]},"67":{"loc":{"start":{"line":448,"column":8},"end":{"line":448,"column":17}},"type":"binary-expr","locations":[{"start":{"line":448,"column":8},"end":{"line":448,"column":17}},{"start":{"line":448,"column":8},"end":{"line":448,"column":17}}]},"68":{"loc":{"start":{"line":451,"column":10},"end":{"line":451,"column":56}},"type":"cond-expr","locations":[{"start":{"line":451,"column":28},"end":{"line":451,"column":51}},{"start":{"line":451,"column":54},"end":{"line":451,"column":56}}]},"69":{"loc":{"start":{"line":474,"column":8},"end":{"line":474,"column":56}},"type":"cond-expr","locations":[{"start":{"line":474,"column":31},"end":{"line":474,"column":42}},{"start":{"line":474,"column":45},"end":{"line":474,"column":56}}]},"70":{"loc":{"start":{"line":482,"column":4},"end":{"line":488,"column":null}},"type":"if","locations":[{"start":{"line":482,"column":4},"end":{"line":488,"column":null}}]},"71":{"loc":{"start":{"line":483,"column":6},"end":{"line":485,"column":40}},"type":"binary-expr","locations":[{"start":{"line":483,"column":6},"end":{"line":483,"column":26}},{"start":{"line":484,"column":6},"end":{"line":484,"column":14}},{"start":{"line":485,"column":6},"end":{"line":485,"column":40}}]},"72":{"loc":{"start":{"line":487,"column":50},"end":{"line":487,"column":65}},"type":"cond-expr","locations":[{"start":{"line":487,"column":59},"end":{"line":487,"column":63}},{"start":{"line":487,"column":63},"end":{"line":487,"column":65}}]},"73":{"loc":{"start":{"line":487,"column":50},"end":{"line":487,"column":63}},"type":"binary-expr","locations":[{"start":{"line":487,"column":50},"end":{"line":487,"column":63}},{"start":{"line":487,"column":59},"end":{"line":487,"column":63}}]},"74":{"loc":{"start":{"line":495,"column":21},"end":{"line":495,"column":49}},"type":"cond-expr","locations":[{"start":{"line":495,"column":43},"end":{"line":495,"column":47}},{"start":{"line":495,"column":47},"end":{"line":495,"column":49}}]},"75":{"loc":{"start":{"line":495,"column":21},"end":{"line":495,"column":47}},"type":"binary-expr","locations":[{"start":{"line":495,"column":21},"end":{"line":495,"column":47}},{"start":{"line":495,"column":43},"end":{"line":495,"column":47}}]},"76":{"loc":{"start":{"line":495,"column":21},"end":{"line":495,"column":43}},"type":"cond-expr","locations":[{"start":{"line":495,"column":31},"end":{"line":495,"column":33}},{"start":{"line":495,"column":31},"end":{"line":495,"column":43}}]},"77":{"loc":{"start":{"line":495,"column":21},"end":{"line":495,"column":33}},"type":"binary-expr","locations":[{"start":{"line":495,"column":21},"end":{"line":495,"column":33}},{"start":{"line":495,"column":31},"end":{"line":495,"column":33}}]},"78":{"loc":{"start":{"line":496,"column":4},"end":{"line":502,"column":null}},"type":"if","locations":[{"start":{"line":496,"column":4},"end":{"line":502,"column":null}}]},"79":{"loc":{"start":{"line":496,"column":8},"end":{"line":496,"column":98}},"type":"binary-expr","locations":[{"start":{"line":496,"column":8},"end":{"line":496,"column":36}},{"start":{"line":496,"column":40},"end":{"line":496,"column":63}},{"start":{"line":496,"column":67},"end":{"line":496,"column":98}}]},"80":{"loc":{"start":{"line":498,"column":49},"end":{"line":498,"column":66}},"type":"cond-expr","locations":[{"start":{"line":498,"column":60},"end":{"line":498,"column":64}},{"start":{"line":498,"column":64},"end":{"line":498,"column":66}}]},"81":{"loc":{"start":{"line":498,"column":49},"end":{"line":498,"column":64}},"type":"binary-expr","locations":[{"start":{"line":498,"column":49},"end":{"line":498,"column":64}},{"start":{"line":498,"column":60},"end":{"line":498,"column":64}}]},"82":{"loc":{"start":{"line":499,"column":10},"end":{"line":499,"column":28}},"type":"cond-expr","locations":[{"start":{"line":499,"column":22},"end":{"line":499,"column":26}},{"start":{"line":499,"column":26},"end":{"line":499,"column":28}}]},"83":{"loc":{"start":{"line":499,"column":10},"end":{"line":499,"column":26}},"type":"binary-expr","locations":[{"start":{"line":499,"column":10},"end":{"line":499,"column":26}},{"start":{"line":499,"column":22},"end":{"line":499,"column":26}}]},"84":{"loc":{"start":{"line":511,"column":8},"end":{"line":511,"column":47}},"type":"cond-expr","locations":[{"start":{"line":511,"column":41},"end":{"line":511,"column":45}},{"start":{"line":511,"column":45},"end":{"line":511,"column":47}}]},"85":{"loc":{"start":{"line":511,"column":8},"end":{"line":511,"column":45}},"type":"binary-expr","locations":[{"start":{"line":511,"column":8},"end":{"line":511,"column":45}},{"start":{"line":511,"column":41},"end":{"line":511,"column":45}}]},"86":{"loc":{"start":{"line":511,"column":8},"end":{"line":511,"column":41}},"type":"cond-expr","locations":[{"start":{"line":511,"column":18},"end":{"line":511,"column":20}},{"start":{"line":511,"column":18},"end":{"line":511,"column":41}}]},"87":{"loc":{"start":{"line":511,"column":8},"end":{"line":511,"column":20}},"type":"binary-expr","locations":[{"start":{"line":511,"column":8},"end":{"line":511,"column":20}},{"start":{"line":511,"column":18},"end":{"line":511,"column":20}}]},"88":{"loc":{"start":{"line":512,"column":8},"end":{"line":512,"column":43}},"type":"cond-expr","locations":[{"start":{"line":512,"column":37},"end":{"line":512,"column":41}},{"start":{"line":512,"column":41},"end":{"line":512,"column":43}}]},"89":{"loc":{"start":{"line":512,"column":8},"end":{"line":512,"column":41}},"type":"binary-expr","locations":[{"start":{"line":512,"column":8},"end":{"line":512,"column":41}},{"start":{"line":512,"column":37},"end":{"line":512,"column":41}}]},"90":{"loc":{"start":{"line":512,"column":8},"end":{"line":512,"column":37}},"type":"cond-expr","locations":[{"start":{"line":512,"column":18},"end":{"line":512,"column":20}},{"start":{"line":512,"column":18},"end":{"line":512,"column":37}}]},"91":{"loc":{"start":{"line":512,"column":8},"end":{"line":512,"column":20}},"type":"binary-expr","locations":[{"start":{"line":512,"column":8},"end":{"line":512,"column":20}},{"start":{"line":512,"column":18},"end":{"line":512,"column":20}}]},"92":{"loc":{"start":{"line":515,"column":23},"end":{"line":515,"column":43}},"type":"cond-expr","locations":[{"start":{"line":515,"column":31},"end":{"line":515,"column":33}},{"start":{"line":515,"column":31},"end":{"line":515,"column":43}}]},"93":{"loc":{"start":{"line":515,"column":23},"end":{"line":515,"column":33}},"type":"binary-expr","locations":[{"start":{"line":515,"column":23},"end":{"line":515,"column":33}},{"start":{"line":515,"column":31},"end":{"line":515,"column":33}}]},"94":{"loc":{"start":{"line":516,"column":4},"end":{"line":522,"column":null}},"type":"if","locations":[{"start":{"line":516,"column":4},"end":{"line":522,"column":null}}]},"95":{"loc":{"start":{"line":516,"column":8},"end":{"line":516,"column":73}},"type":"binary-expr","locations":[{"start":{"line":516,"column":8},"end":{"line":516,"column":26}},{"start":{"line":516,"column":30},"end":{"line":516,"column":73}}]},"96":{"loc":{"start":{"line":516,"column":8},"end":{"line":516,"column":26}},"type":"cond-expr","locations":[{"start":{"line":516,"column":18},"end":{"line":516,"column":20}},{"start":{"line":516,"column":8},"end":{"line":516,"column":26}}]},"97":{"loc":{"start":{"line":516,"column":8},"end":{"line":516,"column":20}},"type":"binary-expr","locations":[{"start":{"line":516,"column":8},"end":{"line":516,"column":20}},{"start":{"line":516,"column":8},"end":{"line":516,"column":20}}]},"98":{"loc":{"start":{"line":519,"column":10},"end":{"line":519,"column":34}},"type":"cond-expr","locations":[{"start":{"line":519,"column":28},"end":{"line":519,"column":32}},{"start":{"line":519,"column":32},"end":{"line":519,"column":34}}]},"99":{"loc":{"start":{"line":519,"column":10},"end":{"line":519,"column":32}},"type":"binary-expr","locations":[{"start":{"line":519,"column":10},"end":{"line":519,"column":32}},{"start":{"line":519,"column":28},"end":{"line":519,"column":32}}]},"100":{"loc":{"start":{"line":533,"column":6},"end":{"line":533,"column":54}},"type":"cond-expr","locations":[{"start":{"line":533,"column":29},"end":{"line":533,"column":40}},{"start":{"line":533,"column":43},"end":{"line":533,"column":54}}]},"101":{"loc":{"start":{"line":540,"column":2},"end":{"line":546,"column":null}},"type":"if","locations":[{"start":{"line":540,"column":2},"end":{"line":546,"column":null}}]},"102":{"loc":{"start":{"line":540,"column":6},"end":{"line":540,"column":19}},"type":"cond-expr","locations":[{"start":{"line":540,"column":12},"end":{"line":540,"column":14}},{"start":{"line":540,"column":6},"end":{"line":540,"column":19}}]},"103":{"loc":{"start":{"line":540,"column":6},"end":{"line":540,"column":14}},"type":"binary-expr","locations":[{"start":{"line":540,"column":6},"end":{"line":540,"column":14}},{"start":{"line":540,"column":6},"end":{"line":540,"column":14}}]},"104":{"loc":{"start":{"line":543,"column":8},"end":{"line":543,"column":58}},"type":"cond-expr","locations":[{"start":{"line":543,"column":24},"end":{"line":543,"column":53}},{"start":{"line":543,"column":56},"end":{"line":543,"column":58}}]},"105":{"loc":{"start":{"line":547,"column":2},"end":{"line":549,"column":null}},"type":"if","locations":[{"start":{"line":547,"column":2},"end":{"line":549,"column":null}}]},"106":{"loc":{"start":{"line":547,"column":6},"end":{"line":547,"column":21}},"type":"cond-expr","locations":[{"start":{"line":547,"column":12},"end":{"line":547,"column":14}},{"start":{"line":547,"column":6},"end":{"line":547,"column":21}}]},"107":{"loc":{"start":{"line":547,"column":6},"end":{"line":547,"column":14}},"type":"binary-expr","locations":[{"start":{"line":547,"column":6},"end":{"line":547,"column":14}},{"start":{"line":547,"column":6},"end":{"line":547,"column":14}}]},"108":{"loc":{"start":{"line":554,"column":21},"end":{"line":554,"column":45}},"type":"cond-expr","locations":[{"start":{"line":554,"column":39},"end":{"line":554,"column":43}},{"start":{"line":554,"column":43},"end":{"line":554,"column":45}}]},"109":{"loc":{"start":{"line":554,"column":21},"end":{"line":554,"column":43}},"type":"binary-expr","locations":[{"start":{"line":554,"column":21},"end":{"line":554,"column":43}},{"start":{"line":554,"column":39},"end":{"line":554,"column":43}}]},"110":{"loc":{"start":{"line":554,"column":21},"end":{"line":554,"column":39}},"type":"cond-expr","locations":[{"start":{"line":554,"column":27},"end":{"line":554,"column":29}},{"start":{"line":554,"column":21},"end":{"line":554,"column":39}}]},"111":{"loc":{"start":{"line":554,"column":21},"end":{"line":554,"column":29}},"type":"binary-expr","locations":[{"start":{"line":554,"column":21},"end":{"line":554,"column":29}},{"start":{"line":554,"column":21},"end":{"line":554,"column":29}}]},"112":{"loc":{"start":{"line":555,"column":4},"end":{"line":561,"column":null}},"type":"if","locations":[{"start":{"line":555,"column":4},"end":{"line":561,"column":null}}]},"113":{"loc":{"start":{"line":558,"column":10},"end":{"line":558,"column":48}},"type":"cond-expr","locations":[{"start":{"line":558,"column":24},"end":{"line":558,"column":43}},{"start":{"line":558,"column":46},"end":{"line":558,"column":48}}]},"114":{"loc":{"start":{"line":559,"column":11},"end":{"line":559,"column":50}},"type":"cond-expr","locations":[{"start":{"line":559,"column":26},"end":{"line":559,"column":45}},{"start":{"line":559,"column":48},"end":{"line":559,"column":50}}]},"115":{"loc":{"start":{"line":565,"column":8},"end":{"line":565,"column":43}},"type":"cond-expr","locations":[{"start":{"line":565,"column":37},"end":{"line":565,"column":41}},{"start":{"line":565,"column":41},"end":{"line":565,"column":43}}]},"116":{"loc":{"start":{"line":565,"column":8},"end":{"line":565,"column":41}},"type":"binary-expr","locations":[{"start":{"line":565,"column":8},"end":{"line":565,"column":41}},{"start":{"line":565,"column":37},"end":{"line":565,"column":41}}]},"117":{"loc":{"start":{"line":565,"column":8},"end":{"line":565,"column":37}},"type":"cond-expr","locations":[{"start":{"line":565,"column":14},"end":{"line":565,"column":16}},{"start":{"line":565,"column":8},"end":{"line":565,"column":37}}]},"118":{"loc":{"start":{"line":565,"column":8},"end":{"line":565,"column":16}},"type":"binary-expr","locations":[{"start":{"line":565,"column":8},"end":{"line":565,"column":16}},{"start":{"line":565,"column":8},"end":{"line":565,"column":16}}]},"119":{"loc":{"start":{"line":566,"column":8},"end":{"line":566,"column":39}},"type":"cond-expr","locations":[{"start":{"line":566,"column":33},"end":{"line":566,"column":37}},{"start":{"line":566,"column":37},"end":{"line":566,"column":39}}]},"120":{"loc":{"start":{"line":566,"column":8},"end":{"line":566,"column":37}},"type":"binary-expr","locations":[{"start":{"line":566,"column":8},"end":{"line":566,"column":37}},{"start":{"line":566,"column":33},"end":{"line":566,"column":37}}]},"121":{"loc":{"start":{"line":566,"column":8},"end":{"line":566,"column":33}},"type":"cond-expr","locations":[{"start":{"line":566,"column":14},"end":{"line":566,"column":16}},{"start":{"line":566,"column":8},"end":{"line":566,"column":33}}]},"122":{"loc":{"start":{"line":566,"column":8},"end":{"line":566,"column":16}},"type":"binary-expr","locations":[{"start":{"line":566,"column":8},"end":{"line":566,"column":16}},{"start":{"line":566,"column":8},"end":{"line":566,"column":16}}]},"123":{"loc":{"start":{"line":569,"column":20},"end":{"line":569,"column":37}},"type":"cond-expr","locations":[{"start":{"line":569,"column":28},"end":{"line":569,"column":30}},{"start":{"line":569,"column":28},"end":{"line":569,"column":37}}]},"124":{"loc":{"start":{"line":569,"column":20},"end":{"line":569,"column":30}},"type":"binary-expr","locations":[{"start":{"line":569,"column":20},"end":{"line":569,"column":30}},{"start":{"line":569,"column":28},"end":{"line":569,"column":30}}]},"125":{"loc":{"start":{"line":570,"column":4},"end":{"line":576,"column":null}},"type":"if","locations":[{"start":{"line":570,"column":4},"end":{"line":576,"column":null}}]},"126":{"loc":{"start":{"line":570,"column":8},"end":{"line":570,"column":23}},"type":"cond-expr","locations":[{"start":{"line":570,"column":15},"end":{"line":570,"column":17}},{"start":{"line":570,"column":8},"end":{"line":570,"column":23}}]},"127":{"loc":{"start":{"line":570,"column":8},"end":{"line":570,"column":17}},"type":"binary-expr","locations":[{"start":{"line":570,"column":8},"end":{"line":570,"column":17}},{"start":{"line":570,"column":8},"end":{"line":570,"column":17}}]},"128":{"loc":{"start":{"line":573,"column":10},"end":{"line":573,"column":59}},"type":"cond-expr","locations":[{"start":{"line":573,"column":28},"end":{"line":573,"column":54}},{"start":{"line":573,"column":57},"end":{"line":573,"column":59}}]},"129":{"loc":{"start":{"line":577,"column":23},"end":{"line":577,"column":43}},"type":"cond-expr","locations":[{"start":{"line":577,"column":31},"end":{"line":577,"column":33}},{"start":{"line":577,"column":31},"end":{"line":577,"column":43}}]},"130":{"loc":{"start":{"line":577,"column":23},"end":{"line":577,"column":33}},"type":"binary-expr","locations":[{"start":{"line":577,"column":23},"end":{"line":577,"column":33}},{"start":{"line":577,"column":31},"end":{"line":577,"column":33}}]},"131":{"loc":{"start":{"line":578,"column":4},"end":{"line":586,"column":null}},"type":"if","locations":[{"start":{"line":578,"column":4},"end":{"line":586,"column":null}}]},"132":{"loc":{"start":{"line":581,"column":10},"end":{"line":581,"column":40}},"type":"cond-expr","locations":[{"start":{"line":581,"column":27},"end":{"line":581,"column":31}},{"start":{"line":581,"column":31},"end":{"line":581,"column":40}}]},"133":{"loc":{"start":{"line":581,"column":10},"end":{"line":581,"column":31}},"type":"binary-expr","locations":[{"start":{"line":581,"column":10},"end":{"line":581,"column":31}},{"start":{"line":581,"column":27},"end":{"line":581,"column":31}}]},"134":{"loc":{"start":{"line":583,"column":10},"end":{"line":583,"column":65}},"type":"cond-expr","locations":[{"start":{"line":583,"column":31},"end":{"line":583,"column":60}},{"start":{"line":583,"column":63},"end":{"line":583,"column":65}}]},"135":{"loc":{"start":{"line":591,"column":2},"end":{"line":593,"column":null}},"type":"if","locations":[{"start":{"line":591,"column":2},"end":{"line":593,"column":null}}]},"136":{"loc":{"start":{"line":611,"column":8},"end":{"line":611,"column":56}},"type":"cond-expr","locations":[{"start":{"line":611,"column":31},"end":{"line":611,"column":42}},{"start":{"line":611,"column":45},"end":{"line":611,"column":56}}]},"137":{"loc":{"start":{"line":618,"column":2},"end":{"line":620,"column":null}},"type":"if","locations":[{"start":{"line":618,"column":2},"end":{"line":620,"column":null}}]},"138":{"loc":{"start":{"line":623,"column":14},"end":{"line":623,"column":64}},"type":"cond-expr","locations":[{"start":{"line":623,"column":44},"end":{"line":623,"column":48}},{"start":{"line":623,"column":48},"end":{"line":623,"column":64}}]},"139":{"loc":{"start":{"line":623,"column":14},"end":{"line":623,"column":48}},"type":"binary-expr","locations":[{"start":{"line":623,"column":14},"end":{"line":623,"column":48}},{"start":{"line":623,"column":44},"end":{"line":623,"column":48}}]},"140":{"loc":{"start":{"line":623,"column":14},"end":{"line":623,"column":44}},"type":"cond-expr","locations":[{"start":{"line":623,"column":29},"end":{"line":623,"column":33}},{"start":{"line":623,"column":33},"end":{"line":623,"column":44}}]},"141":{"loc":{"start":{"line":623,"column":14},"end":{"line":623,"column":33}},"type":"binary-expr","locations":[{"start":{"line":623,"column":14},"end":{"line":623,"column":33}},{"start":{"line":623,"column":29},"end":{"line":623,"column":33}}]},"142":{"loc":{"start":{"line":624,"column":11},"end":{"line":624,"column":40}},"type":"cond-expr","locations":[{"start":{"line":624,"column":15},"end":{"line":624,"column":36}},{"start":{"line":624,"column":39},"end":{"line":624,"column":40}}]},"143":{"loc":{"start":{"line":630,"column":18},"end":{"line":630,"column":64}},"type":"cond-expr","locations":[{"start":{"line":630,"column":43},"end":{"line":630,"column":59}},{"start":{"line":630,"column":62},"end":{"line":630,"column":64}}]},"144":{"loc":{"start":{"line":630,"column":18},"end":{"line":630,"column":40}},"type":"binary-expr","locations":[{"start":{"line":630,"column":18},"end":{"line":630,"column":25}},{"start":{"line":630,"column":29},"end":{"line":630,"column":40}}]},"145":{"loc":{"start":{"line":631,"column":30},"end":{"line":631,"column":44}},"type":"cond-expr","locations":[{"start":{"line":631,"column":38},"end":{"line":631,"column":42}},{"start":{"line":631,"column":42},"end":{"line":631,"column":44}}]},"146":{"loc":{"start":{"line":631,"column":30},"end":{"line":631,"column":42}},"type":"binary-expr","locations":[{"start":{"line":631,"column":30},"end":{"line":631,"column":42}},{"start":{"line":631,"column":38},"end":{"line":631,"column":42}}]},"147":{"loc":{"start":{"line":632,"column":6},"end":{"line":632,"column":21}},"type":"cond-expr","locations":[{"start":{"line":632,"column":15},"end":{"line":632,"column":19}},{"start":{"line":632,"column":19},"end":{"line":632,"column":21}}]},"148":{"loc":{"start":{"line":632,"column":6},"end":{"line":632,"column":19}},"type":"binary-expr","locations":[{"start":{"line":632,"column":6},"end":{"line":632,"column":19}},{"start":{"line":632,"column":15},"end":{"line":632,"column":19}}]},"149":{"loc":{"start":{"line":635,"column":2},"end":{"line":639,"column":null}},"type":"if","locations":[{"start":{"line":635,"column":2},"end":{"line":639,"column":null}}]},"150":{"loc":{"start":{"line":647,"column":2},"end":{"line":647,"column":null}},"type":"if","locations":[{"start":{"line":647,"column":2},"end":{"line":647,"column":null}}]},"151":{"loc":{"start":{"line":651,"column":9},"end":{"line":651,"column":null}},"type":"if","locations":[{"start":{"line":651,"column":9},"end":{"line":651,"column":null}}]},"152":{"loc":{"start":{"line":654,"column":4},"end":{"line":656,"column":null}},"type":"if","locations":[{"start":{"line":654,"column":4},"end":{"line":656,"column":null}}]},"153":{"loc":{"start":{"line":658,"column":8},"end":{"line":658,"column":9}},"type":"if","locations":[{"start":{"line":658,"column":8},"end":{"line":658,"column":9}}]},"154":{"loc":{"start":{"line":666,"column":8},"end":{"line":666,"column":23}},"type":"if","locations":[{"start":{"line":666,"column":8},"end":{"line":666,"column":23}}]},"155":{"loc":{"start":{"line":676,"column":8},"end":{"line":676,"column":23}},"type":"if","locations":[{"start":{"line":676,"column":8},"end":{"line":676,"column":23}}]},"156":{"loc":{"start":{"line":700,"column":2},"end":{"line":702,"column":null}},"type":"if","locations":[{"start":{"line":700,"column":2},"end":{"line":702,"column":null}}]},"157":{"loc":{"start":{"line":705,"column":2},"end":{"line":710,"column":null}},"type":"if","locations":[{"start":{"line":705,"column":2},"end":{"line":710,"column":null}}]},"158":{"loc":{"start":{"line":705,"column":6},"end":{"line":705,"column":44}},"type":"binary-expr","locations":[{"start":{"line":705,"column":6},"end":{"line":705,"column":21}},{"start":{"line":705,"column":25},"end":{"line":705,"column":44}}]},"159":{"loc":{"start":{"line":716,"column":19},"end":{"line":716,"column":null}},"type":"switch","locations":[{"start":{"line":716,"column":19},"end":{"line":716,"column":null}}]},"160":{"loc":{"start":{"line":729,"column":2},"end":{"line":731,"column":null}},"type":"if","locations":[{"start":{"line":729,"column":2},"end":{"line":731,"column":null}}]},"161":{"loc":{"start":{"line":729,"column":6},"end":{"line":729,"column":65}},"type":"binary-expr","locations":[{"start":{"line":729,"column":6},"end":{"line":729,"column":28}},{"start":{"line":729,"column":28},"end":{"line":729,"column":65}}]},"162":{"loc":{"start":{"line":729,"column":7},"end":{"line":729,"column":24}},"type":"cond-expr","locations":[{"start":{"line":729,"column":17},"end":{"line":729,"column":19}},{"start":{"line":729,"column":17},"end":{"line":729,"column":24}}]},"163":{"loc":{"start":{"line":729,"column":7},"end":{"line":729,"column":19}},"type":"binary-expr","locations":[{"start":{"line":729,"column":7},"end":{"line":729,"column":19}},{"start":{"line":729,"column":17},"end":{"line":729,"column":19}}]},"164":{"loc":{"start":{"line":736,"column":19},"end":{"line":736,"column":null}},"type":"switch","locations":[{"start":{"line":736,"column":19},"end":{"line":736,"column":null}}]},"165":{"loc":{"start":{"line":738,"column":2},"end":{"line":740,"column":null}},"type":"if","locations":[{"start":{"line":738,"column":2},"end":{"line":740,"column":null}}]},"166":{"loc":{"start":{"line":738,"column":6},"end":{"line":738,"column":24}},"type":"cond-expr","locations":[{"start":{"line":738,"column":16},"end":{"line":738,"column":18}},{"start":{"line":738,"column":16},"end":{"line":738,"column":24}}]},"167":{"loc":{"start":{"line":738,"column":6},"end":{"line":738,"column":18}},"type":"binary-expr","locations":[{"start":{"line":738,"column":6},"end":{"line":738,"column":18}},{"start":{"line":738,"column":16},"end":{"line":738,"column":18}}]},"168":{"loc":{"start":{"line":741,"column":11},"end":{"line":741,"column":32}},"type":"cond-expr","locations":[{"start":{"line":741,"column":21},"end":{"line":741,"column":23}},{"start":{"line":741,"column":21},"end":{"line":741,"column":32}}]},"169":{"loc":{"start":{"line":741,"column":11},"end":{"line":741,"column":23}},"type":"binary-expr","locations":[{"start":{"line":741,"column":11},"end":{"line":741,"column":23}},{"start":{"line":741,"column":21},"end":{"line":741,"column":23}}]},"170":{"loc":{"start":{"line":768,"column":18},"end":{"line":775,"column":null}},"type":"switch","locations":[{"start":{"line":768,"column":18},"end":{"line":775,"column":null}}]},"171":{"loc":{"start":{"line":776,"column":2},"end":{"line":778,"column":null}},"type":"if","locations":[{"start":{"line":776,"column":2},"end":{"line":778,"column":null}}]},"172":{"loc":{"start":{"line":782,"column":13},"end":{"line":782,"column":63}},"type":"binary-expr","locations":[{"start":{"line":782,"column":13},"end":{"line":782,"column":31}},{"start":{"line":782,"column":35},"end":{"line":782,"column":63}}]},"173":{"loc":{"start":{"line":782,"column":13},"end":{"line":782,"column":31}},"type":"cond-expr","locations":[{"start":{"line":782,"column":25},"end":{"line":782,"column":27}},{"start":{"line":782,"column":25},"end":{"line":782,"column":31}}]},"174":{"loc":{"start":{"line":782,"column":13},"end":{"line":782,"column":27}},"type":"binary-expr","locations":[{"start":{"line":782,"column":13},"end":{"line":782,"column":27}},{"start":{"line":782,"column":25},"end":{"line":782,"column":27}}]},"175":{"loc":{"start":{"line":790,"column":19},"end":{"line":790,"column":null}},"type":"switch","locations":[{"start":{"line":790,"column":19},"end":{"line":790,"column":null}}]},"176":{"loc":{"start":{"line":813,"column":33},"end":{"line":813,"column":58}},"type":"cond-expr","locations":[{"start":{"line":813,"column":49},"end":{"line":813,"column":51}},{"start":{"line":813,"column":49},"end":{"line":813,"column":58}}]},"177":{"loc":{"start":{"line":813,"column":33},"end":{"line":813,"column":51}},"type":"binary-expr","locations":[{"start":{"line":813,"column":33},"end":{"line":813,"column":51}},{"start":{"line":813,"column":49},"end":{"line":813,"column":51}}]},"178":{"loc":{"start":{"line":835,"column":2},"end":{"line":835,"column":null}},"type":"switch","locations":[{"start":{"line":835,"column":2},"end":{"line":835,"column":null}}]},"179":{"loc":{"start":{"line":839,"column":15},"end":{"line":839,"column":null}},"type":"switch","locations":[{"start":{"line":839,"column":15},"end":{"line":839,"column":null}}]},"180":{"loc":{"start":{"line":841,"column":19},"end":{"line":841,"column":43}},"type":"cond-expr","locations":[{"start":{"line":841,"column":33},"end":{"line":841,"column":35}},{"start":{"line":841,"column":33},"end":{"line":841,"column":43}}]},"181":{"loc":{"start":{"line":841,"column":19},"end":{"line":841,"column":35}},"type":"binary-expr","locations":[{"start":{"line":841,"column":19},"end":{"line":841,"column":35}},{"start":{"line":841,"column":33},"end":{"line":841,"column":35}}]},"182":{"loc":{"start":{"line":842,"column":2},"end":{"line":844,"column":null}},"type":"if","locations":[{"start":{"line":842,"column":2},"end":{"line":844,"column":null}}]},"183":{"loc":{"start":{"line":897,"column":2},"end":{"line":899,"column":null}},"type":"if","locations":[{"start":{"line":897,"column":2},"end":{"line":899,"column":null}}]},"184":{"loc":{"start":{"line":902,"column":2},"end":{"line":906,"column":null}},"type":"if","locations":[{"start":{"line":902,"column":2},"end":{"line":906,"column":null}}]},"185":{"loc":{"start":{"line":902,"column":7},"end":{"line":902,"column":25}},"type":"cond-expr","locations":[{"start":{"line":902,"column":14},"end":{"line":902,"column":16}},{"start":{"line":902,"column":7},"end":{"line":902,"column":25}}]},"186":{"loc":{"start":{"line":902,"column":7},"end":{"line":902,"column":16}},"type":"binary-expr","locations":[{"start":{"line":902,"column":7},"end":{"line":902,"column":16}},{"start":{"line":902,"column":7},"end":{"line":902,"column":16}}]},"187":{"loc":{"start":{"line":914,"column":4},"end":{"line":916,"column":null}},"type":"if","locations":[{"start":{"line":914,"column":4},"end":{"line":916,"column":null}}]},"188":{"loc":{"start":{"line":914,"column":8},"end":{"line":914,"column":51}},"type":"binary-expr","locations":[{"start":{"line":914,"column":8},"end":{"line":914,"column":26}},{"start":{"line":914,"column":30},"end":{"line":914,"column":51}}]},"189":{"loc":{"start":{"line":920,"column":4},"end":{"line":922,"column":null}},"type":"switch","locations":[{"start":{"line":920,"column":4},"end":{"line":922,"column":null}}]},"190":{"loc":{"start":{"line":924,"column":4},"end":{"line":926,"column":null}},"type":"if","locations":[{"start":{"line":924,"column":4},"end":{"line":926,"column":null}}]},"191":{"loc":{"start":{"line":924,"column":8},"end":{"line":924,"column":73}},"type":"binary-expr","locations":[{"start":{"line":924,"column":8},"end":{"line":924,"column":30}},{"start":{"line":924,"column":34},"end":{"line":924,"column":73}}]},"192":{"loc":{"start":{"line":927,"column":4},"end":{"line":929,"column":null}},"type":"if","locations":[{"start":{"line":927,"column":4},"end":{"line":929,"column":null}}]},"193":{"loc":{"start":{"line":930,"column":4},"end":{"line":932,"column":null}},"type":"if","locations":[{"start":{"line":930,"column":4},"end":{"line":932,"column":null}}]},"194":{"loc":{"start":{"line":940,"column":2},"end":{"line":942,"column":null}},"type":"if","locations":[{"start":{"line":940,"column":2},"end":{"line":942,"column":null}}]},"195":{"loc":{"start":{"line":940,"column":7},"end":{"line":940,"column":37}},"type":"cond-expr","locations":[{"start":{"line":940,"column":29},"end":{"line":940,"column":31}},{"start":{"line":940,"column":29},"end":{"line":940,"column":37}}]},"196":{"loc":{"start":{"line":940,"column":7},"end":{"line":940,"column":31}},"type":"binary-expr","locations":[{"start":{"line":940,"column":7},"end":{"line":940,"column":31}},{"start":{"line":940,"column":29},"end":{"line":940,"column":31}}]},"197":{"loc":{"start":{"line":945,"column":4},"end":{"line":947,"column":null}},"type":"if","locations":[{"start":{"line":945,"column":4},"end":{"line":947,"column":null}}]},"198":{"loc":{"start":{"line":951,"column":6},"end":{"line":951,"column":75}},"type":"cond-expr","locations":[{"start":{"line":951,"column":36},"end":{"line":951,"column":67}},{"start":{"line":951,"column":70},"end":{"line":951,"column":75}}]},"199":{"loc":{"start":{"line":954,"column":4},"end":{"line":956,"column":null}},"type":"if","locations":[{"start":{"line":954,"column":4},"end":{"line":956,"column":null}}]},"200":{"loc":{"start":{"line":960,"column":6},"end":{"line":962,"column":null}},"type":"if","locations":[{"start":{"line":960,"column":6},"end":{"line":962,"column":null}}]},"201":{"loc":{"start":{"line":960,"column":10},"end":{"line":960,"column":58}},"type":"binary-expr","locations":[{"start":{"line":960,"column":10},"end":{"line":960,"column":32}},{"start":{"line":960,"column":36},"end":{"line":960,"column":43}},{"start":{"line":960,"column":47},"end":{"line":960,"column":58}}]},"202":{"loc":{"start":{"line":966,"column":4},"end":{"line":971,"column":null}},"type":"if","locations":[{"start":{"line":966,"column":4},"end":{"line":971,"column":null}},{"start":{"line":968,"column":11},"end":{"line":971,"column":null}}]},"203":{"loc":{"start":{"line":979,"column":19},"end":{"line":979,"column":null}},"type":"switch","locations":[{"start":{"line":979,"column":19},"end":{"line":979,"column":null}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":1,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":1,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":1,"108":0,"109":1,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":1,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":1,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"142":0,"143":0,"144":0,"145":1,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"158":0,"159":0,"160":0,"161":1,"162":0,"163":1,"164":0,"165":0,"166":0,"167":0,"168":0,"169":0,"170":1,"171":1,"172":1,"173":1,"174":1,"175":0,"176":0,"177":0,"178":0,"179":0,"180":0,"181":0,"182":0,"183":0,"184":0,"185":0,"186":0,"187":1,"188":0,"189":0,"190":0,"191":0,"192":0,"193":0,"194":0,"195":0,"196":0,"197":0,"198":0,"199":0,"200":1,"201":0,"202":0,"203":0,"204":0,"205":0,"206":0,"207":0,"208":0,"209":0,"210":0,"211":0,"212":0,"213":1,"214":0,"215":0,"216":0,"217":0,"218":0,"219":0,"220":0,"221":0,"222":0,"223":0,"224":1,"225":0,"226":0,"227":0,"228":0,"229":0,"230":0,"231":0,"232":0,"233":0,"234":0,"235":0,"236":0,"237":1,"238":0,"239":0,"240":0,"241":0,"242":0,"243":0,"244":0,"245":0,"246":1,"247":0,"248":0,"249":0,"250":0,"251":0,"252":0,"253":0,"254":0,"255":0,"256":0,"257":1,"258":0,"259":0,"260":0,"261":0,"262":0,"263":0,"264":0,"265":0,"266":0,"267":0,"268":0,"269":0,"270":0,"271":0,"272":0,"273":0,"274":0,"275":0,"276":0,"277":0,"278":0,"279":0,"280":0,"281":0,"282":0,"283":0,"284":0,"285":0,"286":0,"287":0,"288":0,"289":1,"290":0,"291":0,"292":0,"293":0,"294":0,"295":0,"296":0,"297":0,"298":0,"299":0,"300":0,"301":0,"302":0,"303":0,"304":0,"305":0,"306":0,"307":0,"308":0,"309":0,"310":0,"311":0,"312":0,"313":0,"314":0,"315":0,"316":0,"317":0,"318":0,"319":0,"320":0,"321":0,"322":0,"323":0,"324":0,"325":0,"326":0,"327":0,"328":0,"329":0,"330":0,"331":0,"332":0,"333":0,"334":0,"335":0,"336":0,"337":0,"338":0,"339":1,"340":3,"341":3,"342":3,"343":0,"344":0,"345":0,"346":0,"347":0,"348":1,"349":0,"350":0,"351":0,"352":1,"353":0,"354":0,"355":0,"356":1,"357":0,"358":0,"359":0,"360":0,"361":0,"362":0,"363":0,"364":0,"365":0,"366":0,"367":0,"368":0,"369":0,"370":0,"371":0,"372":0,"373":0,"374":1,"375":0,"376":0,"377":0,"378":0,"379":0,"380":0,"381":1,"382":0,"383":0,"384":0,"385":1,"386":0,"387":0,"388":0,"389":0,"390":0,"391":0,"392":0,"393":0,"394":0,"395":0,"396":0,"397":0,"398":0,"399":0,"400":0,"401":0,"402":0,"403":0,"404":1,"405":0,"406":0,"407":0,"408":0,"409":1,"410":0,"411":0,"412":0,"413":0,"414":0,"415":0,"416":0,"417":0,"418":0,"419":0,"420":0,"421":0,"422":0,"423":0,"424":0,"425":0,"426":0,"427":0,"428":0,"429":0,"430":0,"431":0,"432":0,"433":0,"434":0,"435":0,"436":1,"437":1,"438":0,"439":0,"440":0,"441":0,"442":0,"443":1,"444":0,"445":0,"446":0,"447":0,"448":0,"449":0,"450":0,"451":0,"452":0,"453":1,"454":3,"455":3,"456":3,"457":0,"458":0,"459":0,"460":0,"461":0,"462":0,"463":0,"464":0,"465":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"472":0,"473":0,"474":0,"475":0,"476":0,"477":0,"478":0,"479":0,"480":1,"481":0,"482":0,"483":0,"484":1},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":3,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":1,"49":0,"50":0,"51":0,"52":3,"53":0,"54":0},"b":{"0":[0],"1":[0],"2":[0,0],"3":[0,0],"4":[0],"5":[0],"6":[0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0],"12":[0,0],"13":[0,0],"14":[0],"15":[0,0],"16":[0,0],"17":[0],"18":[0],"19":[0],"20":[0],"21":[0],"22":[0],"23":[0,0],"24":[0,0],"25":[0],"26":[0,0],"27":[0,0],"28":[0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0,0],"38":[0],"39":[0],"40":[0],"41":[0,0],"42":[0],"43":[0],"44":[0],"45":[0,0],"46":[0,0],"47":[0,0],"48":[0],"49":[0],"50":[0],"51":[0],"52":[0],"53":[0],"54":[0,0],"55":[0,0],"56":[0,0],"57":[0,0],"58":[0,0],"59":[0,0],"60":[0,0],"61":[0,0],"62":[0,0],"63":[0,0],"64":[0],"65":[0,0],"66":[0,0],"67":[0,0],"68":[0,0],"69":[0,0],"70":[0],"71":[0,0,0],"72":[0,0],"73":[0,0],"74":[0,0],"75":[0,0],"76":[0,0],"77":[0,0],"78":[0],"79":[0,0,0],"80":[0,0],"81":[0,0],"82":[0,0],"83":[0,0],"84":[0,0],"85":[0,0],"86":[0,0],"87":[0,0],"88":[0,0],"89":[0,0],"90":[0,0],"91":[0,0],"92":[0,0],"93":[0,0],"94":[0],"95":[0,0],"96":[0,0],"97":[0,0],"98":[0,0],"99":[0,0],"100":[0,0],"101":[0],"102":[0,0],"103":[0,0],"104":[0,0],"105":[0],"106":[0,0],"107":[0,0],"108":[0,0],"109":[0,0],"110":[0,0],"111":[0,0],"112":[0],"113":[0,0],"114":[0,0],"115":[0,0],"116":[0,0],"117":[0,0],"118":[0,0],"119":[0,0],"120":[0,0],"121":[0,0],"122":[0,0],"123":[0,0],"124":[0,0],"125":[0],"126":[0,0],"127":[0,0],"128":[0,0],"129":[0,0],"130":[0,0],"131":[0],"132":[0,0],"133":[0,0],"134":[0,0],"135":[0],"136":[0,0],"137":[0],"138":[0,0],"139":[0,0],"140":[0,0],"141":[0,0],"142":[0,0],"143":[0,0],"144":[0,0],"145":[0,0],"146":[0,0],"147":[0,0],"148":[0,0],"149":[0],"150":[0],"151":[0],"152":[0],"153":[0],"154":[0],"155":[0],"156":[3],"157":[0],"158":[0,0],"159":[0],"160":[0],"161":[0,0],"162":[0,0],"163":[0,0],"164":[0],"165":[0],"166":[0,0],"167":[0,0],"168":[0,0],"169":[0,0],"170":[0],"171":[0],"172":[0,0],"173":[0,0],"174":[0,0],"175":[0],"176":[0,0],"177":[0,0],"178":[0],"179":[0],"180":[0,0],"181":[0,0],"182":[0],"183":[0],"184":[0],"185":[0,0],"186":[0,0],"187":[0],"188":[0,0],"189":[0],"190":[0],"191":[0,0],"192":[0],"193":[0],"194":[3],"195":[3,0],"196":[3,3],"197":[0],"198":[0,0],"199":[0],"200":[0],"201":[0,0,0],"202":[0,0],"203":[0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/k8s/utils.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/src/k8s/utils.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":24}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":31}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":37}},"3":{"start":{"line":6,"column":0},"end":{"line":6,"column":28}},"4":{"start":{"line":7,"column":0},"end":{"line":7,"column":35}},"5":{"start":{"line":8,"column":0},"end":{"line":8,"column":41}},"6":{"start":{"line":9,"column":0},"end":{"line":9,"column":63}},"7":{"start":{"line":10,"column":0},"end":{"line":10,"column":30}},"8":{"start":{"line":12,"column":13},"end":{"line":12,"column":null}},"9":{"start":{"line":13,"column":13},"end":{"line":13,"column":null}},"10":{"start":{"line":15,"column":13},"end":{"line":15,"column":null}},"11":{"start":{"line":16,"column":13},"end":{"line":16,"column":null}},"12":{"start":{"line":19,"column":2},"end":{"line":19,"column":null}},"13":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"14":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"15":{"start":{"line":23,"column":38},"end":{"line":28,"column":null}},"16":{"start":{"line":30,"column":24},"end":{"line":30,"column":62}},"17":{"start":{"line":31,"column":2},"end":{"line":57,"column":null}},"18":{"start":{"line":32,"column":14},"end":{"line":32,"column":49}},"19":{"start":{"line":33,"column":34},"end":{"line":33,"column":74}},"20":{"start":{"line":34,"column":4},"end":{"line":55,"column":null}},"21":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"22":{"start":{"line":59,"column":2},"end":{"line":61,"column":null}},"23":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"24":{"start":{"line":63,"column":2},"end":{"line":79,"column":null}},"25":{"start":{"line":81,"column":2},"end":{"line":83,"column":null}},"26":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"27":{"start":{"line":85,"column":2},"end":{"line":107,"column":null}},"28":{"start":{"line":85,"column":27},"end":{"line":85,"column":43}},"29":{"start":{"line":85,"column":23},"end":{"line":85,"column":27}},"30":{"start":{"line":86,"column":27},"end":{"line":86,"column":29}},"31":{"start":{"line":87,"column":4},"end":{"line":99,"column":null}},"32":{"start":{"line":88,"column":6},"end":{"line":92,"column":null}},"33":{"start":{"line":89,"column":8},"end":{"line":91,"column":null}},"34":{"start":{"line":94,"column":6},"end":{"line":96,"column":null}},"35":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"36":{"start":{"line":101,"column":4},"end":{"line":106,"column":null}},"37":{"start":{"line":109,"column":2},"end":{"line":109,"column":null}},"38":{"start":{"line":18,"column":0},"end":{"line":18,"column":16}},"39":{"start":{"line":119,"column":19},"end":{"line":119,"column":21}},"40":{"start":{"line":120,"column":2},"end":{"line":125,"column":null}},"41":{"start":{"line":123,"column":6},"end":{"line":123,"column":75}},"42":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"43":{"start":{"line":126,"column":26},"end":{"line":126,"column":28}},"44":{"start":{"line":128,"column":2},"end":{"line":150,"column":null}},"45":{"start":{"line":129,"column":32},"end":{"line":129,"column":34}},"46":{"start":{"line":130,"column":4},"end":{"line":148,"column":null}},"47":{"start":{"line":130,"column":31},"end":{"line":130,"column":37}},"48":{"start":{"line":130,"column":31},"end":{"line":130,"column":67}},"49":{"start":{"line":130,"column":15},"end":{"line":130,"column":16}},"50":{"start":{"line":130,"column":19},"end":{"line":130,"column":21}},"51":{"start":{"line":130,"column":26},"end":{"line":130,"column":27}},"52":{"start":{"line":131,"column":6},"end":{"line":140,"column":null}},"53":{"start":{"line":137,"column":8},"end":{"line":139,"column":null}},"54":{"start":{"line":141,"column":6},"end":{"line":147,"column":null}},"55":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"56":{"start":{"line":152,"column":18},"end":{"line":156,"column":null}},"57":{"start":{"line":159,"column":19},"end":{"line":159,"column":35}},"58":{"start":{"line":160,"column":25},"end":{"line":160,"column":65}},"59":{"start":{"line":161,"column":2},"end":{"line":161,"column":null}},"60":{"start":{"line":162,"column":2},"end":{"line":165,"column":null}},"61":{"start":{"line":112,"column":0},"end":{"line":112,"column":16}},"62":{"start":{"line":169,"column":22},"end":{"line":169,"column":44}},"63":{"start":{"line":170,"column":15},"end":{"line":170,"column":44}},"64":{"start":{"line":172,"column":2},"end":{"line":174,"column":null}},"65":{"start":{"line":173,"column":4},"end":{"line":173,"column":null}},"66":{"start":{"line":176,"column":2},"end":{"line":176,"column":null}},"67":{"start":{"line":168,"column":0},"end":{"line":168,"column":16}},"68":{"start":{"line":191,"column":2},"end":{"line":212,"column":null}},"69":{"start":{"line":191,"column":29},"end":{"line":191,"column":35}},"70":{"start":{"line":191,"column":29},"end":{"line":191,"column":49}},"71":{"start":{"line":191,"column":13},"end":{"line":191,"column":14}},"72":{"start":{"line":191,"column":17},"end":{"line":191,"column":19}},"73":{"start":{"line":191,"column":24},"end":{"line":191,"column":25}},"74":{"start":{"line":192,"column":4},"end":{"line":211,"column":null}},"75":{"start":{"line":193,"column":6},"end":{"line":195,"column":null}},"76":{"start":{"line":194,"column":8},"end":{"line":194,"column":null}},"77":{"start":{"line":196,"column":6},"end":{"line":196,"column":14}},"78":{"start":{"line":197,"column":11},"end":{"line":211,"column":null}},"79":{"start":{"line":198,"column":6},"end":{"line":198,"column":null}},"80":{"start":{"line":199,"column":6},"end":{"line":199,"column":14}},"81":{"start":{"line":200,"column":11},"end":{"line":211,"column":null}},"82":{"start":{"line":201,"column":19},"end":{"line":201,"column":42}},"83":{"start":{"line":202,"column":6},"end":{"line":202,"column":null}},"84":{"start":{"line":203,"column":11},"end":{"line":211,"column":null}},"85":{"start":{"line":204,"column":27},"end":{"line":204,"column":55}},"86":{"start":{"line":205,"column":6},"end":{"line":205,"column":null}},"87":{"start":{"line":206,"column":11},"end":{"line":211,"column":null}},"88":{"start":{"line":207,"column":20},"end":{"line":207,"column":50}},"89":{"start":{"line":208,"column":6},"end":{"line":208,"column":null}},"90":{"start":{"line":210,"column":6},"end":{"line":210,"column":null}},"91":{"start":{"line":187,"column":0},"end":{"line":187,"column":16}},"92":{"start":{"line":219,"column":2},"end":{"line":232,"column":null}},"93":{"start":{"line":219,"column":29},"end":{"line":219,"column":35}},"94":{"start":{"line":219,"column":29},"end":{"line":219,"column":49}},"95":{"start":{"line":219,"column":13},"end":{"line":219,"column":14}},"96":{"start":{"line":219,"column":17},"end":{"line":219,"column":19}},"97":{"start":{"line":219,"column":24},"end":{"line":219,"column":25}},"98":{"start":{"line":220,"column":4},"end":{"line":231,"column":null}},"99":{"start":{"line":221,"column":6},"end":{"line":224,"column":null}},"100":{"start":{"line":223,"column":15},"end":{"line":223,"column":null}},"101":{"start":{"line":226,"column":11},"end":{"line":231,"column":null}},"102":{"start":{"line":227,"column":22},"end":{"line":227,"column":45}},"103":{"start":{"line":228,"column":6},"end":{"line":228,"column":null}},"104":{"start":{"line":230,"column":6},"end":{"line":230,"column":null}},"105":{"start":{"line":215,"column":0},"end":{"line":215,"column":16}},"106":{"start":{"line":239,"column":2},"end":{"line":243,"column":null}},"107":{"start":{"line":240,"column":4},"end":{"line":242,"column":null}},"108":{"start":{"line":244,"column":2},"end":{"line":251,"column":null}},"109":{"start":{"line":245,"column":4},"end":{"line":250,"column":null}},"110":{"start":{"line":245,"column":31},"end":{"line":245,"column":37}},"111":{"start":{"line":245,"column":31},"end":{"line":245,"column":58}},"112":{"start":{"line":245,"column":15},"end":{"line":245,"column":16}},"113":{"start":{"line":245,"column":19},"end":{"line":245,"column":21}},"114":{"start":{"line":245,"column":26},"end":{"line":245,"column":27}},"115":{"start":{"line":246,"column":6},"end":{"line":248,"column":null}},"116":{"start":{"line":247,"column":8},"end":{"line":247,"column":null}},"117":{"start":{"line":249,"column":6},"end":{"line":249,"column":null}},"118":{"start":{"line":253,"column":2},"end":{"line":262,"column":null}},"119":{"start":{"line":254,"column":4},"end":{"line":261,"column":null}},"120":{"start":{"line":254,"column":31},"end":{"line":254,"column":37}},"121":{"start":{"line":254,"column":31},"end":{"line":254,"column":63}},"122":{"start":{"line":254,"column":15},"end":{"line":254,"column":16}},"123":{"start":{"line":254,"column":19},"end":{"line":254,"column":21}},"124":{"start":{"line":254,"column":26},"end":{"line":254,"column":27}},"125":{"start":{"line":255,"column":6},"end":{"line":259,"column":null}},"126":{"start":{"line":256,"column":8},"end":{"line":258,"column":null}},"127":{"start":{"line":260,"column":6},"end":{"line":260,"column":null}},"128":{"start":{"line":235,"column":0},"end":{"line":235,"column":16}},"129":{"start":{"line":266,"column":19},"end":{"line":266,"column":54}},"130":{"start":{"line":267,"column":2},"end":{"line":269,"column":null}},"131":{"start":{"line":268,"column":4},"end":{"line":268,"column":null}},"132":{"start":{"line":270,"column":14},"end":{"line":270,"column":58}},"133":{"start":{"line":271,"column":2},"end":{"line":273,"column":null}},"134":{"start":{"line":272,"column":4},"end":{"line":272,"column":null}},"135":{"start":{"line":274,"column":2},"end":{"line":274,"column":null}},"136":{"start":{"line":265,"column":0},"end":{"line":265,"column":16}},"137":{"start":{"line":278,"column":2},"end":{"line":278,"column":null}},"138":{"start":{"line":277,"column":0},"end":{"line":277,"column":16}},"139":{"start":{"line":281,"column":0},"end":{"line":281,"column":null}},"140":{"start":{"line":282,"column":2},"end":{"line":282,"column":null}},"141":{"start":{"line":283,"column":2},"end":{"line":283,"column":null}},"142":{"start":{"line":284,"column":2},"end":{"line":284,"column":null}},"143":{"start":{"line":285,"column":2},"end":{"line":285,"column":null}},"144":{"start":{"line":286,"column":2},"end":{"line":286,"column":null}},"145":{"start":{"line":287,"column":2},"end":{"line":287,"column":null}},"146":{"start":{"line":291,"column":17},"end":{"line":291,"column":27}},"147":{"start":{"line":292,"column":2},"end":{"line":294,"column":null}},"148":{"start":{"line":293,"column":4},"end":{"line":293,"column":null}},"149":{"start":{"line":295,"column":2},"end":{"line":295,"column":17}},"150":{"start":{"line":296,"column":2},"end":{"line":296,"column":null}},"151":{"start":{"line":300,"column":2},"end":{"line":300,"column":null}},"152":{"start":{"line":299,"column":0},"end":{"line":299,"column":16}}},"fnMap":{"0":{"name":"containerVolumes","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":32}},"loc":{"start":{"line":21,"column":25},"end":{"line":110,"column":1}}},"1":{"name":"writeEntryPointScript","decl":{"start":{"line":112,"column":16},"end":{"line":112,"column":37}},"loc":{"start":{"line":117,"column":50},"end":{"line":166,"column":1}}},"2":{"name":"generateContainerName","decl":{"start":{"line":168,"column":16},"end":{"line":168,"column":37}},"loc":{"start":{"line":168,"column":51},"end":{"line":177,"column":1}}},"3":{"name":"mergeContainerWithOptions","decl":{"start":{"line":187,"column":16},"end":{"line":187,"column":41}},"loc":{"start":{"line":189,"column":23},"end":{"line":213,"column":1}}},"4":{"name":"mergePodSpecWithOptions","decl":{"start":{"line":215,"column":16},"end":{"line":215,"column":39}},"loc":{"start":{"line":217,"column":21},"end":{"line":233,"column":1}}},"5":{"name":"(anonymous_11)","decl":{"start":{"line":223,"column":10},"end":{"line":223,"column":11}},"loc":{"start":{"line":223,"column":11},"end":{"line":223,"column":null}}},"6":{"name":"mergeObjectMeta","decl":{"start":{"line":235,"column":16},"end":{"line":235,"column":31}},"loc":{"start":{"line":237,"column":24},"end":{"line":263,"column":1}}},"7":{"name":"readExtensionFromFile","decl":{"start":{"line":265,"column":16},"end":{"line":265,"column":37}},"loc":{"start":{"line":265,"column":37},"end":{"line":275,"column":1}}},"8":{"name":"useKubeScheduler","decl":{"start":{"line":277,"column":16},"end":{"line":277,"column":32}},"loc":{"start":{"line":277,"column":32},"end":{"line":279,"column":1}}},"9":{"name":"(anonymous_15)","decl":{"start":{"line":281,"column":0},"end":{"line":281,"column":12}},"loc":{"start":{"line":281,"column":20},"end":{"line":288,"column":1}}},"10":{"name":"mergeLists","decl":{"start":{"line":290,"column":9},"end":{"line":290,"column":19}},"loc":{"start":{"line":290,"column":45},"end":{"line":297,"column":1}}},"11":{"name":"fixArgs","decl":{"start":{"line":299,"column":16},"end":{"line":299,"column":23}},"loc":{"start":{"line":299,"column":38},"end":{"line":301,"column":1}}}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":2},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":2},"end":{"line":19,"column":null}}]},"1":{"loc":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":20,"column":2},"end":{"line":20,"column":null}}]},"2":{"loc":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"type":"if","locations":[{"start":{"line":21,"column":2},"end":{"line":21,"column":null}}]},"3":{"loc":{"start":{"line":31,"column":2},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":31,"column":2},"end":{"line":57,"column":null}}]},"4":{"loc":{"start":{"line":59,"column":2},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":59,"column":2},"end":{"line":61,"column":null}}]},"5":{"loc":{"start":{"line":81,"column":2},"end":{"line":83,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":2},"end":{"line":83,"column":null}}]},"6":{"loc":{"start":{"line":81,"column":7},"end":{"line":81,"column":31}},"type":"cond-expr","locations":[{"start":{"line":81,"column":23},"end":{"line":81,"column":25}},{"start":{"line":81,"column":7},"end":{"line":81,"column":31}}]},"7":{"loc":{"start":{"line":81,"column":7},"end":{"line":81,"column":25}},"type":"binary-expr","locations":[{"start":{"line":81,"column":7},"end":{"line":81,"column":25}},{"start":{"line":81,"column":7},"end":{"line":81,"column":25}}]},"8":{"loc":{"start":{"line":87,"column":4},"end":{"line":99,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":4},"end":{"line":99,"column":null}},{"start":{"line":97,"column":11},"end":{"line":99,"column":null}}]},"9":{"loc":{"start":{"line":88,"column":6},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":6},"end":{"line":92,"column":null}}]},"10":{"loc":{"start":{"line":120,"column":2},"end":{"line":125,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":2},"end":{"line":125,"column":null}}]},"11":{"loc":{"start":{"line":120,"column":6},"end":{"line":120,"column":25}},"type":"cond-expr","locations":[{"start":{"line":120,"column":17},"end":{"line":120,"column":19}},{"start":{"line":120,"column":6},"end":{"line":120,"column":25}}]},"12":{"loc":{"start":{"line":120,"column":6},"end":{"line":120,"column":19}},"type":"binary-expr","locations":[{"start":{"line":120,"column":6},"end":{"line":120,"column":19}},{"start":{"line":120,"column":6},"end":{"line":120,"column":19}}]},"13":{"loc":{"start":{"line":123,"column":6},"end":{"line":123,"column":75}},"type":"cond-expr","locations":[{"start":{"line":123,"column":40},"end":{"line":123,"column":51}},{"start":{"line":123,"column":54},"end":{"line":123,"column":75}}]},"14":{"loc":{"start":{"line":128,"column":2},"end":{"line":150,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":2},"end":{"line":150,"column":null}}]},"15":{"loc":{"start":{"line":128,"column":6},"end":{"line":128,"column":73}},"type":"binary-expr","locations":[{"start":{"line":128,"column":6},"end":{"line":128,"column":26}},{"start":{"line":128,"column":30},"end":{"line":128,"column":73}}]},"16":{"loc":{"start":{"line":131,"column":6},"end":{"line":140,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":6},"end":{"line":140,"column":null}}]},"17":{"loc":{"start":{"line":132,"column":8},"end":{"line":135,"column":25}},"type":"binary-expr","locations":[{"start":{"line":132,"column":8},"end":{"line":132,"column":25}},{"start":{"line":133,"column":8},"end":{"line":133,"column":25}},{"start":{"line":134,"column":8},"end":{"line":134,"column":25}},{"start":{"line":135,"column":8},"end":{"line":135,"column":25}}]},"18":{"loc":{"start":{"line":156,"column":4},"end":{"line":156,"column":58}},"type":"cond-expr","locations":[{"start":{"line":156,"column":29},"end":{"line":156,"column":53}},{"start":{"line":156,"column":56},"end":{"line":156,"column":58}}]},"19":{"loc":{"start":{"line":156,"column":4},"end":{"line":156,"column":26}},"type":"cond-expr","locations":[{"start":{"line":156,"column":18},"end":{"line":156,"column":20}},{"start":{"line":156,"column":4},"end":{"line":156,"column":26}}]},"20":{"loc":{"start":{"line":156,"column":4},"end":{"line":156,"column":20}},"type":"binary-expr","locations":[{"start":{"line":156,"column":4},"end":{"line":156,"column":20}},{"start":{"line":156,"column":4},"end":{"line":156,"column":20}}]},"21":{"loc":{"start":{"line":170,"column":15},"end":{"line":170,"column":44}},"type":"cond-expr","locations":[{"start":{"line":170,"column":26},"end":{"line":170,"column":28}},{"start":{"line":170,"column":15},"end":{"line":170,"column":44}}]},"22":{"loc":{"start":{"line":170,"column":15},"end":{"line":170,"column":28}},"type":"binary-expr","locations":[{"start":{"line":170,"column":15},"end":{"line":170,"column":28}},{"start":{"line":170,"column":15},"end":{"line":170,"column":28}}]},"23":{"loc":{"start":{"line":172,"column":2},"end":{"line":174,"column":null}},"type":"if","locations":[{"start":{"line":172,"column":2},"end":{"line":174,"column":null}}]},"24":{"loc":{"start":{"line":192,"column":4},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":192,"column":4},"end":{"line":211,"column":null}},{"start":{"line":197,"column":11},"end":{"line":211,"column":null}}]},"25":{"loc":{"start":{"line":193,"column":6},"end":{"line":195,"column":null}},"type":"if","locations":[{"start":{"line":193,"column":6},"end":{"line":195,"column":null}}]},"26":{"loc":{"start":{"line":197,"column":11},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":197,"column":11},"end":{"line":211,"column":null}},{"start":{"line":200,"column":11},"end":{"line":211,"column":null}}]},"27":{"loc":{"start":{"line":200,"column":11},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":11},"end":{"line":211,"column":null}},{"start":{"line":203,"column":11},"end":{"line":211,"column":null}}]},"28":{"loc":{"start":{"line":203,"column":11},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":11},"end":{"line":211,"column":null}},{"start":{"line":206,"column":11},"end":{"line":211,"column":null}}]},"29":{"loc":{"start":{"line":203,"column":15},"end":{"line":203,"column":46}},"type":"binary-expr","locations":[{"start":{"line":203,"column":15},"end":{"line":203,"column":37}},{"start":{"line":203,"column":41},"end":{"line":203,"column":46}}]},"30":{"loc":{"start":{"line":206,"column":11},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":206,"column":11},"end":{"line":211,"column":null}},{"start":{"line":209,"column":11},"end":{"line":211,"column":null}}]},"31":{"loc":{"start":{"line":206,"column":15},"end":{"line":206,"column":39}},"type":"binary-expr","locations":[{"start":{"line":206,"column":15},"end":{"line":206,"column":30}},{"start":{"line":206,"column":34},"end":{"line":206,"column":39}}]},"32":{"loc":{"start":{"line":220,"column":4},"end":{"line":231,"column":null}},"type":"if","locations":[{"start":{"line":220,"column":4},"end":{"line":231,"column":null}},{"start":{"line":226,"column":11},"end":{"line":231,"column":null}}]},"33":{"loc":{"start":{"line":223,"column":16},"end":{"line":223,"column":62}},"type":"cond-expr","locations":[{"start":{"line":223,"column":22},"end":{"line":223,"column":24}},{"start":{"line":223,"column":22},"end":{"line":223,"column":62}}]},"34":{"loc":{"start":{"line":223,"column":16},"end":{"line":223,"column":24}},"type":"binary-expr","locations":[{"start":{"line":223,"column":16},"end":{"line":223,"column":24}},{"start":{"line":223,"column":22},"end":{"line":223,"column":24}}]},"35":{"loc":{"start":{"line":226,"column":11},"end":{"line":231,"column":null}},"type":"if","locations":[{"start":{"line":226,"column":11},"end":{"line":231,"column":null}},{"start":{"line":229,"column":11},"end":{"line":231,"column":null}}]},"36":{"loc":{"start":{"line":226,"column":15},"end":{"line":226,"column":41}},"type":"binary-expr","locations":[{"start":{"line":226,"column":15},"end":{"line":226,"column":32}},{"start":{"line":226,"column":36},"end":{"line":226,"column":41}}]},"37":{"loc":{"start":{"line":239,"column":2},"end":{"line":243,"column":null}},"type":"if","locations":[{"start":{"line":239,"column":2},"end":{"line":243,"column":null}}]},"38":{"loc":{"start":{"line":239,"column":6},"end":{"line":239,"column":61}},"type":"binary-expr","locations":[{"start":{"line":239,"column":6},"end":{"line":239,"column":32}},{"start":{"line":239,"column":32},"end":{"line":239,"column":61}}]},"39":{"loc":{"start":{"line":239,"column":7},"end":{"line":239,"column":28}},"type":"cond-expr","locations":[{"start":{"line":239,"column":20},"end":{"line":239,"column":22}},{"start":{"line":239,"column":20},"end":{"line":239,"column":28}}]},"40":{"loc":{"start":{"line":239,"column":7},"end":{"line":239,"column":22}},"type":"binary-expr","locations":[{"start":{"line":239,"column":7},"end":{"line":239,"column":22}},{"start":{"line":239,"column":20},"end":{"line":239,"column":22}}]},"41":{"loc":{"start":{"line":239,"column":33},"end":{"line":239,"column":59}},"type":"cond-expr","locations":[{"start":{"line":239,"column":46},"end":{"line":239,"column":48}},{"start":{"line":239,"column":46},"end":{"line":239,"column":59}}]},"42":{"loc":{"start":{"line":239,"column":33},"end":{"line":239,"column":48}},"type":"binary-expr","locations":[{"start":{"line":239,"column":33},"end":{"line":239,"column":48}},{"start":{"line":239,"column":46},"end":{"line":239,"column":48}}]},"43":{"loc":{"start":{"line":244,"column":2},"end":{"line":251,"column":null}},"type":"if","locations":[{"start":{"line":244,"column":2},"end":{"line":251,"column":null}}]},"44":{"loc":{"start":{"line":244,"column":6},"end":{"line":244,"column":18}},"type":"cond-expr","locations":[{"start":{"line":244,"column":10},"end":{"line":244,"column":12}},{"start":{"line":244,"column":6},"end":{"line":244,"column":18}}]},"45":{"loc":{"start":{"line":244,"column":6},"end":{"line":244,"column":12}},"type":"binary-expr","locations":[{"start":{"line":244,"column":6},"end":{"line":244,"column":12}},{"start":{"line":244,"column":6},"end":{"line":244,"column":12}}]},"46":{"loc":{"start":{"line":246,"column":6},"end":{"line":248,"column":null}},"type":"if","locations":[{"start":{"line":246,"column":6},"end":{"line":248,"column":null}}]},"47":{"loc":{"start":{"line":246,"column":10},"end":{"line":246,"column":38}},"type":"cond-expr","locations":[{"start":{"line":246,"column":31},"end":{"line":246,"column":34}},{"start":{"line":246,"column":31},"end":{"line":246,"column":38}}]},"48":{"loc":{"start":{"line":246,"column":10},"end":{"line":246,"column":34}},"type":"binary-expr","locations":[{"start":{"line":246,"column":10},"end":{"line":246,"column":34}},{"start":{"line":246,"column":31},"end":{"line":246,"column":34}}]},"49":{"loc":{"start":{"line":246,"column":10},"end":{"line":246,"column":31}},"type":"cond-expr","locations":[{"start":{"line":246,"column":23},"end":{"line":246,"column":25}},{"start":{"line":246,"column":23},"end":{"line":246,"column":31}}]},"50":{"loc":{"start":{"line":246,"column":10},"end":{"line":246,"column":25}},"type":"binary-expr","locations":[{"start":{"line":246,"column":10},"end":{"line":246,"column":25}},{"start":{"line":246,"column":23},"end":{"line":246,"column":25}}]},"51":{"loc":{"start":{"line":253,"column":2},"end":{"line":262,"column":null}},"type":"if","locations":[{"start":{"line":253,"column":2},"end":{"line":262,"column":null}}]},"52":{"loc":{"start":{"line":253,"column":6},"end":{"line":253,"column":23}},"type":"cond-expr","locations":[{"start":{"line":253,"column":10},"end":{"line":253,"column":12}},{"start":{"line":253,"column":6},"end":{"line":253,"column":23}}]},"53":{"loc":{"start":{"line":253,"column":6},"end":{"line":253,"column":12}},"type":"binary-expr","locations":[{"start":{"line":253,"column":6},"end":{"line":253,"column":12}},{"start":{"line":253,"column":6},"end":{"line":253,"column":12}}]},"54":{"loc":{"start":{"line":255,"column":6},"end":{"line":259,"column":null}},"type":"if","locations":[{"start":{"line":255,"column":6},"end":{"line":259,"column":null}}]},"55":{"loc":{"start":{"line":255,"column":10},"end":{"line":255,"column":43}},"type":"cond-expr","locations":[{"start":{"line":255,"column":36},"end":{"line":255,"column":39}},{"start":{"line":255,"column":36},"end":{"line":255,"column":43}}]},"56":{"loc":{"start":{"line":255,"column":10},"end":{"line":255,"column":39}},"type":"binary-expr","locations":[{"start":{"line":255,"column":10},"end":{"line":255,"column":39}},{"start":{"line":255,"column":36},"end":{"line":255,"column":39}}]},"57":{"loc":{"start":{"line":255,"column":10},"end":{"line":255,"column":36}},"type":"cond-expr","locations":[{"start":{"line":255,"column":23},"end":{"line":255,"column":25}},{"start":{"line":255,"column":23},"end":{"line":255,"column":36}}]},"58":{"loc":{"start":{"line":255,"column":10},"end":{"line":255,"column":25}},"type":"binary-expr","locations":[{"start":{"line":255,"column":10},"end":{"line":255,"column":25}},{"start":{"line":255,"column":23},"end":{"line":255,"column":25}}]},"59":{"loc":{"start":{"line":267,"column":2},"end":{"line":269,"column":null}},"type":"if","locations":[{"start":{"line":267,"column":2},"end":{"line":269,"column":null}}]},"60":{"loc":{"start":{"line":271,"column":2},"end":{"line":273,"column":null}},"type":"if","locations":[{"start":{"line":271,"column":2},"end":{"line":273,"column":null}}]},"61":{"loc":{"start":{"line":271,"column":6},"end":{"line":271,"column":37}},"type":"binary-expr","locations":[{"start":{"line":271,"column":6},"end":{"line":271,"column":10}},{"start":{"line":271,"column":14},"end":{"line":271,"column":37}}]},"62":{"loc":{"start":{"line":281,"column":12},"end":{"line":281,"column":null}},"type":"binary-expr","locations":[{"start":{"line":281,"column":12},"end":{"line":281,"column":20}},{"start":{"line":281,"column":12},"end":{"line":281,"column":null}}]},"63":{"loc":{"start":{"line":291,"column":17},"end":{"line":291,"column":27}},"type":"binary-expr","locations":[{"start":{"line":291,"column":17},"end":{"line":291,"column":21}},{"start":{"line":291,"column":25},"end":{"line":291,"column":27}}]},"64":{"loc":{"start":{"line":292,"column":2},"end":{"line":294,"column":null}},"type":"if","locations":[{"start":{"line":292,"column":2},"end":{"line":294,"column":null}}]},"65":{"loc":{"start":{"line":292,"column":7},"end":{"line":292,"column":19}},"type":"cond-expr","locations":[{"start":{"line":292,"column":11},"end":{"line":292,"column":13}},{"start":{"line":292,"column":7},"end":{"line":292,"column":19}}]},"66":{"loc":{"start":{"line":292,"column":7},"end":{"line":292,"column":13}},"type":"binary-expr","locations":[{"start":{"line":292,"column":7},"end":{"line":292,"column":13}},{"start":{"line":292,"column":7},"end":{"line":292,"column":13}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":6,"13":3,"14":6,"15":3,"16":3,"17":3,"18":0,"19":0,"20":0,"21":0,"22":3,"23":0,"24":3,"25":3,"26":3,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":1,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":1,"62":0,"63":0,"64":0,"65":0,"66":0,"67":1,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":1,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":1,"106":0,"107":0,"108":0,"109":0,"110":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"117":0,"118":0,"119":0,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":1,"129":3,"130":3,"131":3,"132":0,"133":0,"134":0,"135":0,"136":1,"137":0,"138":1,"139":1,"140":1,"141":1,"142":1,"143":1,"144":1,"145":1,"146":0,"147":0,"148":0,"149":0,"150":0,"151":3,"152":1},"f":{"0":3,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":3,"8":0,"9":1,"10":0,"11":3},"b":{"0":[3],"1":[0],"2":[3],"3":[0],"4":[0],"5":[3],"6":[0,3],"7":[3,3],"8":[0,0],"9":[0],"10":[0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0],"15":[0,0],"16":[0],"17":[0,0,0,0],"18":[0,0],"19":[0,0],"20":[0,0],"21":[0,0],"22":[0,0],"23":[0],"24":[0,0],"25":[0],"26":[0,0],"27":[0,0],"28":[0,0],"29":[0,0],"30":[0,0],"31":[0,0],"32":[0,0],"33":[0,0],"34":[0,0],"35":[0,0],"36":[0,0],"37":[0],"38":[0,0],"39":[0,0],"40":[0,0],"41":[0,0],"42":[0,0],"43":[0],"44":[0,0],"45":[0,0],"46":[0],"47":[0,0],"48":[0,0],"49":[0,0],"50":[0,0],"51":[0],"52":[0,0],"53":[0,0],"54":[0],"55":[0,0],"56":[0,0],"57":[0,0],"58":[0,0],"59":[3],"60":[0],"61":[0,0],"62":[1,1],"63":[0,0],"64":[0],"65":[0,0],"66":[0,0]}} +,"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/tests/test-setup.ts": {"path":"/__w/backlog/backlog/work/runner-container-hooks/packages/k8s/tests/test-setup.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":24}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":28}},"3":{"start":{"line":5,"column":0},"end":{"line":5,"column":35}},"4":{"start":{"line":7,"column":11},"end":{"line":7,"column":31}},"5":{"start":{"line":9,"column":0},"end":{"line":9,"column":null}},"6":{"start":{"line":11,"column":15},"end":{"line":11,"column":46}},"7":{"start":{"line":12,"column":22},"end":{"line":12,"column":56}},"8":{"start":{"line":14,"column":0},"end":{"line":14,"column":13}},"9":{"start":{"line":18,"column":4},"end":{"line":18,"column":null}},"10":{"start":{"line":19,"column":4},"end":{"line":19,"column":null}},"11":{"start":{"line":22,"column":15},"end":{"line":45,"column":null}},"12":{"start":{"line":23,"column":4},"end":{"line":23,"column":null}},"13":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"14":{"start":{"line":25,"column":4},"end":{"line":25,"column":null}},"15":{"start":{"line":26,"column":4},"end":{"line":26,"column":null}},"16":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"17":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"18":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"19":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"20":{"start":{"line":33,"column":4},"end":{"line":36,"column":null}},"21":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"22":{"start":{"line":40,"column":6},"end":{"line":40,"column":null}},"23":{"start":{"line":41,"column":6},"end":{"line":41,"column":null}},"24":{"start":{"line":43,"column":6},"end":{"line":43,"column":null}},"25":{"start":{"line":47,"column":15},"end":{"line":52,"column":null}},"26":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"27":{"start":{"line":50,"column":6},"end":{"line":50,"column":null}},"28":{"start":{"line":53,"column":15},"end":{"line":77,"column":null}},"29":{"start":{"line":54,"column":4},"end":{"line":62,"column":null}},"30":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"31":{"start":{"line":64,"column":4},"end":{"line":64,"column":null}},"32":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"33":{"start":{"line":68,"column":4},"end":{"line":76,"column":null}},"34":{"start":{"line":78,"column":9},"end":{"line":82,"column":null}},"35":{"start":{"line":79,"column":21},"end":{"line":79,"column":66}},"36":{"start":{"line":80,"column":4},"end":{"line":80,"column":null}},"37":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"38":{"start":{"line":84,"column":9},"end":{"line":87,"column":null}},"39":{"start":{"line":85,"column":21},"end":{"line":85,"column":54}},"40":{"start":{"line":86,"column":4},"end":{"line":86,"column":null}},"41":{"start":{"line":89,"column":15},"end":{"line":106,"column":null}},"42":{"start":{"line":90,"column":10},"end":{"line":94,"column":null}},"43":{"start":{"line":96,"column":10},"end":{"line":104,"column":null}},"44":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"45":{"start":{"line":108,"column":15},"end":{"line":152,"column":null}},"46":{"start":{"line":109,"column":8},"end":{"line":115,"column":null}},"47":{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},"48":{"start":{"line":118,"column":8},"end":{"line":133,"column":null}},"49":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"50":{"start":{"line":135,"column":8},"end":{"line":150,"column":null}},"51":{"start":{"line":151,"column":4},"end":{"line":151,"column":null}},"52":{"start":{"line":154,"column":9},"end":{"line":169,"column":null}},"53":{"start":{"line":155,"column":23},"end":{"line":159,"column":null}},"54":{"start":{"line":162,"column":4},"end":{"line":162,"column":null}},"55":{"start":{"line":163,"column":4},"end":{"line":163,"column":null}},"56":{"start":{"line":164,"column":4},"end":{"line":166,"column":null}},"57":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"58":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"59":{"start":{"line":171,"column":9},"end":{"line":181,"column":null}},"60":{"start":{"line":172,"column":26},"end":{"line":176,"column":null}},"61":{"start":{"line":179,"column":4},"end":{"line":179,"column":null}},"62":{"start":{"line":180,"column":4},"end":{"line":180,"column":null}},"63":{"start":{"line":183,"column":9},"end":{"line":195,"column":null}},"64":{"start":{"line":184,"column":29},"end":{"line":188,"column":null}},"65":{"start":{"line":191,"column":4},"end":{"line":191,"column":null}},"66":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"67":{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},"68":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"69":{"start":{"line":196,"column":0},"end":{"line":196,"column":null}},"70":{"start":{"line":14,"column":13},"end":{"line":14,"column":23}}},"fnMap":{"0":{"name":"(anonymous_19)","decl":{"start":{"line":14,"column":0},"end":{"line":14,"column":13}},"loc":{"start":{"line":14,"column":0},"end":{"line":196,"column":null}}},"1":{"name":"TestHelper","decl":{"start":{"line":17,"column":2},"end":{"line":17,"column":null}},"loc":{"start":{"line":17,"column":2},"end":{"line":20,"column":3}}},"2":{"name":"(anonymous_21)","decl":{"start":{"line":22,"column":2},"end":{"line":22,"column":15}},"loc":{"start":{"line":22,"column":2},"end":{"line":45,"column":null}}},"3":{"name":"(anonymous_24)","decl":{"start":{"line":47,"column":2},"end":{"line":47,"column":15}},"loc":{"start":{"line":47,"column":2},"end":{"line":52,"column":null}}},"4":{"name":"(anonymous_27)","decl":{"start":{"line":53,"column":2},"end":{"line":53,"column":15}},"loc":{"start":{"line":53,"column":2},"end":{"line":77,"column":null}}},"5":{"name":"(anonymous_30)","decl":{"start":{"line":62,"column":13},"end":{"line":62,"column":14}},"loc":{"start":{"line":62,"column":14},"end":{"line":62,"column":20}}},"6":{"name":"(anonymous_31)","decl":{"start":{"line":63,"column":68},"end":{"line":63,"column":69}},"loc":{"start":{"line":63,"column":69},"end":{"line":63,"column":75}}},"7":{"name":"(anonymous_32)","decl":{"start":{"line":64,"column":66},"end":{"line":64,"column":67}},"loc":{"start":{"line":64,"column":67},"end":{"line":64,"column":73}}},"8":{"name":"(anonymous_33)","decl":{"start":{"line":67,"column":13},"end":{"line":67,"column":14}},"loc":{"start":{"line":67,"column":14},"end":{"line":67,"column":20}}},"9":{"name":"(anonymous_34)","decl":{"start":{"line":76,"column":13},"end":{"line":76,"column":14}},"loc":{"start":{"line":76,"column":14},"end":{"line":76,"column":20}}},"10":{"name":"(anonymous_35)","decl":{"start":{"line":78,"column":2},"end":{"line":78,"column":9}},"loc":{"start":{"line":78,"column":37},"end":{"line":82,"column":3}}},"11":{"name":"(anonymous_36)","decl":{"start":{"line":84,"column":2},"end":{"line":84,"column":9}},"loc":{"start":{"line":84,"column":36},"end":{"line":87,"column":3}}},"12":{"name":"(anonymous_37)","decl":{"start":{"line":89,"column":2},"end":{"line":89,"column":15}},"loc":{"start":{"line":89,"column":2},"end":{"line":106,"column":null}}},"13":{"name":"(anonymous_40)","decl":{"start":{"line":108,"column":2},"end":{"line":108,"column":15}},"loc":{"start":{"line":108,"column":2},"end":{"line":152,"column":null}}},"14":{"name":"(anonymous_43)","decl":{"start":{"line":154,"column":2},"end":{"line":154,"column":9}},"loc":{"start":{"line":154,"column":2},"end":{"line":169,"column":3}}},"15":{"name":"(anonymous_44)","decl":{"start":{"line":164,"column":37},"end":{"line":164,"column":38}},"loc":{"start":{"line":164,"column":38},"end":{"line":166,"column":5}}},"16":{"name":"(anonymous_45)","decl":{"start":{"line":171,"column":2},"end":{"line":171,"column":9}},"loc":{"start":{"line":171,"column":2},"end":{"line":181,"column":3}}},"17":{"name":"(anonymous_46)","decl":{"start":{"line":183,"column":2},"end":{"line":183,"column":9}},"loc":{"start":{"line":183,"column":2},"end":{"line":195,"column":3}}}},"branchMap":{"0":{"loc":{"start":{"line":54,"column":4},"end":{"line":62,"column":null}},"type":"switch","locations":[{"start":{"line":54,"column":4},"end":{"line":62,"column":null}}]},"1":{"loc":{"start":{"line":79,"column":44},"end":{"line":79,"column":64}},"type":"binary-expr","locations":[{"start":{"line":79,"column":44},"end":{"line":79,"column":52}},{"start":{"line":79,"column":56},"end":{"line":79,"column":64}}]}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"8":1,"9":0,"10":0,"11":1,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":1,"26":0,"27":0,"28":1,"29":0,"30":0,"31":0,"32":0,"33":0,"34":1,"35":0,"36":0,"37":0,"38":1,"39":0,"40":0,"41":1,"42":0,"43":0,"44":0,"45":1,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":1,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":1,"60":0,"61":0,"62":0,"63":1,"64":0,"65":0,"66":0,"67":0,"68":0,"69":1,"70":1},"f":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0},"b":{"0":[0],"1":[0,0]}} +} diff --git a/packages/k8s/coverage/lcov-report/base.css b/packages/k8s/coverage/lcov-report/base.css new file mode 100644 index 00000000..f418035b --- /dev/null +++ b/packages/k8s/coverage/lcov-report/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/packages/k8s/coverage/lcov-report/block-navigation.js b/packages/k8s/coverage/lcov-report/block-navigation.js new file mode 100644 index 00000000..cc121302 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/packages/k8s/coverage/lcov-report/favicon.png b/packages/k8s/coverage/lcov-report/favicon.png new file mode 100644 index 00000000..66918178 Binary files /dev/null and b/packages/k8s/coverage/lcov-report/favicon.png differ diff --git a/packages/k8s/coverage/lcov-report/hooks/index.html b/packages/k8s/coverage/lcov-report/hooks/index.html new file mode 100644 index 00000000..91fbefed --- /dev/null +++ b/packages/k8s/coverage/lcov-report/hooks/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for hooks + + + + + + + + + +
+
+

All files hooks

+
+ +
+ 34.23% + Statements + 63/184 +
+ + +
+ 14.22% + Branches + 34/239 +
+ + +
+ 15.38% + Functions + 2/13 +
+ + +
+ 34.75% + Lines + 57/164 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
prepare-job.ts +
+
8.1%9/1110%0/1400%0/109.27%9/97
run-container-step.ts +
+
73.97%54/7334.34%34/9966.66%2/371.64%48/67
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/hooks/prepare-job.ts.html b/packages/k8s/coverage/lcov-report/hooks/prepare-job.ts.html new file mode 100644 index 00000000..713c0a8f --- /dev/null +++ b/packages/k8s/coverage/lcov-report/hooks/prepare-job.ts.html @@ -0,0 +1,886 @@ + + + + + + Code coverage report for hooks/prepare-job.ts + + + + + + + + + +
+
+

All files / hooks prepare-job.ts

+
+ +
+ 8.1% + Statements + 9/111 +
+ + +
+ 0% + Branches + 0/140 +
+ + +
+ 0% + Functions + 0/10 +
+ + +
+ 9.27% + Lines + 9/97 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +2681x +1x +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import * as core from '@actions/core'
+import * as io from '@actions/io'
+import * as k8s from '@kubernetes/client-node'
+import {
+  JobContainerInfo,
+  ContextPorts,
+  PrepareJobArgs,
+  writeToResponseFile
+} from 'hooklib'
+import path from 'path'
+import {
+  containerPorts,
+  createPod,
+  isPodContainerAlpine,
+  prunePods,
+  waitForPodPhases,
+  getPrepareJobTimeoutSeconds
+} from '../k8s'
+import {
+  containerVolumes,
+  DEFAULT_CONTAINER_ENTRY_POINT,
+  DEFAULT_CONTAINER_ENTRY_POINT_ARGS,
+  generateContainerName,
+  mergeContainerWithOptions,
+  readExtensionFromFile,
+  PodPhase,
+  fixArgs
+} from '../k8s/utils'
+import { CONTAINER_EXTENSION_PREFIX, JOB_CONTAINER_NAME } from './constants'
+ 
+export async function prepareJob(
+  args: PrepareJobArgs,
+  responseFile
+): Promise<void> {
+  Iif (!args.container) {
+    throw new Error('Job Container is required.')
+  }
+ 
+  await prunePods()
+ 
+  const extension = readExtensionFromFile()
+  await copyExternalsToRoot()
+ 
+  let container: k8s.V1Container | undefined = undefined
+  Iif (args.container?.image) {
+    core.debug(`Using image '${args.container.image}' for job image`)
+    container = createContainerSpec(
+      args.container,
+      JOB_CONTAINER_NAME,
+      true,
+      extension
+    )
+  }
+ 
+  let services: k8s.V1Container[] = []
+  Iif (args.services?.length) {
+    services = args.services.map(service => {
+      core.debug(`Adding service '${service.image}' to pod definition`)
+      return createContainerSpec(
+        service,
+        generateContainerName(service.image),
+        false,
+        extension
+      )
+    })
+  }
+ 
+  Iif (!container && !services?.length) {
+    throw new Error('No containers exist, skipping hook invocation')
+  }
+ 
+  let createdPod: k8s.V1Pod | undefined = undefined
+  try {
+    createdPod = await createPod(
+      container,
+      services,
+      args.container.registry,
+      extension
+    )
+  } catch (err) {
+    await prunePods()
+    core.debug(`createPod failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to create job pod: ${message}`)
+  }
+ 
+  Iif (!createdPod?.metadata?.name) {
+    throw new Error('created pod should have metadata.name')
+  }
+  core.debug(
+    `Job pod created, waiting for it to come online ${createdPod?.metadata?.name}`
+  )
+ 
+  try {
+    await waitForPodPhases(
+      createdPod.metadata.name,
+      new Set([PodPhase.RUNNING]),
+      new Set([PodPhase.PENDING]),
+      getPrepareJobTimeoutSeconds()
+    )
+  } catch (err) {
+    try {
+      await prunePods()
+    } catch (pruneErr) {
+      core.error(`Failed to prune pods: ${pruneErr instanceof Error ? pruneErr.message : String(pruneErr)}`)
+    }
+    const message = err instanceof Error ? err.message : String(err)
+    throw new Error(`pod failed to come online:\n${message}`)
+  }
+ 
+  core.debug('Job pod is ready for traffic')
+ 
+  let isAlpine = false
+  try {
+    isAlpine = await isPodContainerAlpine(
+      createdPod.metadata.name,
+      JOB_CONTAINER_NAME
+    )
+  } catch (err) {
+    core.debug(
+      `Failed to determine if the pod is alpine: ${JSON.stringify(err)}`
+    )
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to determine if the pod is alpine: ${message}`)
+  }
+  core.debug(`Setting isAlpine to ${isAlpine}`)
+  generateResponseFile(responseFile, args, createdPod, isAlpine)
+}
+ 
+function generateResponseFile(
+  responseFile: string,
+  args: PrepareJobArgs,
+  appPod: k8s.V1Pod,
+  isAlpine
+): void {
+  Iif (!appPod.metadata?.name) {
+    throw new Error('app pod must have metadata.name specified')
+  }
+  const response = {
+    state: {
+      jobPod: appPod.metadata.name
+    },
+    context: {},
+    isAlpine
+  }
+ 
+  const mainContainer = appPod.spec?.containers?.find(
+    c => c.name === JOB_CONTAINER_NAME
+  )
+  Iif (mainContainer) {
+    const mainContainerContextPorts: ContextPorts = {}
+    Iif (mainContainer?.ports) {
+      for (const port of mainContainer.ports) {
+        mainContainerContextPorts[port.containerPort] =
+          mainContainerContextPorts.hostPort
+      }
+    }
+ 
+    response.context['container'] = {
+      image: mainContainer.image,
+      ports: mainContainerContextPorts
+    }
+  }
+ 
+  Iif (args.services?.length) {
+    const serviceContainerNames =
+      args.services?.map(s => generateContainerName(s.image)) || []
+ 
+    response.context['services'] = appPod?.spec?.containers
+      ?.filter(c => serviceContainerNames.includes(c.name))
+      .map(c => {
+        const ctxPorts: ContextPorts = {}
+        Iif (c.ports?.length) {
+          for (const port of c.ports) {
+            ctxPorts[port.containerPort] = port.hostPort
+          }
+        }
+ 
+        return {
+          image: c.image,
+          ports: ctxPorts
+        }
+      })
+  }
+ 
+  writeToResponseFile(responseFile, JSON.stringify(response))
+}
+ 
+async function copyExternalsToRoot(): Promise<void> {
+  const workspace = process.env['RUNNER_WORKSPACE']
+  if (Iworkspace) {
+    await io.cp(
+      path.join(workspace, '../../externals'),
+      path.join(workspace, '../externals'),
+      { force: true, recursive: true, copySourceDirectory: false }
+    )
+  }
+}
+ 
+export function createContainerSpec(
+  container: JobContainerInfo,
+  name: string,
+  IjobContainer = false,
+  extension?: k8s.V1PodTemplateSpec
+): k8s.V1Container {
+  Iif (!container.entryPoint && jobContainer) {
+    container.entryPoint = DEFAULT_CONTAINER_ENTRY_POINT
+    container.entryPointArgs = DEFAULT_CONTAINER_ENTRY_POINT_ARGS
+  }
+ 
+  const podContainer = {
+    name,
+    image: container.image,
+    ports: containerPorts(container)
+  } as k8s.V1Container
+  Iif (container.workingDirectory) {
+    podContainer.workingDir = container.workingDirectory
+  }
+ 
+  Iif (container.entryPoint) {
+    podContainer.command = [container.entryPoint]
+  }
+ 
+  Iif (container.entryPointArgs?.length > 0) {
+    podContainer.args = fixArgs(container.entryPointArgs)
+  }
+ 
+  podContainer.env = []
+  for (const [key, value] of Object.entries(
+    container['environmentVariables']
+  )) {
+    Iif (value && key !== 'HOME') {
+      podContainer.env.push({ name: key, value: value as string })
+    }
+  }
+ 
+  podContainer.env.push({
+    name: 'GITHUB_ACTIONS',
+    value: 'true'
+  })
+ 
+  Iif (!('CI' in container['environmentVariables'])) {
+    podContainer.env.push({
+      name: 'CI',
+      value: 'true'
+    })
+  }
+ 
+  podContainer.volumeMounts = containerVolumes(
+    container.userMountVolumes,
+    jobContainer
+  )
+ 
+  Iif (!extension) {
+    return podContainer
+  }
+ 
+  const from = extension.spec?.containers?.find(
+    c => c.name === CONTAINER_EXTENSION_PREFIX + name
+  )
+ 
+  Iif (from) {
+    mergeContainerWithOptions(podContainer, from)
+  }
+ 
+  return podContainer
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/hooks/run-container-step.ts.html b/packages/k8s/coverage/lcov-report/hooks/run-container-step.ts.html new file mode 100644 index 00000000..66134a10 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/hooks/run-container-step.ts.html @@ -0,0 +1,592 @@ + + + + + + Code coverage report for hooks/run-container-step.ts + + + + + + + + + +
+
+

All files / hooks run-container-step.ts

+
+ +
+ 73.97% + Statements + 54/73 +
+ + +
+ 34.34% + Branches + 34/99 +
+ + +
+ 66.66% + Functions + 2/3 +
+ + +
+ 71.64% + Lines + 48/67 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +1701x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +1x +  +  +9x +  +  +  +9x +14x +  +4x +  +  +4x +4x +4x +  +4x +  +4x +4x +4x +  +  +  +5x +  +5x +5x +  +  +  +5x +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +  +  +5x +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +5x +  +10x +  +5x +10x +  +  +5x +5x +  +  +5x +  +  +  +  +  +  +  +  +5x +5x +5x +5x +5x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +5x +5x +5x +5x +  +  +5x +  +  +  +5x +  +  +  +  +  +  +  +  +  +5x +  +5x +5x +  +  +  +  +  +  +  +  +  +  +  + 
import * as core from '@actions/core'
+import * as k8s from '@kubernetes/client-node'
+import { RunContainerStepArgs } from 'hooklib'
+import {
+  createJob,
+  createSecretForEnvs,
+  describePodFailure,
+  getContainerJobPodName,
+  getContainerTerminatedErrors,
+  getPodByName,
+  getPodLogs,
+  getPodStatus,
+  waitForJobToComplete,
+  waitForPodPhases
+} from '../k8s'
+import {
+  containerVolumes,
+  fixArgs,
+  mergeContainerWithOptions,
+  PodPhase,
+  readExtensionFromFile
+} from '../k8s/utils'
+import { JOB_CONTAINER_EXTENSION_NAME, JOB_CONTAINER_NAME } from './constants'
+ 
+export async function runContainerStep(
+  stepContainer: RunContainerStepArgs
+): Promise<number> {
+  Iif (stepContainer.dockerfile) {
+    throw new Error('Building container actions is not currently supported')
+  }
+ 
+  let secretName: string | undefined = undefined
+  if (stepContainer.environmentVariables) {
+    try {
+      const envs = JSON.parse(
+        JSON.stringify(stepContainer.environmentVariables)
+      )
+      envs['GITHUB_ACTIONS'] = 'true'
+      if (!('CI' in envs)) {
+        envs.CI = 'true'
+      }
+      secretName = await createSecretForEnvs(envs)
+    } catch (err) {
+      core.debug(`createSecretForEnvs failed: ${JSON.stringify(err)}`)
+      const message = (err as any)?.response?.body?.message || err
+      throw new Error(`failed to create script environment: ${message}`)
+    }
+  }
+ 
+  const extension = readExtensionFromFile()
+ 
+  core.debug(`Created secret ${secretName} for container job envs`)
+  const container = createContainerSpec(stepContainer, secretName, extension)
+ 
+  let job: k8s.V1Job
+  try {
+    job = await createJob(container, extension)
+  } catch (err) {
+    core.debug(`createJob failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to run script step: ${message}`)
+  }
+ 
+  Iif (!job.metadata?.name) {
+    throw new Error(
+      `Expected job ${JSON.stringify(
+        job
+      )} to have correctly set the metadata.name`
+    )
+  }
+  core.debug(`Job created, waiting for pod to start: ${job.metadata?.name}`)
+ 
+  let podName: string
+  try {
+    podName = await getContainerJobPodName(job.metadata.name)
+  } catch (err) {
+    core.debug(`getContainerJobPodName failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to get container job pod name: ${message}`)
+  }
+ 
+  await waitForPodPhases(
+    podName,
+    new Set([
+      PodPhase.COMPLETED,
+      PodPhase.RUNNING,
+      PodPhase.SUCCEEDED,
+      PodPhase.FAILED
+    ]),
+    new Set([PodPhase.PENDING, PodPhase.UNKNOWN])
+  )
+  core.debug('Container step is running or complete, pulling logs')
+ 
+  await getPodLogs(podName, JOB_CONTAINER_NAME)
+ 
+  core.debug('Waiting for container job to complete')
+  await waitForJobToComplete(job.metadata.name)
+ 
+  // pod has failed so pull the status code from the container
+  const status = await getPodStatus(podName)
+  Iif (status?.phase === 'Succeeded') {
+    return 0
+  }
+  Iif (!status?.containerStatuses?.length) {
+    core.error(
+      `Can't determine container status from response:  ${JSON.stringify(
+        status
+      )}`
+    )
+    return 1
+  }
+ 
+  const pod = await getPodByName(podName)
+  const terminatedErrors = getContainerTerminatedErrors(pod)
+  if (IterminatedErrors.length > 0) {
+    const details = await describePodFailure(podName)
+    core.error(
+      `Pod ${podName} has unrecoverable container errors:\n${terminatedErrors.join('\n')}\n${details}`
+    )
+    return 1
+  }
+ 
+  const exitCode =
+    status.containerStatuses[status.containerStatuses.length - 1].state
+      ?.terminated?.exitCode
+  return Number(exitCode) || 1
+}
+ 
+function createContainerSpec(
+  container: RunContainerStepArgs,
+  secretName?: string,
+  extension?: k8s.V1PodTemplateSpec
+): k8s.V1Container {
+  const podContainer = new k8s.V1Container()
+  podContainer.name = JOB_CONTAINER_NAME
+  podContainer.image = container.image
+  podContainer.workingDir = container.workingDirectory
+  podContainer.command = container.entryPoint
+    ? [container.entryPoint]
+    : undefined
+  podContainer.args = container.entryPointArgs?.length
+    ? fixArgs(container.entryPointArgs)
+    : undefined
+ 
+  Iif (secretName) {
+    podContainer.envFrom = [
+      {
+        secretRef: {
+          name: secretName,
+          optional: false
+        }
+      }
+    ]
+  }
+  podContainer.volumeMounts = containerVolumes(undefined, false, true)
+ 
+  if (!extension) {
+    return podContainer
+  }
+ 
+  const from = extension.spec?.containers?.find(
+    c => c.name === JOB_CONTAINER_EXTENSION_NAME
+  )
+  Iif (from) {
+    mergeContainerWithOptions(podContainer, from)
+  }
+ 
+  return podContainer
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/index.html b/packages/k8s/coverage/lcov-report/index.html new file mode 100644 index 00000000..ea929c54 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 21.75% + Statements + 206/947 +
+ + +
+ 6.55% + Branches + 47/717 +
+ + +
+ 10.9% + Functions + 12/110 +
+ + +
+ 24.27% + Lines + 201/828 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src/hooks +
+
36.55%87/23812.89%33/25616%4/2538.24%83/217
src/k8s +
+
15.36%98/6383.05%14/45810.44%7/6718.11%98/541
tests +
+
29.57%21/710%0/35.55%1/1828.57%20/70
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/k8s/index.html b/packages/k8s/coverage/lcov-report/k8s/index.html new file mode 100644 index 00000000..790df482 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/k8s/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for k8s + + + + + + + + + +
+
+

All files k8s

+
+ +
+ 47.42% + Statements + 230/485 +
+ + +
+ 50.58% + Branches + 173/342 +
+ + +
+ 36.36% + Functions + 20/55 +
+ + +
+ 47.71% + Lines + 198/415 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
47.42%230/48550.58%173/34236.36%20/5547.71%198/415
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/k8s/index.ts.html b/packages/k8s/coverage/lcov-report/k8s/index.ts.html new file mode 100644 index 00000000..9250f7cf --- /dev/null +++ b/packages/k8s/coverage/lcov-report/k8s/index.ts.html @@ -0,0 +1,3028 @@ + + + + + + Code coverage report for k8s/index.ts + + + + + + + + + +
+
+

All files / k8s index.ts

+
+ +
+ 47.42% + Statements + 230/485 +
+ + +
+ 50.58% + Branches + 173/342 +
+ + +
+ 36.36% + Functions + 20/55 +
+ + +
+ 47.71% + Lines + 198/415 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +9822x +2x +  +2x +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +  +2x +  +2x +2x +2x +  +2x +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +4x +  +4x +4x +4x +4x +4x +4x +  +4x +  +  +4x +4x +12x +12x +  +  +8x +  +  +  +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +  +2x +  +2x +22x +22x +19x +  +3x +6x +6x +6x +3x +  +  +3x +  +  +2x +10x +10x +8x +  +2x +4x +4x +4x +1x +  +  +2x +  +  +2x +  +34x +34x +30x +  +4x +9x +9x +9x +4x +  +  +4x +  +  +2x +19x +19x +19x +  +  +  +38x +14x +14x +11x +  +  +  +  +  +  +19x +  +  +2x +7x +  +  +7x +  +  +  +  +  +  +6x +  +1x +  +  +  +  +1x +  +  +6x +7x +7x +  +  +  +  +5x +  +  +6x +  +  +2x +13x +13x +11x +4x +  +  +  +  +  +  +13x +  +  +2x +28x +28x +28x +  +  +  +56x +28x +28x +21x +  +  +  +  +  +  +28x +  +  +2x +  +  +8x +  +1x +  +  +  +  +7x +7x +  +7x +7x +  +  +  +  +  +7x +1x +  +  +7x +7x +  +7x +2x +2x +  +  +  +  +  +  +  +7x +  +  +  +7x +3x +3x +2x +  +  +  +  +  +3x +3x +1x +  +  +  +  +  +  +  +  +  +7x +  +7x +  +  +7x +  +  +  +  +  +7x +  +  +  +  +  +  +6x +  +1x +  +  +  +  +1x +  +  +6x +6x +5x +  +  +1x +  +  +  +1x +  +1x +1x +1x +1x +  +  +  +1x +  +  +  +  +1x +  +  +2x +  +  +  +16x +  +8x +8x +12x +12x +12x +12x +5x +  +  +13x +1x +1x +  +  +  +  +6x +11x +1x +1x +  +  +  +  +  +  +5x +9x +1x +1x +  +  +  +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +19x +  +  +2x +  +  +  +  +  +  +  +2x +19x +3x +  +16x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +38x +38x +  +  +  +  +  +  +  +  +  +  +  +2x +8x +8x +8x +8x +  +  +  +  +2x +8x +4x +  +4x +4x +  +  +4x +4x +  +4x +  +  +  +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  + 
import * as core from '@actions/core'
+import * as k8s from '@kubernetes/client-node'
+import { ContainerInfo, Registry } from 'hooklib'
+import * as stream from 'stream'
+import {
+  getJobPodName,
+  getRunnerPodName,
+  getSecretName,
+  getStepPodName,
+  getVolumeClaimName,
+  RunnerInstanceLabel
+} from '../hooks/constants'
+import {
+  PodPhase,
+  mergePodSpecWithOptions,
+  mergeObjectMeta,
+  useKubeScheduler,
+  fixArgs
+} from './utils'
+ 
+const kc = new k8s.KubeConfig()
+ 
+kc.loadFromDefault()
+ 
+const k8sApi = kc.makeApiClient(k8s.CoreV1Api)
+const k8sBatchV1Api = kc.makeApiClient(k8s.BatchV1Api)
+const k8sAuthorizationV1Api = kc.makeApiClient(k8s.AuthorizationV1Api)
+ 
+const DEFAULT_WAIT_FOR_POD_TIME_SECONDS = 10 * 60 // 10 min
+ 
+export const POD_VOLUME_NAME = 'work'
+ 
+export const requiredPermissions = [
+  {
+    group: '',
+    verbs: ['get', 'list', 'create', 'delete'],
+    resource: 'pods',
+    subresource: ''
+  },
+  {
+    group: '',
+    verbs: ['get', 'create'],
+    resource: 'pods',
+    subresource: 'exec'
+  },
+  {
+    group: '',
+    verbs: ['get', 'list', 'watch'],
+    resource: 'pods',
+    subresource: 'log'
+  },
+  {
+    group: 'batch',
+    verbs: ['get', 'list', 'create', 'delete'],
+    resource: 'jobs',
+    subresource: ''
+  },
+  {
+    group: '',
+    verbs: ['create', 'delete', 'get', 'list'],
+    resource: 'secrets',
+    subresource: ''
+  }
+]
+ 
+export async function createPod(
+  jobContainer?: k8s.V1Container,
+  services?: k8s.V1Container[],
+  registry?: Registry,
+  extension?: k8s.V1PodTemplateSpec
+): Promise<k8s.V1Pod> {
+  const containers: k8s.V1Container[] = []
+  Iif (jobContainer) {
+    containers.push(jobContainer)
+  }
+  Iif (services?.length) {
+    containers.push(...services)
+  }
+ 
+  const appPod = new k8s.V1Pod()
+ 
+  appPod.apiVersion = 'v1'
+  appPod.kind = 'Pod'
+ 
+  appPod.metadata = new k8s.V1ObjectMeta()
+  appPod.metadata.name = getJobPodName()
+ 
+  const instanceLabel = new RunnerInstanceLabel()
+  appPod.metadata.labels = {
+    [instanceLabel.key]: instanceLabel.value
+  }
+  appPod.metadata.annotations = {}
+ 
+  appPod.spec = new k8s.V1PodSpec()
+  appPod.spec.containers = containers
+  appPod.spec.restartPolicy = 'Never'
+ 
+  const nodeName = await getCurrentNodeName()
+  if (IuseKubeScheduler()) {
+    appPod.spec.affinity = await getPodAffinity(nodeName)
+  } else {
+    appPod.spec.affinity = await getPreferredPodAffinity(nodeName)
+  }
+  const claimName = getVolumeClaimName()
+  appPod.spec.volumes = [
+    {
+      name: 'work',
+      persistentVolumeClaim: { claimName }
+    }
+  ]
+ 
+  if (Iregistry) {
+    const secret = await createDockerSecret(registry)
+    Iif (!secret?.metadata?.name) {
+      throw new Error(`created secret does not have secret.metadata.name`)
+    }
+    const secretReference = new k8s.V1LocalObjectReference()
+    secretReference.name = secret.metadata.name
+    appPod.spec.imagePullSecrets = [secretReference]
+  }
+ 
+  Iif (extension?.metadata) {
+    mergeObjectMeta(appPod, extension.metadata)
+  }
+ 
+  Iif (extension?.spec) {
+    mergePodSpecWithOptions(appPod.spec, extension.spec)
+  }
+ 
+  const { body } = await k8sApi.createNamespacedPod(namespace(), appPod)
+  return body
+}
+ 
+export async function createJob(
+  container: k8s.V1Container,
+  extension?: k8s.V1PodTemplateSpec
+): Promise<k8s.V1Job> {
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const job = new k8s.V1Job()
+  job.apiVersion = 'batch/v1'
+  job.kind = 'Job'
+  job.metadata = new k8s.V1ObjectMeta()
+  job.metadata.name = getStepPodName()
+  job.metadata.labels = { [runnerInstanceLabel.key]: runnerInstanceLabel.value }
+  job.metadata.annotations = {}
+ 
+  job.spec = new k8s.V1JobSpec()
+  job.spec.ttlSecondsAfterFinished = 300
+  job.spec.backoffLimit = 0
+  job.spec.template = new k8s.V1PodTemplateSpec()
+ 
+  job.spec.template.spec = new k8s.V1PodSpec()
+  job.spec.template.metadata = new k8s.V1ObjectMeta()
+  job.spec.template.metadata.labels = {}
+  job.spec.template.metadata.annotations = {}
+  job.spec.template.spec.containers = [container]
+  job.spec.template.spec.restartPolicy = 'Never'
+ 
+  const nodeName = await getCurrentNodeName()
+  if (IuseKubeScheduler()) {
+    job.spec.template.spec.affinity = await getPodAffinity(nodeName)
+  } else {
+    job.spec.template.spec.affinity = await getPreferredPodAffinity(nodeName)
+  }
+ 
+  const claimName = getVolumeClaimName()
+  job.spec.template.spec.volumes = [
+    {
+      name: 'work',
+      persistentVolumeClaim: { claimName }
+    }
+  ]
+ 
+  Iif (extension) {
+    Iif (extension.metadata) {
+      // apply metadata both to the job and the pod created by the job
+      mergeObjectMeta(job, extension.metadata)
+      mergeObjectMeta(job.spec.template, extension.metadata)
+    }
+    Iif (extension.spec) {
+      mergePodSpecWithOptions(job.spec.template.spec, extension.spec)
+    }
+  }
+ 
+  const { body } = await k8sBatchV1Api.createNamespacedJob(namespace(), job)
+  return body
+}
+ 
+export async function getContainerJobPodName(jobName: string): Promise<string> {
+  const selector = `job-name=${jobName}`
+  const backOffManager = new BackOffManager(60)
+  while (Itrue) {
+    const podList = await k8sApi.listNamespacedPod(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      undefined,
+      selector,
+      1
+    )
+ 
+    if (I!podList.body.items?.length) {
+      await backOffManager.backOff()
+      continue
+    }
+ 
+    Iif (!podList.body.items[0].metadata?.name) {
+      throw new Error(
+        `Failed to determine the name of the pod for job ${jobName}`
+      )
+    }
+    return podList.body.items[0].metadata.name
+  }
+}
+ 
+export async function deletePod(podName: string): Promise<void> {
+  await k8sApi.deleteNamespacedPod(
+    podName,
+    namespace(),
+    undefined,
+    undefined,
+    0
+  )
+}
+ 
+export async function execPodStep(
+  command: string[],
+  podName: string,
+  containerName: string,
+  stdin?: stream.Readable
+): Promise<void> {
+  const exec = new k8s.Exec(kc)
+  command = fixArgs(command)
+  // Exec returns a websocket. If websocket fails, we should reject the promise. Otherwise, websocket will call a callback. Since at that point, websocket is not failing, we can safely resolve or reject the promise.
+  await new Promise(function (resolve, reject) {
+    exec
+      .exec(
+        namespace(),
+        podName,
+        containerName,
+        command,
+        process.stdout,
+        process.stderr,
+        stdin ?? null,
+        false /* tty */,
+        resp => {
+          // kube.exec returns an error if exit code is not 0, but we can't actually get the exit code
+          if (resp.status === 'Success') {
+            resolve(resp.code)
+          } else {
+            core.debug(
+              JSON.stringify({
+                message: resp?.message,
+                details: resp?.details
+              })
+            )
+            reject(resp?.message)
+          }
+        }
+      )
+      // If exec.exec fails, explicitly reject the outer promise
+      // eslint-disable-next-line github/no-then
+      .catch(e => reject(e))
+  })
+}
+ 
+export async function waitForJobToComplete(jobName: string): Promise<void> {
+  const backOffManager = new BackOffManager()
+  while (Itrue) {
+    try {
+      Iif (await isJobSucceeded(jobName)) {
+        return
+      }
+    } catch (error) {
+      throw new Error(`job ${jobName} has failed`)
+    }
+    await backOffManager.backOff()
+  }
+}
+ 
+export async function createDockerSecret(
+  registry: Registry
+): Promise<k8s.V1Secret> {
+  const authContent = {
+    auths: {
+      [registry.serverUrl || 'https://index.docker.io/v1/']: {
+        username: registry.username,
+        password: registry.password,
+        auth: Buffer.from(`${registry.username}:${registry.password}`).toString(
+          'base64'
+        )
+      }
+    }
+  }
+ 
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const secretName = getSecretName()
+  const secret = new k8s.V1Secret()
+  secret.immutable = true
+  secret.apiVersion = 'v1'
+  secret.metadata = new k8s.V1ObjectMeta()
+  secret.metadata.name = secretName
+  secret.metadata.namespace = namespace()
+  secret.metadata.labels = {
+    [runnerInstanceLabel.key]: runnerInstanceLabel.value
+  }
+  secret.type = 'kubernetes.io/dockerconfigjson'
+  secret.kind = 'Secret'
+  secret.data = {
+    '.dockerconfigjson': Buffer.from(JSON.stringify(authContent)).toString(
+      'base64'
+    )
+  }
+ 
+  const { body } = await k8sApi.createNamespacedSecret(namespace(), secret)
+  return body
+}
+ 
+export async function createSecretForEnvs(envs: {
+  [key: string]: string
+}): Promise<string> {
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const secret = new k8s.V1Secret()
+  const secretName = getSecretName()
+  secret.immutable = true
+  secret.apiVersion = 'v1'
+  secret.metadata = new k8s.V1ObjectMeta()
+  secret.metadata.name = secretName
+ 
+  secret.metadata.labels = {
+    [runnerInstanceLabel.key]: runnerInstanceLabel.value
+  }
+  secret.kind = 'Secret'
+  secret.data = {}
+  for (const [key, value] of Object.entries(envs)) {
+    secret.data[key] = Buffer.from(value).toString('base64')
+  }
+ 
+  await k8sApi.createNamespacedSecret(namespace(), secret)
+  return secretName
+}
+ 
+export async function deleteSecret(secretName: string): Promise<void> {
+  await k8sApi.deleteNamespacedSecret(secretName, namespace())
+}
+ 
+export async function pruneSecrets(): Promise<void> {
+  const secretList = await k8sApi.listNamespacedSecret(
+    namespace(),
+    undefined,
+    undefined,
+    undefined,
+    undefined,
+    new RunnerInstanceLabel().toString()
+  )
+  Iif (!secretList.body.items.length) {
+    return
+  }
+ 
+  await Promise.all(
+    secretList.body.items.map(
+      secret => secret.metadata?.name && deleteSecret(secret.metadata.name)
+    )
+  )
+}
+ 
+export const UNRECOVERABLE_WAITING_REASONS = new Set([
+  'ImagePullBackOff',
+  'ErrImagePull',
+  'InvalidImageName',
+  'CreateContainerConfigError',
+  'CreateContainerError'
+])
+ 
+export const UNRECOVERABLE_EVENT_REASONS = new Set([
+  'FailedScheduling',
+  'FailedBinding',
+  'FailedMount'
+])
+ 
+export const UNRECOVERABLE_TERMINATED_REASONS = new Set([
+  'OOMKilled',
+  'Error',
+  'FailedPostStartHookError'
+])
+ 
+const MAX_DIAGNOSTIC_EVENTS = 10
+ 
+export function getUnrecoverableWaitingReasons(): Set<string> {
+  const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS']
+  if (!extra) {
+    return UNRECOVERABLE_WAITING_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_WAITING_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    if (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getUnrecoverableEventReasons(): Set<string> {
+  const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS']
+  if (!extra) {
+    return UNRECOVERABLE_EVENT_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_EVENT_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    if (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getUnrecoverableTerminatedReasons(): Set<string> {
+  const extra =
+    process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS']
+  if (!extra) {
+    return UNRECOVERABLE_TERMINATED_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_TERMINATED_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    if (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getContainerErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  const unrecoverableReasons = getUnrecoverableWaitingReasons()
+  const allStatuses = [
+    ...(pod.status?.initContainerStatuses ?? []),
+    ...(pod.status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const waiting = cs.state?.waiting
+    if (waiting?.reason && unrecoverableReasons.has(waiting.reason)) {
+      errors.push(
+        `container "${cs.name}": ${waiting.reason}${
+          waiting.message ? ` - ${waiting.message}` : ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export async function getPodEventErrors(podName: string): Promise<string[]> {
+  const unrecoverableReasons = getUnrecoverableEventReasons()
+  let items: k8s.CoreV1Event[]
+  try {
+    const { body } = await k8sApi.listNamespacedEvent(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      `involvedObject.name=${podName}`
+    )
+    items = body.items
+  } catch (err) {
+    core.debug(
+      `Could not list events for pod ${podName} (the 'events' permission may be missing): ${
+        err instanceof Error ? err.message : String(err)
+      }`
+    )
+    return []
+  }
+ 
+  const errors: string[] = []
+  for (const e of items) {
+    if (
+      e.type === 'Warning' &&
+      e.reason &&
+      unrecoverableReasons.has(e.reason)
+    ) {
+      errors.push(`Event [Warning] ${e.reason}: ${e.message ?? ''}`)
+    }
+  }
+  return errors
+}
+ 
+export function getPodConditionErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  for (const cond of pod.status?.conditions ?? []) {
+    if (cond.type === 'PodScheduled' && cond.status === 'False' && cond.reason === 'Unschedulable') {
+      errors.push(
+        `Condition ${cond.type}=False (reason: ${cond.reason ?? ''}): ${
+          cond.message ?? ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export function getContainerTerminatedErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  const unrecoverableReasons = getUnrecoverableTerminatedReasons()
+  const allStatuses = [
+    ...(pod.status?.initContainerStatuses ?? []),
+    ...(pod.status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const terminated = cs.state?.terminated
+    if (terminated?.reason && unrecoverableReasons.has(terminated.reason)) {
+      errors.push(
+        `container "${cs.name}": ${terminated.reason} (exit code ${terminated.exitCode}) - ${
+          terminated.message ?? ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export async function describePodFailure(podName: string): Promise<string> {
+  let pod: k8s.V1Pod
+  try {
+    pod = await readPod(podName)
+  } catch (err) {
+    return `Could not read pod ${podName} for diagnostics: ${
+      err instanceof Error ? err.message : String(err)
+    }`
+  }
+ 
+  const lines: string[] = []
+  const status = pod.status
+ 
+  if (status?.phase) {
+    lines.push(
+      `Phase: ${status.phase}${
+        status.reason ? ` (reason: ${status.reason})` : ''
+      }`
+    )
+  }
+  if (status?.message) {
+    lines.push(`Message: ${status.message}`)
+  }
+ 
+  const separator = '────────────────────────────────────────────────────────────'
+  lines.push(separator)
+ 
+  for (const cond of status?.conditions ?? []) {
+    if (cond.status === 'False') {
+      lines.push(
+        `  ✗ ${cond.type}=False${
+          cond.reason ? ` (${cond.reason})` : ''
+        }${cond.message ? `: ${cond.message}` : ''}`
+      )
+    }
+  }
+ 
+  const allStatuses = [
+    ...(status?.initContainerStatuses ?? []),
+    ...(status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const waiting = cs.state?.waiting
+    if (waiting?.reason) {
+      lines.push(
+        `  ✗ container "${cs.name}": ${waiting.reason}${
+          waiting.message ? `\n    ${waiting.message}` : ''
+        }`
+      )
+    }
+    const terminated = cs.state?.terminated
+    if (terminated) {
+      lines.push(
+        `  ✗ container "${cs.name}": ${
+          terminated.reason ?? 'Unknown'
+        } (exit code ${terminated.exitCode})${
+          terminated.message ? `\n    ${terminated.message}` : ''
+        }`
+      )
+    }
+  }
+ 
+  lines.push(...(await describePodWarningEvents(podName)))
+ 
+  Iif (!lines.length) {
+    return `No additional diagnostic information available for pod ${podName}`
+  }
+  return lines.join('\n')
+}
+ 
+async function describePodWarningEvents(podName: string): Promise<string[]> {
+  let items: k8s.CoreV1Event[]
+  try {
+    const { body } = await k8sApi.listNamespacedEvent(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      `involvedObject.name=${podName}`
+    )
+    items = body.items
+  } catch (err) {
+    core.debug(
+      `Could not list events for pod ${podName} (the 'events' permission may be missing): ${
+        err instanceof Error ? err.message : String(err)
+      }`
+    )
+    return []
+  }
+ 
+  const warnings = items.filter(e => e.type === 'Warning')
+  if (!warnings.length) {
+    return []
+  }
+ 
+  const eventTime = (e: k8s.CoreV1Event): number => {
+    const t = e.lastTimestamp ?? e.eventTime ?? e.firstTimestamp
+    return t ? new Date(t).getTime() : 0
+  }
+  warnings.sort((a, b) => eventTime(a) - eventTime(b))
+ 
+  const recent = warnings.slice(-MAX_DIAGNOSTIC_EVENTS)
+  const lines = recent.map(e => {
+    const count = e.count && e.count > 1 ? ` (x${e.count})` : ''
+    return `Event [Warning] ${e.reason ?? ''}${count}: ${
+      e.message ?? ''
+    }`.trim()
+  })
+  Iif (warnings.length > recent.length) {
+    lines.unshift(
+      `(showing ${recent.length} of ${warnings.length} warning events)`
+    )
+  }
+  return lines
+}
+ 
+export async function waitForPodPhases(
+  podName: string,
+  awaitingPhases: Set<PodPhase>,
+  backOffPhases: Set<PodPhase>,
+  maxTimeSeconds = DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+): Promise<void> {
+  const backOffManager = new BackOffManager(maxTimeSeconds)
+  let phase: PodPhase = PodPhase.UNKNOWN
+  while (Itrue) {
+    const pod = await readPod(podName)
+    phase = parsePodPhase(pod)
+    if (awaitingPhases.has(phase)) {
+      return
+    }
+ 
+    if (!backOffPhases.has(phase)) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} is unhealthy with phase status ${phase}\n${details}`
+      )
+    }
+ 
+    const containerErrors = getContainerErrors(pod)
+    if (containerErrors.length > 0) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} has unrecoverable container errors: ${containerErrors.join(
+          '; '
+        )}\n${details}`
+      )
+    }
+ 
+    const conditionErrors = getPodConditionErrors(pod)
+    if (conditionErrors.length > 0) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} has unrecoverable condition errors: ${conditionErrors.join(
+          '; '
+        )}\n${details}`
+      )
+    }
+ 
+    try {
+      await backOffManager.backOff()
+    } catch (error) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} is unhealthy: timed out after ${maxTimeSeconds}s in phase ${phase}\n${details}`
+      )
+    }
+  }
+}
+ 
+export function getPrepareJobTimeoutSeconds(): number {
+  const envTimeoutSeconds =
+    process.env['ACTIONS_RUNNER_PREPARE_JOB_TIMEOUT_SECONDS']
+ 
+  Iif (!envTimeoutSeconds) {
+    return DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+  }
+ 
+  const timeoutSeconds = parseInt(envTimeoutSeconds, 10)
+  Iif (!timeoutSeconds || timeoutSeconds <= 0) {
+    core.warning(
+      `Prepare job timeout is invalid ("${timeoutSeconds}"): use an int > 0`
+    )
+    return DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+  }
+ 
+  return timeoutSeconds
+}
+ 
+async function readPod(podName: string): Promise<k8s.V1Pod> {
+  const { body } = await k8sApi.readNamespacedPod(podName, namespace())
+  return body
+}
+ 
+const podPhaseLookup = new Set<string>([
+  PodPhase.PENDING,
+  PodPhase.RUNNING,
+  PodPhase.SUCCEEDED,
+  PodPhase.FAILED,
+  PodPhase.UNKNOWN
+])
+ 
+export function parsePodPhase(pod: k8s.V1Pod): PodPhase {
+  if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) {
+    return PodPhase.UNKNOWN
+  }
+  return pod.status.phase as PodPhase
+}
+ 
+async function isJobSucceeded(jobName: string): Promise<boolean> {
+  const { body } = await k8sBatchV1Api.readNamespacedJob(jobName, namespace())
+  const job = body
+  Iif (job.status?.failed) {
+    throw new Error(`job ${jobName} has failed`)
+  }
+  return !!job.status?.succeeded
+}
+ 
+export async function getPodLogs(
+  podName: string,
+  containerName: string
+): Promise<void> {
+  const log = new k8s.Log(kc)
+  const logStream = new stream.PassThrough()
+  logStream.on('data', chunk => {
+    // use write rather than console.log to prevent double line feed
+    process.stdout.write(chunk)
+  })
+ 
+  logStream.on('error', err => {
+    process.stderr.write(err.message)
+  })
+ 
+  const r = await log.log(namespace(), podName, containerName, logStream, {
+    follow: true,
+    pretty: false,
+    timestamps: false
+  })
+  await new Promise(resolve => r.on('close', () => resolve(null)))
+}
+ 
+export async function prunePods(): Promise<void> {
+  const podList = await k8sApi.listNamespacedPod(
+    namespace(),
+    undefined,
+    undefined,
+    undefined,
+    undefined,
+    new RunnerInstanceLabel().toString()
+  )
+  Iif (!podList.body.items.length) {
+    return
+  }
+ 
+  await Promise.all(
+    podList.body.items.map(
+      pod => pod.metadata?.name && deletePod(pod.metadata.name)
+    )
+  )
+}
+ 
+export async function getPodStatus(
+  name: string
+): Promise<k8s.V1PodStatus | undefined> {
+  const { body } = await k8sApi.readNamespacedPod(name, namespace())
+  return body.status
+}
+ 
+export async function isAuthPermissionsOK(): Promise<boolean> {
+  const sar = new k8s.V1SelfSubjectAccessReview()
+  const asyncs: Promise<{
+    response: unknown
+    body: k8s.V1SelfSubjectAccessReview
+  }>[] = []
+  for (const resource of requiredPermissions) {
+    for (const verb of resource.verbs) {
+      sar.spec = new k8s.V1SelfSubjectAccessReviewSpec()
+      sar.spec.resourceAttributes = new k8s.V1ResourceAttributes()
+      sar.spec.resourceAttributes.verb = verb
+      sar.spec.resourceAttributes.namespace = namespace()
+      sar.spec.resourceAttributes.group = resource.group
+      sar.spec.resourceAttributes.resource = resource.resource
+      sar.spec.resourceAttributes.subresource = resource.subresource
+      asyncs.push(k8sAuthorizationV1Api.createSelfSubjectAccessReview(sar))
+    }
+  }
+  const responses = await Promise.all(asyncs)
+  return responses.every(resp => resp.body.status?.allowed)
+}
+ 
+export async function isPodContainerAlpine(
+  podName: string,
+  containerName: string
+): Promise<boolean> {
+  let isAlpine = true
+  try {
+    await execPodStep(
+      [
+        'sh',
+        '-c',
+        `'[ $(cat /etc/*release* | grep -i -e "^ID=*alpine*" -c) != 0 ] || exit 1'`
+      ],
+      podName,
+      containerName
+    )
+  } catch (err) {
+    isAlpine = false
+  }
+ 
+  return isAlpine
+}
+ 
+async function getCurrentNodeName(): Promise<string> {
+  const resp = await k8sApi.readNamespacedPod(getRunnerPodName(), namespace())
+ 
+  const nodeName = resp.body.spec?.nodeName
+  Iif (!nodeName) {
+    throw new Error('Failed to determine node name')
+  }
+  return nodeName
+}
+ 
+async function getPodAffinity(nodeName: string): Promise<k8s.V1Affinity> {
+  const affinity = new k8s.V1Affinity()
+  affinity.nodeAffinity = new k8s.V1NodeAffinity()
+  affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution =
+    new k8s.V1NodeSelector()
+  affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms =
+    [
+      {
+        matchExpressions: [
+          {
+            key: 'kubernetes.io/hostname',
+            operator: 'In',
+            values: [nodeName]
+          }
+        ]
+      }
+    ]
+  return affinity
+}
+ 
+async function getPreferredPodAffinity(
+  nodeName: string
+): Promise<k8s.V1Affinity> {
+  const affinity = new k8s.V1Affinity()
+  affinity.nodeAffinity = new k8s.V1NodeAffinity()
+ 
+  // 创建 PreferredSchedulingTerm 对象
+  const preferredTerm = new k8s.V1PreferredSchedulingTerm()
+  preferredTerm.weight = 1 // 设置权重(1-100)
+ 
+  // 创建 NodeSelectorTerm
+  preferredTerm.preference = new k8s.V1NodeSelectorTerm()
+  preferredTerm.preference.matchExpressions = [
+    {
+      key: 'kubernetes.io/hostname',
+      operator: 'In',
+      values: [nodeName]
+    }
+  ]
+ 
+  // 将 PreferredSchedulingTerm 添加到数组中
+  affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution = [
+    preferredTerm
+  ]
+ 
+  return affinity
+}
+ 
+export function namespace(): string {
+  if (process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE']) {
+    return process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE']
+  }
+ 
+  const context = kc.getContexts().find(ctx => ctx.namespace)
+  Iif (!context?.namespace) {
+    throw new Error(
+      'Failed to determine namespace, falling back to `default`. Namespace should be set in context, or in env variable "ACTIONS_RUNNER_KUBERNETES_NAMESPACE"'
+    )
+  }
+  return context.namespace
+}
+ 
+class BackOffManager {
+  private backOffSeconds = 1
+  totalTime = 0
+  constructor(private throwAfterSeconds?: number) {
+    Iif (!throwAfterSeconds || throwAfterSeconds < 0) {
+      this.throwAfterSeconds = undefined
+    }
+  }
+ 
+  async backOff(): Promise<void> {
+    await new Promise(resolve =>
+      setTimeout(resolve, this.backOffSeconds * 1000)
+    )
+    this.totalTime += this.backOffSeconds
+    Iif (this.throwAfterSeconds && this.throwAfterSeconds < this.totalTime) {
+      throw new Error('backoff timeout')
+    }
+    if (this.backOffSeconds < 20) {
+      this.backOffSeconds *= 2
+    }
+    Iif (this.backOffSeconds > 20) {
+      this.backOffSeconds = 20
+    }
+  }
+}
+ 
+export function containerPorts(
+  container: ContainerInfo
+): k8s.V1ContainerPort[] {
+  const ports: k8s.V1ContainerPort[] = []
+  Iif (!container.portMappings?.length) {
+    return ports
+  }
+  for (const portDefinition of container.portMappings) {
+    const portProtoSplit = portDefinition.split('/')
+    Iif (portProtoSplit.length > 2) {
+      throw new Error(`Unexpected port format: ${portDefinition}`)
+    }
+ 
+    const port = new k8s.V1ContainerPort()
+    port.protocol =
+      portProtoSplit.length === 2 ? portProtoSplit[1].toUpperCase() : 'TCP'
+ 
+    const portSplit = portProtoSplit[0].split(':')
+    Iif (portSplit.length > 2) {
+      throw new Error('ports should have at most one ":" separator')
+    }
+ 
+    const parsePort = (p: string): number => {
+      const num = Number(p)
+      Iif (!Number.isInteger(num) || num < 1 || num > 65535) {
+        throw new Error(`invalid container port: ${p}`)
+      }
+      return num
+    }
+ 
+    if (portSplit.length === 1) {
+      port.containerPort = parsePort(portSplit[0])
+    } else {
+      port.hostPort = parsePort(portSplit[0])
+      port.containerPort = parsePort(portSplit[1])
+    }
+ 
+    ports.push(port)
+  }
+  return ports
+}
+ 
+export async function getPodByName(name): Promise<k8s.V1Pod> {
+  const { body } = await k8sApi.readNamespacedPod(name, namespace())
+  return body
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/prettify.css b/packages/k8s/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/packages/k8s/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/packages/k8s/coverage/lcov-report/prettify.js b/packages/k8s/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..b3225238 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/packages/k8s/coverage/lcov-report/sort-arrow-sprite.png b/packages/k8s/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 00000000..03f704a6 Binary files /dev/null and b/packages/k8s/coverage/lcov-report/sort-arrow-sprite.png differ diff --git a/packages/k8s/coverage/lcov-report/sorter.js b/packages/k8s/coverage/lcov-report/sorter.js new file mode 100644 index 00000000..2bb296a8 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/packages/k8s/coverage/lcov-report/src/hooks/cleanup-job.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/cleanup-job.ts.html new file mode 100644 index 00000000..584c5eb1 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/cleanup-job.ts.html @@ -0,0 +1,100 @@ + + + + + + Code coverage report for src/hooks/cleanup-job.ts + + + + + + + + + +
+
+

All files / src/hooks cleanup-job.ts

+
+ +
+ 66.66% + Statements + 2/3 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 66.66% + Lines + 2/3 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +61x +  +1x +  +  + 
import { prunePods, pruneSecrets } from '../k8s'
+ 
+export async function cleanupJob(): Promise<void> {
+  await Promise.all([prunePods(), pruneSecrets()])
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/constants.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/constants.ts.html new file mode 100644 index 00000000..76ab4987 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/constants.ts.html @@ -0,0 +1,280 @@ + + + + + + Code coverage report for src/hooks/constants.ts + + + + + + + + + +
+
+

All files / src/hooks constants.ts

+
+ +
+ 53.12% + Statements + 17/32 +
+ + +
+ 0% + Branches + 0/2 +
+ + +
+ 10% + Functions + 1/10 +
+ + +
+ 51.61% + Lines + 16/31 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +661x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +1x +  +  +  +1x +  +  +  +1x +  +  +1x + 
import { v4 as uuidv4 } from 'uuid'
+ 
+export function getRunnerPodName(): string {
+  const name = process.env.ACTIONS_RUNNER_POD_NAME
+  Iif (!name) {
+    throw new Error(
+      "'ACTIONS_RUNNER_POD_NAME' env is required, please contact your self hosted runner administrator"
+    )
+  }
+  return name
+}
+ 
+export function getJobPodName(): string {
+  return `${getRunnerPodName().substring(
+    0,
+    MAX_POD_NAME_LENGTH - '-workflow'.length
+  )}-workflow`
+}
+ 
+export function getStepPodName(): string {
+  return `${getRunnerPodName().substring(
+    0,
+    MAX_POD_NAME_LENGTH - ('-step-'.length + STEP_POD_NAME_SUFFIX_LENGTH)
+  )}-step-${uuidv4().substring(0, STEP_POD_NAME_SUFFIX_LENGTH)}`
+}
+ 
+export function getVolumeClaimName(): string {
+  const name = process.env.ACTIONS_RUNNER_CLAIM_NAME
+  Iif (!name) {
+    return `${getRunnerPodName()}-work`
+  }
+  return name
+}
+ 
+export function getSecretName(): string {
+  return `${getRunnerPodName().substring(
+    0,
+    MAX_POD_NAME_LENGTH - ('-secret-'.length + STEP_POD_NAME_SUFFIX_LENGTH)
+  )}-secret-${uuidv4().substring(0, STEP_POD_NAME_SUFFIX_LENGTH)}`
+}
+ 
+export const MAX_POD_NAME_LENGTH = 63
+export const STEP_POD_NAME_SUFFIX_LENGTH = 8
+export const CONTAINER_EXTENSION_PREFIX = '$'
+export const JOB_CONTAINER_NAME = 'job'
+export const JOB_CONTAINER_EXTENSION_NAME = '$job'
+ 
+export class RunnerInstanceLabel {
+  private podName: string
+  constructor() {
+    this.podName = getRunnerPodName()
+  }
+ 
+  get key(): string {
+    return 'runner-pod'
+  }
+ 
+  get value(): string {
+    return this.podName
+  }
+ 
+  toString(): string {
+    return `runner-pod=${this.podName}`
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/index.html b/packages/k8s/coverage/lcov-report/src/hooks/index.html new file mode 100644 index 00000000..e597c42c --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/index.html @@ -0,0 +1,191 @@ + + + + + + Code coverage report for src/hooks + + + + + + + + + +
+
+

All files src/hooks

+
+ +
+ 36.55% + Statements + 87/238 +
+ + +
+ 12.89% + Branches + 33/256 +
+ + +
+ 16% + Functions + 4/25 +
+ + +
+ 38.24% + Lines + 83/217 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
cleanup-job.ts +
+
66.66%2/30%0/10%0/166.66%2/3
constants.ts +
+
53.12%17/320%0/210%1/1051.61%16/31
index.ts +
+
100%4/4100%0/0100%0/0100%4/4
prepare-job.ts +
+
46.84%52/11123.57%33/14030%3/1050.51%49/97
run-container-step.ts +
+
8.21%6/730%0/990%0/38.95%6/67
run-script-step.ts +
+
40%6/150%0/140%0/140%6/15
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/index.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/index.ts.html new file mode 100644 index 00000000..5df4c176 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/index.ts.html @@ -0,0 +1,97 @@ + + + + + + Code coverage report for src/hooks/index.ts + + + + + + + + + +
+
+

All files / src/hooks index.ts

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +51x +1x +1x +1x + 
export * from './cleanup-job'
+export * from './prepare-job'
+export * from './run-script-step'
+export * from './run-container-step'
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/prepare-job.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/prepare-job.ts.html new file mode 100644 index 00000000..695c5ea5 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/prepare-job.ts.html @@ -0,0 +1,886 @@ + + + + + + Code coverage report for src/hooks/prepare-job.ts + + + + + + + + + +
+
+

All files / src/hooks prepare-job.ts

+
+ +
+ 46.84% + Statements + 52/111 +
+ + +
+ 23.57% + Branches + 33/140 +
+ + +
+ 30% + Functions + 3/10 +
+ + +
+ 50.51% + Lines + 49/97 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +2681x +1x +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +3x +  +  +  +6x +  +3x +6x +  +3x +3x +3x +3x +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +3x +  +  +  +  +6x +  +  +  +  +  +  +  +6x +  +2x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +6x +  +  +  +  +  +  +  +  +1x +  +  +3x +  +  +3x +3x +3x +  +  +3x +  +  +  +  +3x +  +  +  +3x +3x +  +  +3x +3x +  +  +3x +3x +  +  +  +  +  +  +  +3x +  +  +  +  +3x +3x +  +  +  +  +  +3x +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  + 
import * as core from '@actions/core'
+import * as io from '@actions/io'
+import * as k8s from '@kubernetes/client-node'
+import {
+  JobContainerInfo,
+  ContextPorts,
+  PrepareJobArgs,
+  writeToResponseFile
+} from 'hooklib'
+import path from 'path'
+import {
+  containerPorts,
+  createPod,
+  isPodContainerAlpine,
+  prunePods,
+  waitForPodPhases,
+  getPrepareJobTimeoutSeconds
+} from '../k8s'
+import {
+  containerVolumes,
+  DEFAULT_CONTAINER_ENTRY_POINT,
+  DEFAULT_CONTAINER_ENTRY_POINT_ARGS,
+  generateContainerName,
+  mergeContainerWithOptions,
+  readExtensionFromFile,
+  PodPhase,
+  fixArgs
+} from '../k8s/utils'
+import { CONTAINER_EXTENSION_PREFIX, JOB_CONTAINER_NAME } from './constants'
+ 
+export async function prepareJob(
+  args: PrepareJobArgs,
+  responseFile
+): Promise<void> {
+  Iif (!args.container) {
+    throw new Error('Job Container is required.')
+  }
+ 
+  await prunePods()
+ 
+  const extension = readExtensionFromFile()
+  await copyExternalsToRoot()
+ 
+  let container: k8s.V1Container | undefined = undefined
+  if (args.container?.image) {
+    core.debug(`Using image '${args.container.image}' for job image`)
+    container = createContainerSpec(
+      args.container,
+      JOB_CONTAINER_NAME,
+      true,
+      extension
+    )
+  }
+ 
+  let services: k8s.V1Container[] = []
+  Iif (args.services?.length) {
+    services = args.services.map(service => {
+      core.debug(`Adding service '${service.image}' to pod definition`)
+      return createContainerSpec(
+        service,
+        generateContainerName(service.image),
+        false,
+        extension
+      )
+    })
+  }
+ 
+  Iif (!container && !services?.length) {
+    throw new Error('No containers exist, skipping hook invocation')
+  }
+ 
+  let createdPod: k8s.V1Pod | undefined = undefined
+  try {
+    createdPod = await createPod(
+      container,
+      services,
+      args.container.registry,
+      extension
+    )
+  } catch (err) {
+    await prunePods()
+    core.debug(`createPod failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to create job pod: ${message}`)
+  }
+ 
+  Iif (!createdPod?.metadata?.name) {
+    throw new Error('created pod should have metadata.name')
+  }
+  core.debug(
+    `Job pod created, waiting for it to come online ${createdPod?.metadata?.name}`
+  )
+ 
+  try {
+    await waitForPodPhases(
+      createdPod.metadata.name,
+      new Set([PodPhase.RUNNING]),
+      new Set([PodPhase.PENDING]),
+      getPrepareJobTimeoutSeconds()
+    )
+  } catch (err) {
+    try {
+      await prunePods()
+    } catch (pruneErr) {
+      core.error(`Failed to prune pods: ${pruneErr instanceof Error ? pruneErr.message : String(pruneErr)}`)
+    }
+    const message = err instanceof Error ? err.message : String(err)
+    throw new Error(`pod failed to come online:\n${message}`)
+  }
+ 
+  core.debug('Job pod is ready for traffic')
+ 
+  let isAlpine = false
+  try {
+    isAlpine = await isPodContainerAlpine(
+      createdPod.metadata.name,
+      JOB_CONTAINER_NAME
+    )
+  } catch (err) {
+    core.debug(
+      `Failed to determine if the pod is alpine: ${JSON.stringify(err)}`
+    )
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to determine if the pod is alpine: ${message}`)
+  }
+  core.debug(`Setting isAlpine to ${isAlpine}`)
+  generateResponseFile(responseFile, args, createdPod, isAlpine)
+}
+ 
+function generateResponseFile(
+  responseFile: string,
+  args: PrepareJobArgs,
+  appPod: k8s.V1Pod,
+  isAlpine
+): void {
+  Iif (!appPod.metadata?.name) {
+    throw new Error('app pod must have metadata.name specified')
+  }
+  const response = {
+    state: {
+      jobPod: appPod.metadata.name
+    },
+    context: {},
+    isAlpine
+  }
+ 
+  const mainContainer = appPod.spec?.containers?.find(
+    c => c.name === JOB_CONTAINER_NAME
+  )
+  Iif (mainContainer) {
+    const mainContainerContextPorts: ContextPorts = {}
+    Iif (mainContainer?.ports) {
+      for (const port of mainContainer.ports) {
+        mainContainerContextPorts[port.containerPort] =
+          mainContainerContextPorts.hostPort
+      }
+    }
+ 
+    response.context['container'] = {
+      image: mainContainer.image,
+      ports: mainContainerContextPorts
+    }
+  }
+ 
+  Iif (args.services?.length) {
+    const serviceContainerNames =
+      args.services?.map(s => generateContainerName(s.image)) || []
+ 
+    response.context['services'] = appPod?.spec?.containers
+      ?.filter(c => serviceContainerNames.includes(c.name))
+      .map(c => {
+        const ctxPorts: ContextPorts = {}
+        Iif (c.ports?.length) {
+          for (const port of c.ports) {
+            ctxPorts[port.containerPort] = port.hostPort
+          }
+        }
+ 
+        return {
+          image: c.image,
+          ports: ctxPorts
+        }
+      })
+  }
+ 
+  writeToResponseFile(responseFile, JSON.stringify(response))
+}
+ 
+async function copyExternalsToRoot(): Promise<void> {
+  const workspace = process.env['RUNNER_WORKSPACE']
+  if (workspace) {
+    await io.cp(
+      path.join(workspace, '../../externals'),
+      path.join(workspace, '../externals'),
+      { force: true, recursive: true, copySourceDirectory: false }
+    )
+  }
+}
+ 
+export function createContainerSpec(
+  container: JobContainerInfo,
+  name: string,
+  IjobContainer = false,
+  extension?: k8s.V1PodTemplateSpec
+): k8s.V1Container {
+  if (!container.entryPoint && jobContainer) {
+    container.entryPoint = DEFAULT_CONTAINER_ENTRY_POINT
+    container.entryPointArgs = DEFAULT_CONTAINER_ENTRY_POINT_ARGS
+  }
+ 
+  const podContainer = {
+    name,
+    image: container.image,
+    ports: containerPorts(container)
+  } as k8s.V1Container
+  Iif (container.workingDirectory) {
+    podContainer.workingDir = container.workingDirectory
+  }
+ 
+  if (container.entryPoint) {
+    podContainer.command = [container.entryPoint]
+  }
+ 
+  if (container.entryPointArgs?.length > 0) {
+    podContainer.args = fixArgs(container.entryPointArgs)
+  }
+ 
+  podContainer.env = []
+  for (const [key, value] of Object.entries(
+    container['environmentVariables']
+  )) {
+    Iif (value && key !== 'HOME') {
+      podContainer.env.push({ name: key, value: value as string })
+    }
+  }
+ 
+  podContainer.env.push({
+    name: 'GITHUB_ACTIONS',
+    value: 'true'
+  })
+ 
+  if (!('CI' in container['environmentVariables'])) {
+    podContainer.env.push({
+      name: 'CI',
+      value: 'true'
+    })
+  }
+ 
+  podContainer.volumeMounts = containerVolumes(
+    container.userMountVolumes,
+    jobContainer
+  )
+ 
+  if (!extension) {
+    return podContainer
+  }
+ 
+  const from = extension.spec?.containers?.find(
+    c => c.name === CONTAINER_EXTENSION_PREFIX + name
+  )
+ 
+  Iif (from) {
+    mergeContainerWithOptions(podContainer, from)
+  }
+ 
+  return podContainer
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/run-container-step.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/run-container-step.ts.html new file mode 100644 index 00000000..597716b9 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/run-container-step.ts.html @@ -0,0 +1,592 @@ + + + + + + Code coverage report for src/hooks/run-container-step.ts + + + + + + + + + +
+
+

All files / src/hooks run-container-step.ts

+
+ +
+ 8.21% + Statements + 6/73 +
+ + +
+ 0% + Branches + 0/99 +
+ + +
+ 0% + Functions + 0/3 +
+ + +
+ 8.95% + Lines + 6/67 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +1701x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import * as core from '@actions/core'
+import * as k8s from '@kubernetes/client-node'
+import { RunContainerStepArgs } from 'hooklib'
+import {
+  createJob,
+  createSecretForEnvs,
+  describePodFailure,
+  getContainerJobPodName,
+  getContainerTerminatedErrors,
+  getPodByName,
+  getPodLogs,
+  getPodStatus,
+  waitForJobToComplete,
+  waitForPodPhases
+} from '../k8s'
+import {
+  containerVolumes,
+  fixArgs,
+  mergeContainerWithOptions,
+  PodPhase,
+  readExtensionFromFile
+} from '../k8s/utils'
+import { JOB_CONTAINER_EXTENSION_NAME, JOB_CONTAINER_NAME } from './constants'
+ 
+export async function runContainerStep(
+  stepContainer: RunContainerStepArgs
+): Promise<number> {
+  Iif (stepContainer.dockerfile) {
+    throw new Error('Building container actions is not currently supported')
+  }
+ 
+  let secretName: string | undefined = undefined
+  if (IstepContainer.environmentVariables) {
+    try {
+      const envs = JSON.parse(
+        JSON.stringify(stepContainer.environmentVariables)
+      )
+      envs['GITHUB_ACTIONS'] = 'true'
+      Iif (!('CI' in envs)) {
+        envs.CI = 'true'
+      }
+      secretName = await createSecretForEnvs(envs)
+    } catch (err) {
+      core.debug(`createSecretForEnvs failed: ${JSON.stringify(err)}`)
+      const message = (err as any)?.response?.body?.message || err
+      throw new Error(`failed to create script environment: ${message}`)
+    }
+  }
+ 
+  const extension = readExtensionFromFile()
+ 
+  core.debug(`Created secret ${secretName} for container job envs`)
+  const container = createContainerSpec(stepContainer, secretName, extension)
+ 
+  let job: k8s.V1Job
+  try {
+    job = await createJob(container, extension)
+  } catch (err) {
+    core.debug(`createJob failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to run script step: ${message}`)
+  }
+ 
+  Iif (!job.metadata?.name) {
+    throw new Error(
+      `Expected job ${JSON.stringify(
+        job
+      )} to have correctly set the metadata.name`
+    )
+  }
+  core.debug(`Job created, waiting for pod to start: ${job.metadata?.name}`)
+ 
+  let podName: string
+  try {
+    podName = await getContainerJobPodName(job.metadata.name)
+  } catch (err) {
+    core.debug(`getContainerJobPodName failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to get container job pod name: ${message}`)
+  }
+ 
+  await waitForPodPhases(
+    podName,
+    new Set([
+      PodPhase.COMPLETED,
+      PodPhase.RUNNING,
+      PodPhase.SUCCEEDED,
+      PodPhase.FAILED
+    ]),
+    new Set([PodPhase.PENDING, PodPhase.UNKNOWN])
+  )
+  core.debug('Container step is running or complete, pulling logs')
+ 
+  await getPodLogs(podName, JOB_CONTAINER_NAME)
+ 
+  core.debug('Waiting for container job to complete')
+  await waitForJobToComplete(job.metadata.name)
+ 
+  // pod has failed so pull the status code from the container
+  const status = await getPodStatus(podName)
+  Iif (status?.phase === 'Succeeded') {
+    return 0
+  }
+  Iif (!status?.containerStatuses?.length) {
+    core.error(
+      `Can't determine container status from response:  ${JSON.stringify(
+        status
+      )}`
+    )
+    return 1
+  }
+ 
+  const pod = await getPodByName(podName)
+  const terminatedErrors = getContainerTerminatedErrors(pod)
+  if (IterminatedErrors.length > 0) {
+    const details = await describePodFailure(podName)
+    core.error(
+      `Pod ${podName} has unrecoverable container errors:\n${terminatedErrors.join('\n')}\n${details}`
+    )
+    return 1
+  }
+ 
+  const exitCode =
+    status.containerStatuses[status.containerStatuses.length - 1].state
+      ?.terminated?.exitCode
+  return Number(exitCode) || 1
+}
+ 
+function createContainerSpec(
+  container: RunContainerStepArgs,
+  secretName?: string,
+  extension?: k8s.V1PodTemplateSpec
+): k8s.V1Container {
+  const podContainer = new k8s.V1Container()
+  podContainer.name = JOB_CONTAINER_NAME
+  podContainer.image = container.image
+  podContainer.workingDir = container.workingDirectory
+  podContainer.command = container.entryPoint
+    ? [container.entryPoint]
+    : undefined
+  podContainer.args = container.entryPointArgs?.length
+    ? fixArgs(container.entryPointArgs)
+    : undefined
+ 
+  Iif (secretName) {
+    podContainer.envFrom = [
+      {
+        secretRef: {
+          name: secretName,
+          optional: false
+        }
+      }
+    ]
+  }
+  podContainer.volumeMounts = containerVolumes(undefined, false, true)
+ 
+  Iif (!extension) {
+    return podContainer
+  }
+ 
+  const from = extension.spec?.containers?.find(
+    c => c.name === JOB_CONTAINER_EXTENSION_NAME
+  )
+  Iif (from) {
+    mergeContainerWithOptions(podContainer, from)
+  }
+ 
+  return podContainer
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/hooks/run-script-step.ts.html b/packages/k8s/coverage/lcov-report/src/hooks/run-script-step.ts.html new file mode 100644 index 00000000..1bcbb0f0 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/hooks/run-script-step.ts.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/hooks/run-script-step.ts + + + + + + + + + +
+
+

All files / src/hooks run-script-step.ts

+
+ +
+ 40% + Statements + 6/15 +
+ + +
+ 0% + Branches + 0/14 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 40% + Lines + 6/15 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39  +1x +1x +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/* eslint-disable @typescript-eslint/no-unused-vars */
+import * as fs from 'fs'
+import * as core from '@actions/core'
+import { RunScriptStepArgs } from 'hooklib'
+import { execPodStep } from '../k8s'
+import { writeEntryPointScript } from '../k8s/utils'
+import { JOB_CONTAINER_NAME } from './constants'
+ 
+export async function runScriptStep(
+  args: RunScriptStepArgs,
+  state,
+  responseFile
+): Promise<void> {
+  const { entryPoint, entryPointArgs, environmentVariables } = args
+  const { containerPath, runnerPath } = writeEntryPointScript(
+    args.workingDirectory,
+    entryPoint,
+    entryPointArgs,
+    args.prependPath,
+    environmentVariables
+  )
+ 
+  args.entryPoint = 'sh'
+  args.entryPointArgs = ['-e', containerPath]
+  try {
+    await execPodStep(
+      [args.entryPoint, ...args.entryPointArgs],
+      state.jobPod,
+      JOB_CONTAINER_NAME
+    )
+  } catch (err) {
+    core.debug(`execPodStep failed: ${JSON.stringify(err)}`)
+    const message = (err as any)?.response?.body?.message || err
+    throw new Error(`failed to run script step: ${message}`)
+  } finally {
+    fs.rmSync(runnerPath)
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/k8s/index.html b/packages/k8s/coverage/lcov-report/src/k8s/index.html new file mode 100644 index 00000000..fe188308 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/k8s/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/k8s + + + + + + + + + +
+
+

All files src/k8s

+
+ +
+ 15.36% + Statements + 98/638 +
+ + +
+ 3.05% + Branches + 14/458 +
+ + +
+ 10.44% + Functions + 7/67 +
+ + +
+ 18.11% + Lines + 98/541 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
11.54%56/4851.46%5/3425.45%3/5513.49%56/415
utils.ts +
+
27.45%42/1537.75%9/11633.33%4/1233.33%42/126
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/k8s/index.ts.html b/packages/k8s/coverage/lcov-report/src/k8s/index.ts.html new file mode 100644 index 00000000..88919100 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/k8s/index.ts.html @@ -0,0 +1,3028 @@ + + + + + + Code coverage report for src/k8s/index.ts + + + + + + + + + +
+
+

All files / src/k8s index.ts

+
+ +
+ 11.54% + Statements + 56/485 +
+ + +
+ 1.46% + Branches + 5/342 +
+ + +
+ 5.45% + Functions + 3/55 +
+ + +
+ 13.49% + Lines + 56/415 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +536 +537 +538 +539 +540 +541 +542 +543 +544 +545 +546 +547 +548 +549 +550 +551 +552 +553 +554 +555 +556 +557 +558 +559 +560 +561 +562 +563 +564 +565 +566 +567 +568 +569 +570 +571 +572 +573 +574 +575 +576 +577 +578 +579 +580 +581 +582 +583 +584 +585 +586 +587 +588 +589 +590 +591 +592 +593 +594 +595 +596 +597 +598 +599 +600 +601 +602 +603 +604 +605 +606 +607 +608 +609 +610 +611 +612 +613 +614 +615 +616 +617 +618 +619 +620 +621 +622 +623 +624 +625 +626 +627 +628 +629 +630 +631 +632 +633 +634 +635 +636 +637 +638 +639 +640 +641 +642 +643 +644 +645 +646 +647 +648 +649 +650 +651 +652 +653 +654 +655 +656 +657 +658 +659 +660 +661 +662 +663 +664 +665 +666 +667 +668 +669 +670 +671 +672 +673 +674 +675 +676 +677 +678 +679 +680 +681 +682 +683 +684 +685 +686 +687 +688 +689 +690 +691 +692 +693 +694 +695 +696 +697 +698 +699 +700 +701 +702 +703 +704 +705 +706 +707 +708 +709 +710 +711 +712 +713 +714 +715 +716 +717 +718 +719 +720 +721 +722 +723 +724 +725 +726 +727 +728 +729 +730 +731 +732 +733 +734 +735 +736 +737 +738 +739 +740 +741 +742 +743 +744 +745 +746 +747 +748 +749 +750 +751 +752 +753 +754 +755 +756 +757 +758 +759 +760 +761 +762 +763 +764 +765 +766 +767 +768 +769 +770 +771 +772 +773 +774 +775 +776 +777 +778 +779 +780 +781 +782 +783 +784 +785 +786 +787 +788 +789 +790 +791 +792 +793 +794 +795 +796 +797 +798 +799 +800 +801 +802 +803 +804 +805 +806 +807 +808 +809 +810 +811 +812 +813 +814 +815 +816 +817 +818 +819 +820 +821 +822 +823 +824 +825 +826 +827 +828 +829 +830 +831 +832 +833 +834 +835 +836 +837 +838 +839 +840 +841 +842 +843 +844 +845 +846 +847 +848 +849 +850 +851 +852 +853 +854 +855 +856 +857 +858 +859 +860 +861 +862 +863 +864 +865 +866 +867 +868 +869 +870 +871 +872 +873 +874 +875 +876 +877 +878 +879 +880 +881 +882 +883 +884 +885 +886 +887 +888 +889 +890 +891 +892 +893 +894 +895 +896 +897 +898 +899 +900 +901 +902 +903 +904 +905 +906 +907 +908 +909 +910 +911 +912 +913 +914 +915 +916 +917 +918 +919 +920 +921 +922 +923 +924 +925 +926 +927 +928 +929 +930 +931 +932 +933 +934 +935 +936 +937 +938 +939 +940 +941 +942 +943 +944 +945 +946 +947 +948 +949 +950 +951 +952 +953 +954 +955 +956 +957 +958 +959 +960 +961 +962 +963 +964 +965 +966 +967 +968 +969 +970 +971 +972 +973 +974 +975 +976 +977 +978 +979 +980 +981 +9821x +1x +  +1x +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +1x +  +1x +1x +1x +  +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +3x +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  + 
import * as core from '@actions/core'
+import * as k8s from '@kubernetes/client-node'
+import { ContainerInfo, Registry } from 'hooklib'
+import * as stream from 'stream'
+import {
+  getJobPodName,
+  getRunnerPodName,
+  getSecretName,
+  getStepPodName,
+  getVolumeClaimName,
+  RunnerInstanceLabel
+} from '../hooks/constants'
+import {
+  PodPhase,
+  mergePodSpecWithOptions,
+  mergeObjectMeta,
+  useKubeScheduler,
+  fixArgs
+} from './utils'
+ 
+const kc = new k8s.KubeConfig()
+ 
+kc.loadFromDefault()
+ 
+const k8sApi = kc.makeApiClient(k8s.CoreV1Api)
+const k8sBatchV1Api = kc.makeApiClient(k8s.BatchV1Api)
+const k8sAuthorizationV1Api = kc.makeApiClient(k8s.AuthorizationV1Api)
+ 
+const DEFAULT_WAIT_FOR_POD_TIME_SECONDS = 10 * 60 // 10 min
+ 
+export const POD_VOLUME_NAME = 'work'
+ 
+export const requiredPermissions = [
+  {
+    group: '',
+    verbs: ['get', 'list', 'create', 'delete'],
+    resource: 'pods',
+    subresource: ''
+  },
+  {
+    group: '',
+    verbs: ['get', 'create'],
+    resource: 'pods',
+    subresource: 'exec'
+  },
+  {
+    group: '',
+    verbs: ['get', 'list', 'watch'],
+    resource: 'pods',
+    subresource: 'log'
+  },
+  {
+    group: 'batch',
+    verbs: ['get', 'list', 'create', 'delete'],
+    resource: 'jobs',
+    subresource: ''
+  },
+  {
+    group: '',
+    verbs: ['create', 'delete', 'get', 'list'],
+    resource: 'secrets',
+    subresource: ''
+  }
+]
+ 
+export async function createPod(
+  jobContainer?: k8s.V1Container,
+  services?: k8s.V1Container[],
+  registry?: Registry,
+  extension?: k8s.V1PodTemplateSpec
+): Promise<k8s.V1Pod> {
+  const containers: k8s.V1Container[] = []
+  Iif (jobContainer) {
+    containers.push(jobContainer)
+  }
+  Iif (services?.length) {
+    containers.push(...services)
+  }
+ 
+  const appPod = new k8s.V1Pod()
+ 
+  appPod.apiVersion = 'v1'
+  appPod.kind = 'Pod'
+ 
+  appPod.metadata = new k8s.V1ObjectMeta()
+  appPod.metadata.name = getJobPodName()
+ 
+  const instanceLabel = new RunnerInstanceLabel()
+  appPod.metadata.labels = {
+    [instanceLabel.key]: instanceLabel.value
+  }
+  appPod.metadata.annotations = {}
+ 
+  appPod.spec = new k8s.V1PodSpec()
+  appPod.spec.containers = containers
+  appPod.spec.restartPolicy = 'Never'
+ 
+  const nodeName = await getCurrentNodeName()
+  if (IuseKubeScheduler()) {
+    appPod.spec.affinity = await getPodAffinity(nodeName)
+  } else {
+    appPod.spec.affinity = await getPreferredPodAffinity(nodeName)
+  }
+  const claimName = getVolumeClaimName()
+  appPod.spec.volumes = [
+    {
+      name: 'work',
+      persistentVolumeClaim: { claimName }
+    }
+  ]
+ 
+  if (Iregistry) {
+    const secret = await createDockerSecret(registry)
+    Iif (!secret?.metadata?.name) {
+      throw new Error(`created secret does not have secret.metadata.name`)
+    }
+    const secretReference = new k8s.V1LocalObjectReference()
+    secretReference.name = secret.metadata.name
+    appPod.spec.imagePullSecrets = [secretReference]
+  }
+ 
+  Iif (extension?.metadata) {
+    mergeObjectMeta(appPod, extension.metadata)
+  }
+ 
+  Iif (extension?.spec) {
+    mergePodSpecWithOptions(appPod.spec, extension.spec)
+  }
+ 
+  const { body } = await k8sApi.createNamespacedPod(namespace(), appPod)
+  return body
+}
+ 
+export async function createJob(
+  container: k8s.V1Container,
+  extension?: k8s.V1PodTemplateSpec
+): Promise<k8s.V1Job> {
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const job = new k8s.V1Job()
+  job.apiVersion = 'batch/v1'
+  job.kind = 'Job'
+  job.metadata = new k8s.V1ObjectMeta()
+  job.metadata.name = getStepPodName()
+  job.metadata.labels = { [runnerInstanceLabel.key]: runnerInstanceLabel.value }
+  job.metadata.annotations = {}
+ 
+  job.spec = new k8s.V1JobSpec()
+  job.spec.ttlSecondsAfterFinished = 300
+  job.spec.backoffLimit = 0
+  job.spec.template = new k8s.V1PodTemplateSpec()
+ 
+  job.spec.template.spec = new k8s.V1PodSpec()
+  job.spec.template.metadata = new k8s.V1ObjectMeta()
+  job.spec.template.metadata.labels = {}
+  job.spec.template.metadata.annotations = {}
+  job.spec.template.spec.containers = [container]
+  job.spec.template.spec.restartPolicy = 'Never'
+ 
+  const nodeName = await getCurrentNodeName()
+  if (IuseKubeScheduler()) {
+    job.spec.template.spec.affinity = await getPodAffinity(nodeName)
+  } else {
+    job.spec.template.spec.affinity = await getPreferredPodAffinity(nodeName)
+  }
+ 
+  const claimName = getVolumeClaimName()
+  job.spec.template.spec.volumes = [
+    {
+      name: 'work',
+      persistentVolumeClaim: { claimName }
+    }
+  ]
+ 
+  Iif (extension) {
+    Iif (extension.metadata) {
+      // apply metadata both to the job and the pod created by the job
+      mergeObjectMeta(job, extension.metadata)
+      mergeObjectMeta(job.spec.template, extension.metadata)
+    }
+    Iif (extension.spec) {
+      mergePodSpecWithOptions(job.spec.template.spec, extension.spec)
+    }
+  }
+ 
+  const { body } = await k8sBatchV1Api.createNamespacedJob(namespace(), job)
+  return body
+}
+ 
+export async function getContainerJobPodName(jobName: string): Promise<string> {
+  const selector = `job-name=${jobName}`
+  const backOffManager = new BackOffManager(60)
+  while (Itrue) {
+    const podList = await k8sApi.listNamespacedPod(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      undefined,
+      selector,
+      1
+    )
+ 
+    if (I!podList.body.items?.length) {
+      await backOffManager.backOff()
+      continue
+    }
+ 
+    Iif (!podList.body.items[0].metadata?.name) {
+      throw new Error(
+        `Failed to determine the name of the pod for job ${jobName}`
+      )
+    }
+    return podList.body.items[0].metadata.name
+  }
+}
+ 
+export async function deletePod(podName: string): Promise<void> {
+  await k8sApi.deleteNamespacedPod(
+    podName,
+    namespace(),
+    undefined,
+    undefined,
+    0
+  )
+}
+ 
+export async function execPodStep(
+  command: string[],
+  podName: string,
+  containerName: string,
+  stdin?: stream.Readable
+): Promise<void> {
+  const exec = new k8s.Exec(kc)
+  command = fixArgs(command)
+  // Exec returns a websocket. If websocket fails, we should reject the promise. Otherwise, websocket will call a callback. Since at that point, websocket is not failing, we can safely resolve or reject the promise.
+  await new Promise(function (resolve, reject) {
+    exec
+      .exec(
+        namespace(),
+        podName,
+        containerName,
+        command,
+        process.stdout,
+        process.stderr,
+        stdin ?? null,
+        false /* tty */,
+        resp => {
+          // kube.exec returns an error if exit code is not 0, but we can't actually get the exit code
+          if (resp.status === 'Success') {
+            resolve(resp.code)
+          } else {
+            core.debug(
+              JSON.stringify({
+                message: resp?.message,
+                details: resp?.details
+              })
+            )
+            reject(resp?.message)
+          }
+        }
+      )
+      // If exec.exec fails, explicitly reject the outer promise
+      // eslint-disable-next-line github/no-then
+      .catch(e => reject(e))
+  })
+}
+ 
+export async function waitForJobToComplete(jobName: string): Promise<void> {
+  const backOffManager = new BackOffManager()
+  while (Itrue) {
+    try {
+      Iif (await isJobSucceeded(jobName)) {
+        return
+      }
+    } catch (error) {
+      throw new Error(`job ${jobName} has failed`)
+    }
+    await backOffManager.backOff()
+  }
+}
+ 
+export async function createDockerSecret(
+  registry: Registry
+): Promise<k8s.V1Secret> {
+  const authContent = {
+    auths: {
+      [registry.serverUrl || 'https://index.docker.io/v1/']: {
+        username: registry.username,
+        password: registry.password,
+        auth: Buffer.from(`${registry.username}:${registry.password}`).toString(
+          'base64'
+        )
+      }
+    }
+  }
+ 
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const secretName = getSecretName()
+  const secret = new k8s.V1Secret()
+  secret.immutable = true
+  secret.apiVersion = 'v1'
+  secret.metadata = new k8s.V1ObjectMeta()
+  secret.metadata.name = secretName
+  secret.metadata.namespace = namespace()
+  secret.metadata.labels = {
+    [runnerInstanceLabel.key]: runnerInstanceLabel.value
+  }
+  secret.type = 'kubernetes.io/dockerconfigjson'
+  secret.kind = 'Secret'
+  secret.data = {
+    '.dockerconfigjson': Buffer.from(JSON.stringify(authContent)).toString(
+      'base64'
+    )
+  }
+ 
+  const { body } = await k8sApi.createNamespacedSecret(namespace(), secret)
+  return body
+}
+ 
+export async function createSecretForEnvs(envs: {
+  [key: string]: string
+}): Promise<string> {
+  const runnerInstanceLabel = new RunnerInstanceLabel()
+ 
+  const secret = new k8s.V1Secret()
+  const secretName = getSecretName()
+  secret.immutable = true
+  secret.apiVersion = 'v1'
+  secret.metadata = new k8s.V1ObjectMeta()
+  secret.metadata.name = secretName
+ 
+  secret.metadata.labels = {
+    [runnerInstanceLabel.key]: runnerInstanceLabel.value
+  }
+  secret.kind = 'Secret'
+  secret.data = {}
+  for (const [key, value] of Object.entries(envs)) {
+    secret.data[key] = Buffer.from(value).toString('base64')
+  }
+ 
+  await k8sApi.createNamespacedSecret(namespace(), secret)
+  return secretName
+}
+ 
+export async function deleteSecret(secretName: string): Promise<void> {
+  await k8sApi.deleteNamespacedSecret(secretName, namespace())
+}
+ 
+export async function pruneSecrets(): Promise<void> {
+  const secretList = await k8sApi.listNamespacedSecret(
+    namespace(),
+    undefined,
+    undefined,
+    undefined,
+    undefined,
+    new RunnerInstanceLabel().toString()
+  )
+  Iif (!secretList.body.items.length) {
+    return
+  }
+ 
+  await Promise.all(
+    secretList.body.items.map(
+      secret => secret.metadata?.name && deleteSecret(secret.metadata.name)
+    )
+  )
+}
+ 
+export const UNRECOVERABLE_WAITING_REASONS = new Set([
+  'ImagePullBackOff',
+  'ErrImagePull',
+  'InvalidImageName',
+  'CreateContainerConfigError',
+  'CreateContainerError'
+])
+ 
+export const UNRECOVERABLE_EVENT_REASONS = new Set([
+  'FailedScheduling',
+  'FailedBinding',
+  'FailedMount'
+])
+ 
+export const UNRECOVERABLE_TERMINATED_REASONS = new Set([
+  'OOMKilled',
+  'Error',
+  'FailedPostStartHookError'
+])
+ 
+const MAX_DIAGNOSTIC_EVENTS = 10
+ 
+export function getUnrecoverableWaitingReasons(): Set<string> {
+  const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS']
+  Iif (!extra) {
+    return UNRECOVERABLE_WAITING_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_WAITING_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    Iif (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getUnrecoverableEventReasons(): Set<string> {
+  const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS']
+  Iif (!extra) {
+    return UNRECOVERABLE_EVENT_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_EVENT_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    Iif (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getUnrecoverableTerminatedReasons(): Set<string> {
+  const extra =
+    process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS']
+  Iif (!extra) {
+    return UNRECOVERABLE_TERMINATED_REASONS
+  }
+  const reasons = new Set(UNRECOVERABLE_TERMINATED_REASONS)
+  for (const reason of extra.split(',')) {
+    const trimmed = reason.trim()
+    Iif (trimmed) {
+      reasons.add(trimmed)
+    }
+  }
+  return reasons
+}
+ 
+export function getContainerErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  const unrecoverableReasons = getUnrecoverableWaitingReasons()
+  const allStatuses = [
+    ...(pod.status?.initContainerStatuses ?? []),
+    ...(pod.status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const waiting = cs.state?.waiting
+    Iif (waiting?.reason && unrecoverableReasons.has(waiting.reason)) {
+      errors.push(
+        `container "${cs.name}": ${waiting.reason}${
+          waiting.message ? ` - ${waiting.message}` : ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export async function getPodEventErrors(podName: string): Promise<string[]> {
+  const unrecoverableReasons = getUnrecoverableEventReasons()
+  let items: k8s.CoreV1Event[]
+  try {
+    const { body } = await k8sApi.listNamespacedEvent(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      `involvedObject.name=${podName}`
+    )
+    items = body.items
+  } catch (err) {
+    core.debug(
+      `Could not list events for pod ${podName} (the 'events' permission may be missing): ${
+        err instanceof Error ? err.message : String(err)
+      }`
+    )
+    return []
+  }
+ 
+  const errors: string[] = []
+  for (const e of items) {
+    Iif (
+      e.type === 'Warning' &&
+      e.reason &&
+      unrecoverableReasons.has(e.reason)
+    ) {
+      errors.push(`Event [Warning] ${e.reason}: ${e.message ?? ''}`)
+    }
+  }
+  return errors
+}
+ 
+export function getPodConditionErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  for (const cond of pod.status?.conditions ?? []) {
+    Iif (cond.type === 'PodScheduled' && cond.status === 'False' && cond.reason === 'Unschedulable') {
+      errors.push(
+        `Condition ${cond.type}=False (reason: ${cond.reason ?? ''}): ${
+          cond.message ?? ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export function getContainerTerminatedErrors(pod: k8s.V1Pod): string[] {
+  const errors: string[] = []
+  const unrecoverableReasons = getUnrecoverableTerminatedReasons()
+  const allStatuses = [
+    ...(pod.status?.initContainerStatuses ?? []),
+    ...(pod.status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const terminated = cs.state?.terminated
+    Iif (terminated?.reason && unrecoverableReasons.has(terminated.reason)) {
+      errors.push(
+        `container "${cs.name}": ${terminated.reason} (exit code ${terminated.exitCode}) - ${
+          terminated.message ?? ''
+        }`
+      )
+    }
+  }
+  return errors
+}
+ 
+export async function describePodFailure(podName: string): Promise<string> {
+  let pod: k8s.V1Pod
+  try {
+    pod = await readPod(podName)
+  } catch (err) {
+    return `Could not read pod ${podName} for diagnostics: ${
+      err instanceof Error ? err.message : String(err)
+    }`
+  }
+ 
+  const lines: string[] = []
+  const status = pod.status
+ 
+  Iif (status?.phase) {
+    lines.push(
+      `Phase: ${status.phase}${
+        status.reason ? ` (reason: ${status.reason})` : ''
+      }`
+    )
+  }
+  Iif (status?.message) {
+    lines.push(`Message: ${status.message}`)
+  }
+ 
+  const separator = '────────────────────────────────────────────────────────────'
+  lines.push(separator)
+ 
+  for (const cond of status?.conditions ?? []) {
+    Iif (cond.status === 'False') {
+      lines.push(
+        `  ✗ ${cond.type}=False${
+          cond.reason ? ` (${cond.reason})` : ''
+        }${cond.message ? `: ${cond.message}` : ''}`
+      )
+    }
+  }
+ 
+  const allStatuses = [
+    ...(status?.initContainerStatuses ?? []),
+    ...(status?.containerStatuses ?? [])
+  ]
+  for (const cs of allStatuses) {
+    const waiting = cs.state?.waiting
+    Iif (waiting?.reason) {
+      lines.push(
+        `  ✗ container "${cs.name}": ${waiting.reason}${
+          waiting.message ? `\n    ${waiting.message}` : ''
+        }`
+      )
+    }
+    const terminated = cs.state?.terminated
+    Iif (terminated) {
+      lines.push(
+        `  ✗ container "${cs.name}": ${
+          terminated.reason ?? 'Unknown'
+        } (exit code ${terminated.exitCode})${
+          terminated.message ? `\n    ${terminated.message}` : ''
+        }`
+      )
+    }
+  }
+ 
+  lines.push(...(await describePodWarningEvents(podName)))
+ 
+  Iif (!lines.length) {
+    return `No additional diagnostic information available for pod ${podName}`
+  }
+  return lines.join('\n')
+}
+ 
+async function describePodWarningEvents(podName: string): Promise<string[]> {
+  let items: k8s.CoreV1Event[]
+  try {
+    const { body } = await k8sApi.listNamespacedEvent(
+      namespace(),
+      undefined,
+      undefined,
+      undefined,
+      `involvedObject.name=${podName}`
+    )
+    items = body.items
+  } catch (err) {
+    core.debug(
+      `Could not list events for pod ${podName} (the 'events' permission may be missing): ${
+        err instanceof Error ? err.message : String(err)
+      }`
+    )
+    return []
+  }
+ 
+  const warnings = items.filter(e => e.type === 'Warning')
+  Iif (!warnings.length) {
+    return []
+  }
+ 
+  const eventTime = (e: k8s.CoreV1Event): number => {
+    const t = e.lastTimestamp ?? e.eventTime ?? e.firstTimestamp
+    return t ? new Date(t).getTime() : 0
+  }
+  warnings.sort((a, b) => eventTime(a) - eventTime(b))
+ 
+  const recent = warnings.slice(-MAX_DIAGNOSTIC_EVENTS)
+  const lines = recent.map(e => {
+    const count = e.count && e.count > 1 ? ` (x${e.count})` : ''
+    return `Event [Warning] ${e.reason ?? ''}${count}: ${
+      e.message ?? ''
+    }`.trim()
+  })
+  Iif (warnings.length > recent.length) {
+    lines.unshift(
+      `(showing ${recent.length} of ${warnings.length} warning events)`
+    )
+  }
+  return lines
+}
+ 
+export async function waitForPodPhases(
+  podName: string,
+  awaitingPhases: Set<PodPhase>,
+  backOffPhases: Set<PodPhase>,
+  ImaxTimeSeconds = DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+): Promise<void> {
+  const backOffManager = new BackOffManager(maxTimeSeconds)
+  let phase: PodPhase = PodPhase.UNKNOWN
+  while (Itrue) {
+    const pod = await readPod(podName)
+    phase = parsePodPhase(pod)
+    Iif (awaitingPhases.has(phase)) {
+      return
+    }
+ 
+    if (I!backOffPhases.has(phase)) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} is unhealthy with phase status ${phase}\n${details}`
+      )
+    }
+ 
+    const containerErrors = getContainerErrors(pod)
+    if (IcontainerErrors.length > 0) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} has unrecoverable container errors: ${containerErrors.join(
+          '; '
+        )}\n${details}`
+      )
+    }
+ 
+    const conditionErrors = getPodConditionErrors(pod)
+    if (IconditionErrors.length > 0) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} has unrecoverable condition errors: ${conditionErrors.join(
+          '; '
+        )}\n${details}`
+      )
+    }
+ 
+    try {
+      await backOffManager.backOff()
+    } catch (error) {
+      const details = await describePodFailure(podName)
+      throw new Error(
+        `Pod ${podName} is unhealthy: timed out after ${maxTimeSeconds}s in phase ${phase}\n${details}`
+      )
+    }
+  }
+}
+ 
+export function getPrepareJobTimeoutSeconds(): number {
+  const envTimeoutSeconds =
+    process.env['ACTIONS_RUNNER_PREPARE_JOB_TIMEOUT_SECONDS']
+ 
+  if (!envTimeoutSeconds) {
+    return DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+  }
+ 
+  const timeoutSeconds = parseInt(envTimeoutSeconds, 10)
+  Iif (!timeoutSeconds || timeoutSeconds <= 0) {
+    core.warning(
+      `Prepare job timeout is invalid ("${timeoutSeconds}"): use an int > 0`
+    )
+    return DEFAULT_WAIT_FOR_POD_TIME_SECONDS
+  }
+ 
+  return timeoutSeconds
+}
+ 
+async function readPod(podName: string): Promise<k8s.V1Pod> {
+  const { body } = await k8sApi.readNamespacedPod(podName, namespace())
+  return body
+}
+ 
+const podPhaseLookup = new Set<string>([
+  PodPhase.PENDING,
+  PodPhase.RUNNING,
+  PodPhase.SUCCEEDED,
+  PodPhase.FAILED,
+  PodPhase.UNKNOWN
+])
+ 
+export function parsePodPhase(pod: k8s.V1Pod): PodPhase {
+  Iif (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) {
+    return PodPhase.UNKNOWN
+  }
+  return pod.status.phase as PodPhase
+}
+ 
+async function isJobSucceeded(jobName: string): Promise<boolean> {
+  const { body } = await k8sBatchV1Api.readNamespacedJob(jobName, namespace())
+  const job = body
+  Iif (job.status?.failed) {
+    throw new Error(`job ${jobName} has failed`)
+  }
+  return !!job.status?.succeeded
+}
+ 
+export async function getPodLogs(
+  podName: string,
+  containerName: string
+): Promise<void> {
+  const log = new k8s.Log(kc)
+  const logStream = new stream.PassThrough()
+  logStream.on('data', chunk => {
+    // use write rather than console.log to prevent double line feed
+    process.stdout.write(chunk)
+  })
+ 
+  logStream.on('error', err => {
+    process.stderr.write(err.message)
+  })
+ 
+  const r = await log.log(namespace(), podName, containerName, logStream, {
+    follow: true,
+    pretty: false,
+    timestamps: false
+  })
+  await new Promise(resolve => r.on('close', () => resolve(null)))
+}
+ 
+export async function prunePods(): Promise<void> {
+  const podList = await k8sApi.listNamespacedPod(
+    namespace(),
+    undefined,
+    undefined,
+    undefined,
+    undefined,
+    new RunnerInstanceLabel().toString()
+  )
+  Iif (!podList.body.items.length) {
+    return
+  }
+ 
+  await Promise.all(
+    podList.body.items.map(
+      pod => pod.metadata?.name && deletePod(pod.metadata.name)
+    )
+  )
+}
+ 
+export async function getPodStatus(
+  name: string
+): Promise<k8s.V1PodStatus | undefined> {
+  const { body } = await k8sApi.readNamespacedPod(name, namespace())
+  return body.status
+}
+ 
+export async function isAuthPermissionsOK(): Promise<boolean> {
+  const sar = new k8s.V1SelfSubjectAccessReview()
+  const asyncs: Promise<{
+    response: unknown
+    body: k8s.V1SelfSubjectAccessReview
+  }>[] = []
+  for (const resource of requiredPermissions) {
+    for (const verb of resource.verbs) {
+      sar.spec = new k8s.V1SelfSubjectAccessReviewSpec()
+      sar.spec.resourceAttributes = new k8s.V1ResourceAttributes()
+      sar.spec.resourceAttributes.verb = verb
+      sar.spec.resourceAttributes.namespace = namespace()
+      sar.spec.resourceAttributes.group = resource.group
+      sar.spec.resourceAttributes.resource = resource.resource
+      sar.spec.resourceAttributes.subresource = resource.subresource
+      asyncs.push(k8sAuthorizationV1Api.createSelfSubjectAccessReview(sar))
+    }
+  }
+  const responses = await Promise.all(asyncs)
+  return responses.every(resp => resp.body.status?.allowed)
+}
+ 
+export async function isPodContainerAlpine(
+  podName: string,
+  containerName: string
+): Promise<boolean> {
+  let isAlpine = true
+  try {
+    await execPodStep(
+      [
+        'sh',
+        '-c',
+        `'[ $(cat /etc/*release* | grep -i -e "^ID=*alpine*" -c) != 0 ] || exit 1'`
+      ],
+      podName,
+      containerName
+    )
+  } catch (err) {
+    isAlpine = false
+  }
+ 
+  return isAlpine
+}
+ 
+async function getCurrentNodeName(): Promise<string> {
+  const resp = await k8sApi.readNamespacedPod(getRunnerPodName(), namespace())
+ 
+  const nodeName = resp.body.spec?.nodeName
+  Iif (!nodeName) {
+    throw new Error('Failed to determine node name')
+  }
+  return nodeName
+}
+ 
+async function getPodAffinity(nodeName: string): Promise<k8s.V1Affinity> {
+  const affinity = new k8s.V1Affinity()
+  affinity.nodeAffinity = new k8s.V1NodeAffinity()
+  affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution =
+    new k8s.V1NodeSelector()
+  affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms =
+    [
+      {
+        matchExpressions: [
+          {
+            key: 'kubernetes.io/hostname',
+            operator: 'In',
+            values: [nodeName]
+          }
+        ]
+      }
+    ]
+  return affinity
+}
+ 
+async function getPreferredPodAffinity(
+  nodeName: string
+): Promise<k8s.V1Affinity> {
+  const affinity = new k8s.V1Affinity()
+  affinity.nodeAffinity = new k8s.V1NodeAffinity()
+ 
+  // 创建 PreferredSchedulingTerm 对象
+  const preferredTerm = new k8s.V1PreferredSchedulingTerm()
+  preferredTerm.weight = 1 // 设置权重(1-100)
+ 
+  // 创建 NodeSelectorTerm
+  preferredTerm.preference = new k8s.V1NodeSelectorTerm()
+  preferredTerm.preference.matchExpressions = [
+    {
+      key: 'kubernetes.io/hostname',
+      operator: 'In',
+      values: [nodeName]
+    }
+  ]
+ 
+  // 将 PreferredSchedulingTerm 添加到数组中
+  affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution = [
+    preferredTerm
+  ]
+ 
+  return affinity
+}
+ 
+export function namespace(): string {
+  Iif (process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE']) {
+    return process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE']
+  }
+ 
+  const context = kc.getContexts().find(ctx => ctx.namespace)
+  Iif (!context?.namespace) {
+    throw new Error(
+      'Failed to determine namespace, falling back to `default`. Namespace should be set in context, or in env variable "ACTIONS_RUNNER_KUBERNETES_NAMESPACE"'
+    )
+  }
+  return context.namespace
+}
+ 
+class BackOffManager {
+  private backOffSeconds = 1
+  totalTime = 0
+  constructor(private throwAfterSeconds?: number) {
+    Iif (!throwAfterSeconds || throwAfterSeconds < 0) {
+      this.throwAfterSeconds = undefined
+    }
+  }
+ 
+  async backOff(): Promise<void> {
+    await new Promise(resolve =>
+      setTimeout(resolve, this.backOffSeconds * 1000)
+    )
+    this.totalTime += this.backOffSeconds
+    Iif (this.throwAfterSeconds && this.throwAfterSeconds < this.totalTime) {
+      throw new Error('backoff timeout')
+    }
+    Iif (this.backOffSeconds < 20) {
+      this.backOffSeconds *= 2
+    }
+    Iif (this.backOffSeconds > 20) {
+      this.backOffSeconds = 20
+    }
+  }
+}
+ 
+export function containerPorts(
+  container: ContainerInfo
+): k8s.V1ContainerPort[] {
+  const ports: k8s.V1ContainerPort[] = []
+  if (!container.portMappings?.length) {
+    return ports
+  }
+  for (const portDefinition of container.portMappings) {
+    const portProtoSplit = portDefinition.split('/')
+    Iif (portProtoSplit.length > 2) {
+      throw new Error(`Unexpected port format: ${portDefinition}`)
+    }
+ 
+    const port = new k8s.V1ContainerPort()
+    port.protocol =
+      portProtoSplit.length === 2 ? portProtoSplit[1].toUpperCase() : 'TCP'
+ 
+    const portSplit = portProtoSplit[0].split(':')
+    Iif (portSplit.length > 2) {
+      throw new Error('ports should have at most one ":" separator')
+    }
+ 
+    const parsePort = (p: string): number => {
+      const num = Number(p)
+      Iif (!Number.isInteger(num) || num < 1 || num > 65535) {
+        throw new Error(`invalid container port: ${p}`)
+      }
+      return num
+    }
+ 
+    if (portSplit.length === 1) {
+      port.containerPort = parsePort(portSplit[0])
+    } else {
+      port.hostPort = parsePort(portSplit[0])
+      port.containerPort = parsePort(portSplit[1])
+    }
+ 
+    ports.push(port)
+  }
+  return ports
+}
+ 
+export async function getPodByName(name): Promise<k8s.V1Pod> {
+  const { body } = await k8sApi.readNamespacedPod(name, namespace())
+  return body
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/src/k8s/utils.ts.html b/packages/k8s/coverage/lcov-report/src/k8s/utils.ts.html new file mode 100644 index 00000000..0e436fd0 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/src/k8s/utils.ts.html @@ -0,0 +1,988 @@ + + + + + + Code coverage report for src/k8s/utils.ts + + + + + + + + + +
+
+

All files / src/k8s utils.ts

+
+ +
+ 27.45% + Statements + 42/153 +
+ + +
+ 7.75% + Branches + 9/116 +
+ + +
+ 33.33% + Functions + 4/12 +
+ + +
+ 33.33% + Lines + 42/126 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302  +1x +1x +1x +  +1x +1x +1x +1x +1x +  +1x +1x +  +1x +1x +  +1x +6x +3x +6x +  +3x +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +3x +3x +3x +  +  +  +  +  +  +  +  +1x +  +  +  +1x +1x +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +1x +3x +  + 
import * as k8s from '@kubernetes/client-node'
+import * as fs from 'fs'
+import * as yaml from 'js-yaml'
+import * as core from '@actions/core'
+import { Mount } from 'hooklib'
+import * as path from 'path'
+import { v1 as uuidv4 } from 'uuid'
+import { POD_VOLUME_NAME } from './index'
+import { CONTAINER_EXTENSION_PREFIX } from '../hooks/constants'
+import * as shlex from 'shlex'
+ 
+export const DEFAULT_CONTAINER_ENTRY_POINT_ARGS = [`-f`, `/dev/null`]
+export const DEFAULT_CONTAINER_ENTRY_POINT = 'tail'
+ 
+export const ENV_HOOK_TEMPLATE_PATH = 'ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE'
+export const ENV_USE_KUBE_SCHEDULER = 'ACTIONS_RUNNER_USE_KUBE_SCHEDULER'
+ 
+export function containerVolumes(
+  userMountVolumes: Mount[] = [],
+  IjobContainer = true,
+  containerAction = false
+): k8s.V1VolumeMount[] {
+  const mounts: k8s.V1VolumeMount[] = [
+    {
+      name: POD_VOLUME_NAME,
+      mountPath: '/__w'
+    }
+  ]
+ 
+  const workspacePath = process.env.GITHUB_WORKSPACE as string
+  Iif (containerAction) {
+    const i = workspacePath.lastIndexOf('_work/')
+    const workspaceRelativePath = workspacePath.slice(i + '_work/'.length)
+    mounts.push(
+      {
+        name: POD_VOLUME_NAME,
+        mountPath: '/github/workspace',
+        subPath: workspaceRelativePath
+      },
+      {
+        name: POD_VOLUME_NAME,
+        mountPath: '/github/file_commands',
+        subPath: '_temp/_runner_file_commands'
+      },
+      {
+        name: POD_VOLUME_NAME,
+        mountPath: '/github/home',
+        subPath: '_temp/_github_home'
+      },
+      {
+        name: POD_VOLUME_NAME,
+        mountPath: '/github/workflow',
+        subPath: '_temp/_github_workflow'
+      }
+    )
+    return mounts
+  }
+ 
+  Iif (!jobContainer) {
+    return mounts
+  }
+ 
+  mounts.push(
+    {
+      name: POD_VOLUME_NAME,
+      mountPath: '/__e',
+      subPath: 'externals'
+    },
+    {
+      name: POD_VOLUME_NAME,
+      mountPath: '/github/home',
+      subPath: '_temp/_github_home'
+    },
+    {
+      name: POD_VOLUME_NAME,
+      mountPath: '/github/workflow',
+      subPath: '_temp/_github_workflow'
+    }
+  )
+ 
+  if (!userMountVolumes?.length) {
+    return mounts
+  }
+ 
+  for (const userVolume of userMountVolumes) {
+    let sourceVolumePath = ''
+    if (path.isAbsolute(userVolume.sourceVolumePath)) {
+      Iif (!userVolume.sourceVolumePath.startsWith(workspacePath)) {
+        throw new Error(
+          'Volume mounts outside of the work folder are not supported'
+        )
+      }
+      // source volume path should be relative path
+      sourceVolumePath = userVolume.sourceVolumePath.slice(
+        workspacePath.length + 1
+      )
+    } else {
+      sourceVolumePath = userVolume.sourceVolumePath
+    }
+ 
+    mounts.push({
+      name: POD_VOLUME_NAME,
+      mountPath: userVolume.targetVolumePath,
+      subPath: sourceVolumePath,
+      readOnly: userVolume.readOnly
+    })
+  }
+ 
+  return mounts
+}
+ 
+export function writeEntryPointScript(
+  workingDirectory: string,
+  entryPoint: string,
+  entryPointArgs?: string[],
+  prependPath?: string[],
+  environmentVariables?: { [key: string]: string }
+): { containerPath: string; runnerPath: string } {
+  let exportPath = ''
+  Iif (prependPath?.length) {
+    // TODO: remove compatibility with typeof prependPath === 'string' as we bump to next major version, the hooks will lose PrependPath compat with runners 2.293.0 and older
+    const prepend =
+      typeof prependPath === 'string' ? prependPath : prependPath.join(':')
+    exportPath = `export PATH=${prepend}:$PATH`
+  }
+  let environmentPrefix = ''
+ 
+  Iif (environmentVariables && Object.entries(environmentVariables).length) {
+    const envBuffer: string[] = []
+    for (const [key, value] of Object.entries(environmentVariables)) {
+      Iif (
+        key.includes(`=`) ||
+        key.includes(`'`) ||
+        key.includes(`"`) ||
+        key.includes(`$`)
+      ) {
+        throw new Error(
+          `environment key ${key} is invalid - the key must not contain =, $, ', or "`
+        )
+      }
+      envBuffer.push(
+        `"${key}=${value
+          .replace(/\\/g, '\\\\')
+          .replace(/"/g, '\\"')
+          .replace(/\$/g, '\\$')
+          .replace(/`/g, '\\`')}"`
+      )
+    }
+    environmentPrefix = `env ${envBuffer.join(' ')} `
+  }
+ 
+  const content = `#!/bin/sh -l
+${exportPath}
+cd ${workingDirectory} && \
+exec ${environmentPrefix} ${entryPoint} ${
+    entryPointArgs?.length ? entryPointArgs.join(' ') : ''
+  }
+`
+  const filename = `${uuidv4()}.sh`
+  const entryPointPath = `${process.env.RUNNER_TEMP}/${filename}`
+  fs.writeFileSync(entryPointPath, content)
+  return {
+    containerPath: `/__w/_temp/${filename}`,
+    runnerPath: entryPointPath
+  }
+}
+ 
+export function generateContainerName(image: string): string {
+  const nameWithTag = image.split('/').pop()
+  const name = nameWithTag?.split(':').at(0)
+ 
+  Iif (!name) {
+    throw new Error(`Image definition '${image}' is invalid`)
+  }
+ 
+  return name
+}
+ 
+// Overwrite or append based on container options
+//
+// Keep in mind, envs and volumes could be passed as fields in container definition
+// so default volume mounts and envs are appended first, and then create options are used
+// to append more values
+//
+// Rest of the fields are just applied
+// For example, container.createOptions.container.image is going to overwrite container.image field
+export function mergeContainerWithOptions(
+  base: k8s.V1Container,
+  from: k8s.V1Container
+): void {
+  for (const [key, value] of Object.entries(from)) {
+    if (key === 'name') {
+      Iif (value !== CONTAINER_EXTENSION_PREFIX + base.name) {
+        core.warning("Skipping name override: name can't be overwritten")
+      }
+      continue
+    } else if (key === 'image') {
+      core.warning("Skipping image override: image can't be overwritten")
+      continue
+    } else if (key === 'env') {
+      const envs = value as k8s.V1EnvVar[]
+      base.env = mergeLists(base.env, envs)
+    } else if (key === 'volumeMounts' && value) {
+      const volumeMounts = value as k8s.V1VolumeMount[]
+      base.volumeMounts = mergeLists(base.volumeMounts, volumeMounts)
+    } else if (key === 'ports' && value) {
+      const ports = value as k8s.V1ContainerPort[]
+      base.ports = mergeLists(base.ports, ports)
+    } else {
+      base[key] = value
+    }
+  }
+}
+ 
+export function mergePodSpecWithOptions(
+  base: k8s.V1PodSpec,
+  from: k8s.V1PodSpec
+): void {
+  for (const [key, value] of Object.entries(from)) {
+    if (key === 'containers') {
+      base.containers.push(
+        ...from.containers.filter(
+          e => !e.name?.startsWith(CONTAINER_EXTENSION_PREFIX)
+        )
+      )
+    } else if (key === 'volumes' && value) {
+      const volumes = value as k8s.V1Volume[]
+      base.volumes = mergeLists(base.volumes, volumes)
+    } else {
+      base[key] = value
+    }
+  }
+}
+ 
+export function mergeObjectMeta(
+  base: { metadata?: k8s.V1ObjectMeta },
+  from: k8s.V1ObjectMeta
+): void {
+  Iif (!base.metadata?.labels || !base.metadata?.annotations) {
+    throw new Error(
+      "Can't merge metadata: base.metadata or base.annotations field is undefined"
+    )
+  }
+  Iif (from?.labels) {
+    for (const [key, value] of Object.entries(from.labels)) {
+      Iif (base.metadata?.labels?.[key]) {
+        core.warning(`Label ${key} is already defined and will be overwritten`)
+      }
+      base.metadata.labels[key] = value
+    }
+  }
+ 
+  Iif (from?.annotations) {
+    for (const [key, value] of Object.entries(from.annotations)) {
+      Iif (base.metadata?.annotations?.[key]) {
+        core.warning(
+          `Annotation ${key} is already defined and will be overwritten`
+        )
+      }
+      base.metadata.annotations[key] = value
+    }
+  }
+}
+ 
+export function readExtensionFromFile(): k8s.V1PodTemplateSpec | undefined {
+  const filePath = process.env[ENV_HOOK_TEMPLATE_PATH]
+  if (!filePath) {
+    return undefined
+  }
+  const doc = yaml.load(fs.readFileSync(filePath, 'utf8'))
+  Iif (!doc || typeof doc !== 'object') {
+    throw new Error(`Failed to parse ${filePath}`)
+  }
+  return doc as k8s.V1PodTemplateSpec
+}
+ 
+export function useKubeScheduler(): boolean {
+  return process.env[ENV_USE_KUBE_SCHEDULER] === 'true'
+}
+ 
+export enum PodPhase {
+  PENDING = 'Pending',
+  RUNNING = 'Running',
+  SUCCEEDED = 'Succeeded',
+  FAILED = 'Failed',
+  UNKNOWN = 'Unknown',
+  COMPLETED = 'Completed'
+}
+ 
+function mergeLists<T>(base?: T[], from?: T[]): T[] {
+  const b: T[] = base || []
+  Iif (!from?.length) {
+    return b
+  }
+  b.push(...from)
+  return b
+}
+ 
+export function fixArgs(args: string[]): string[] {
+  return shlex.split(args.join(' '))
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/tests/index.html b/packages/k8s/coverage/lcov-report/tests/index.html new file mode 100644 index 00000000..fa0dbbaf --- /dev/null +++ b/packages/k8s/coverage/lcov-report/tests/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for tests + + + + + + + + + +
+
+

All files tests

+
+ +
+ 29.57% + Statements + 21/71 +
+ + +
+ 0% + Branches + 0/3 +
+ + +
+ 5.55% + Functions + 1/18 +
+ + +
+ 28.57% + Lines + 20/70 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
test-setup.ts +
+
29.57%21/710%0/35.55%1/1828.57%20/70
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov-report/tests/test-setup.ts.html b/packages/k8s/coverage/lcov-report/tests/test-setup.ts.html new file mode 100644 index 00000000..4a47cad7 --- /dev/null +++ b/packages/k8s/coverage/lcov-report/tests/test-setup.ts.html @@ -0,0 +1,673 @@ + + + + + + Code coverage report for tests/test-setup.ts + + + + + + + + + +
+
+

All files / tests test-setup.ts

+
+ +
+ 29.57% + Statements + 21/71 +
+ + +
+ 0% + Branches + 0/3 +
+ + +
+ 5.55% + Functions + 1/18 +
+ + +
+ 28.57% + Lines + 20/70 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +1971x +1x +  +1x +1x +  +1x +  +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +1x + 
import * as k8s from '@kubernetes/client-node'
+import * as fs from 'fs'
+import { HookData } from 'hooklib/lib'
+import * as path from 'path'
+import { v4 as uuidv4 } from 'uuid'
+ 
+const kc = new k8s.KubeConfig()
+ 
+kc.loadFromDefault()
+ 
+const k8sApi = kc.makeApiClient(k8s.CoreV1Api)
+const k8sStorageApi = kc.makeApiClient(k8s.StorageV1Api)
+ 
+export class TestHelper {
+  private tempDirPath: string
+  private podName: string
+  constructor() {
+    this.tempDirPath = `${__dirname}/_temp/runner`
+    this.podName = uuidv4().replace(/-/g, '')
+  }
+ 
+  public async initialize(): Promise<void> {
+    process.env['ACTIONS_RUNNER_POD_NAME'] = `${this.podName}`
+    process.env['RUNNER_WORKSPACE'] = `${this.tempDirPath}/_work/repo`
+    process.env['RUNNER_TEMP'] = `${this.tempDirPath}/_work/_temp`
+    process.env['GITHUB_WORKSPACE'] = `${this.tempDirPath}/_work/repo/repo`
+    process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default'
+ 
+    fs.mkdirSync(`${this.tempDirPath}/_work/repo/repo`, { recursive: true })
+    fs.mkdirSync(`${this.tempDirPath}/externals`, { recursive: true })
+    fs.mkdirSync(process.env.RUNNER_TEMP, { recursive: true })
+ 
+    fs.copyFileSync(
+      path.resolve(`${__dirname}/../../../examples/example-script.sh`),
+      `${process.env.RUNNER_TEMP}/example-script.sh`
+    )
+ 
+    await this.cleanupK8sResources()
+    try {
+      await this.createTestVolume()
+      await this.createTestJobPod()
+    } catch (e) {
+      console.log(e)
+    }
+  }
+ 
+  public async cleanup(): Promise<void> {
+    try {
+      await this.cleanupK8sResources()
+      fs.rmSync(this.tempDirPath, { recursive: true })
+    } catch {}
+  }
+  public async cleanupK8sResources() {
+    await k8sApi
+      .deleteNamespacedPersistentVolumeClaim(
+        `${this.podName}-work`,
+        'default',
+        undefined,
+        undefined,
+        0
+      )
+      .catch(e => {})
+    await k8sApi.deletePersistentVolume(`${this.podName}-pv`).catch(e => {})
+    await k8sStorageApi.deleteStorageClass('local-storage').catch(e => {})
+    await k8sApi
+      .deleteNamespacedPod(this.podName, 'default', undefined, undefined, 0)
+      .catch(e => {})
+    await k8sApi
+      .deleteNamespacedPod(
+        `${this.podName}-workflow`,
+        'default',
+        undefined,
+        undefined,
+        0
+      )
+      .catch(e => {})
+  }
+  public createFile(fileName?: string): string {
+    const filePath = `${this.tempDirPath}/${fileName || uuidv4()}`
+    fs.writeFileSync(filePath, '')
+    return filePath
+  }
+ 
+  public removeFile(fileName: string): void {
+    const filePath = `${this.tempDirPath}/${fileName}`
+    fs.rmSync(filePath)
+  }
+ 
+  public async createTestJobPod() {
+    const container = {
+      name: 'nginx',
+      image: 'nginx:latest',
+      imagePullPolicy: 'IfNotPresent'
+    } as k8s.V1Container
+ 
+    const pod: k8s.V1Pod = {
+      metadata: {
+        name: this.podName
+      },
+      spec: {
+        restartPolicy: 'Never',
+        containers: [container]
+      }
+    } as k8s.V1Pod
+    await k8sApi.createNamespacedPod('default', pod)
+  }
+ 
+  public async createTestVolume() {
+    var sc: k8s.V1StorageClass = {
+      metadata: {
+        name: 'local-storage'
+      },
+      provisioner: 'kubernetes.io/no-provisioner',
+      volumeBindingMode: 'Immediate'
+    }
+    await k8sStorageApi.createStorageClass(sc)
+ 
+    var volume: k8s.V1PersistentVolume = {
+      metadata: {
+        name: `${this.podName}-pv`
+      },
+      spec: {
+        storageClassName: 'local-storage',
+        capacity: {
+          storage: '2Gi'
+        },
+        volumeMode: 'Filesystem',
+        accessModes: ['ReadWriteOnce'],
+        hostPath: {
+          path: `${this.tempDirPath}/_work`
+        }
+      }
+    }
+    await k8sApi.createPersistentVolume(volume)
+    var volumeClaim: k8s.V1PersistentVolumeClaim = {
+      metadata: {
+        name: `${this.podName}-work`
+      },
+      spec: {
+        accessModes: ['ReadWriteOnce'],
+        volumeMode: 'Filesystem',
+        storageClassName: 'local-storage',
+        volumeName: `${this.podName}-pv`,
+        resources: {
+          requests: {
+            storage: '1Gi'
+          }
+        }
+      }
+    }
+    await k8sApi.createNamespacedPersistentVolumeClaim('default', volumeClaim)
+  }
+ 
+  public getPrepareJobDefinition(): HookData {
+    const prepareJob = JSON.parse(
+      fs.readFileSync(
+        path.resolve(__dirname + '/../../../examples/prepare-job.json'),
+        'utf8'
+      )
+    )
+ 
+    prepareJob.args.container.userMountVolumes = undefined
+    prepareJob.args.container.registry = null
+    prepareJob.args.services.forEach(s => {
+      s.registry = null
+    })
+ 
+    return prepareJob
+  }
+ 
+  public getRunScriptStepDefinition(): HookData {
+    const runScriptStep = JSON.parse(
+      fs.readFileSync(
+        path.resolve(__dirname + '/../../../examples/run-script-step.json'),
+        'utf8'
+      )
+    )
+ 
+    runScriptStep.args.entryPointArgs[1] = `/__w/_temp/example-script.sh`
+    return runScriptStep
+  }
+ 
+  public getRunContainerStepDefinition(): HookData {
+    const runContainerStep = JSON.parse(
+      fs.readFileSync(
+        path.resolve(__dirname + '/../../../examples/run-container-step.json'),
+        'utf8'
+      )
+    )
+ 
+    runContainerStep.args.entryPointArgs[1] = `/__w/_temp/example-script.sh`
+    runContainerStep.args.userMountVolumes = undefined
+    runContainerStep.args.registry = null
+    return runContainerStep
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/k8s/coverage/lcov.info b/packages/k8s/coverage/lcov.info new file mode 100644 index 00000000..ccee93e4 --- /dev/null +++ b/packages/k8s/coverage/lcov.info @@ -0,0 +1,1846 @@ +TN: +SF:src/hooks/cleanup-job.ts +FN:3,cleanupJob +FNF:1 +FNH:0 +FNDA:0,cleanupJob +DA:1,1 +DA:3,1 +DA:4,0 +LF:3 +LH:2 +BRDA:4,0,0,0 +BRF:1 +BRH:0 +end_of_record +TN: +SF:src/hooks/constants.ts +FN:3,getRunnerPodName +FN:13,getJobPodName +FN:20,getStepPodName +FN:27,getVolumeClaimName +FN:35,getSecretName +FN:48,(anonymous_5) +FN:50,RunnerInstanceLabel +FN:54,(anonymous_7) +FN:58,(anonymous_8) +FN:62,(anonymous_9) +FNF:10 +FNH:1 +FNDA:0,getRunnerPodName +FNDA:0,getJobPodName +FNDA:0,getStepPodName +FNDA:0,getVolumeClaimName +FNDA:0,getSecretName +FNDA:1,(anonymous_5) +FNDA:0,RunnerInstanceLabel +FNDA:0,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:0,(anonymous_9) +DA:1,1 +DA:3,1 +DA:4,0 +DA:5,0 +DA:6,0 +DA:10,0 +DA:13,1 +DA:14,0 +DA:20,1 +DA:21,0 +DA:27,1 +DA:28,0 +DA:29,0 +DA:30,0 +DA:32,0 +DA:35,1 +DA:36,0 +DA:42,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:46,1 +DA:48,1 +DA:51,0 +DA:54,1 +DA:55,0 +DA:58,1 +DA:59,0 +DA:62,1 +DA:63,0 +DA:65,1 +LF:31 +LH:16 +BRDA:5,0,0,0 +BRDA:29,1,0,0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:src/hooks/index.ts +FNF:0 +FNH:0 +DA:1,1 +DA:2,1 +DA:3,1 +DA:4,1 +LF:4 +LH:4 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/hooks/prepare-job.ts +FN:31,prepareJob +FN:57,(anonymous_23) +FN:130,generateResponseFile +FN:148,(anonymous_25) +FN:167,(anonymous_26) +FN:170,(anonymous_27) +FN:171,(anonymous_28) +FN:189,copyExternalsToRoot +FN:200,createContainerSpec +FN:259,(anonymous_33) +FNF:10 +FNH:3 +FNDA:3,prepareJob +FNDA:0,(anonymous_23) +FNDA:0,generateResponseFile +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:0,(anonymous_28) +FNDA:3,copyExternalsToRoot +FNDA:3,createContainerSpec +FNDA:0,(anonymous_33) +DA:1,1 +DA:2,1 +DA:4,1 +DA:10,1 +DA:11,1 +DA:19,1 +DA:29,1 +DA:31,1 +DA:35,3 +DA:36,0 +DA:39,6 +DA:41,3 +DA:42,6 +DA:44,3 +DA:45,3 +DA:46,3 +DA:47,3 +DA:55,3 +DA:56,3 +DA:57,0 +DA:58,0 +DA:59,0 +DA:68,3 +DA:69,0 +DA:72,3 +DA:74,3 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:87,3 +DA:88,0 +DA:90,3 +DA:95,6 +DA:103,6 +DA:105,2 +DA:107,3 +DA:108,3 +DA:111,0 +DA:113,0 +DA:115,0 +DA:120,0 +DA:123,0 +DA:124,0 +DA:126,0 +DA:127,0 +DA:136,0 +DA:137,0 +DA:139,0 +DA:147,0 +DA:148,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:159,0 +DA:165,0 +DA:167,0 +DA:169,0 +DA:170,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:179,0 +DA:186,0 +DA:190,3 +DA:191,6 +DA:192,0 +DA:200,1 +DA:203,3 +DA:206,3 +DA:207,3 +DA:208,3 +DA:211,3 +DA:216,3 +DA:217,0 +DA:220,3 +DA:221,3 +DA:224,3 +DA:225,3 +DA:228,3 +DA:229,3 +DA:232,0 +DA:233,0 +DA:237,3 +DA:242,3 +DA:243,3 +DA:249,3 +DA:254,3 +DA:255,3 +DA:258,0 +DA:259,0 +DA:262,0 +DA:263,0 +DA:266,0 +LF:97 +LH:49 +BRDA:35,0,0,0 +BRDA:45,1,0,3 +BRDA:45,2,0,0 +BRDA:45,2,1,3 +BRDA:45,3,0,3 +BRDA:45,3,1,3 +BRDA:56,4,0,0 +BRDA:56,5,0,0 +BRDA:56,5,1,3 +BRDA:56,6,0,3 +BRDA:56,6,1,3 +BRDA:68,7,0,0 +BRDA:68,8,0,3 +BRDA:68,8,1,0 +BRDA:68,9,0,0 +BRDA:68,9,1,0 +BRDA:68,10,0,0 +BRDA:68,10,1,0 +BRDA:83,11,0,0 +BRDA:83,11,1,0 +BRDA:83,12,0,0 +BRDA:83,12,1,0 +BRDA:83,13,0,0 +BRDA:83,13,1,0 +BRDA:83,14,0,0 +BRDA:83,14,1,0 +BRDA:83,15,0,0 +BRDA:83,15,1,0 +BRDA:83,16,0,0 +BRDA:83,16,1,0 +BRDA:83,17,0,0 +BRDA:83,17,1,0 +BRDA:87,18,0,0 +BRDA:87,19,0,0 +BRDA:87,19,1,3 +BRDA:87,20,0,3 +BRDA:87,20,1,3 +BRDA:87,21,0,0 +BRDA:87,21,1,3 +BRDA:87,22,0,3 +BRDA:87,22,1,3 +BRDA:91,23,0,0 +BRDA:91,23,1,3 +BRDA:91,24,0,3 +BRDA:91,24,1,3 +BRDA:91,25,0,0 +BRDA:91,25,1,3 +BRDA:91,26,0,3 +BRDA:91,26,1,3 +BRDA:105,27,0,2 +BRDA:105,27,1,0 +BRDA:107,28,0,3 +BRDA:107,28,1,0 +BRDA:123,29,0,0 +BRDA:123,29,1,0 +BRDA:123,30,0,0 +BRDA:123,30,1,0 +BRDA:123,31,0,0 +BRDA:123,31,1,0 +BRDA:123,32,0,0 +BRDA:123,32,1,0 +BRDA:123,33,0,0 +BRDA:123,33,1,0 +BRDA:123,34,0,0 +BRDA:123,34,1,0 +BRDA:123,35,0,0 +BRDA:123,35,1,0 +BRDA:136,36,0,0 +BRDA:136,37,0,0 +BRDA:136,37,1,0 +BRDA:136,38,0,0 +BRDA:136,38,1,0 +BRDA:147,39,0,0 +BRDA:147,39,1,0 +BRDA:147,40,0,0 +BRDA:147,40,1,0 +BRDA:147,41,0,0 +BRDA:147,41,1,0 +BRDA:147,42,0,0 +BRDA:147,42,1,0 +BRDA:150,43,0,0 +BRDA:152,44,0,0 +BRDA:152,45,0,0 +BRDA:152,45,1,0 +BRDA:152,46,0,0 +BRDA:152,46,1,0 +BRDA:165,47,0,0 +BRDA:165,48,0,0 +BRDA:165,48,1,0 +BRDA:165,49,0,0 +BRDA:165,49,1,0 +BRDA:167,50,0,0 +BRDA:167,50,1,0 +BRDA:167,51,0,0 +BRDA:167,51,1,0 +BRDA:167,52,0,0 +BRDA:167,52,1,0 +BRDA:169,53,0,0 +BRDA:169,53,1,0 +BRDA:169,54,0,0 +BRDA:169,54,1,0 +BRDA:169,55,0,0 +BRDA:169,55,1,0 +BRDA:169,56,0,0 +BRDA:169,56,1,0 +BRDA:169,57,0,0 +BRDA:169,57,1,0 +BRDA:169,58,0,0 +BRDA:169,58,1,0 +BRDA:173,59,0,0 +BRDA:173,60,0,0 +BRDA:173,60,1,0 +BRDA:173,61,0,0 +BRDA:173,61,1,0 +BRDA:191,62,0,3 +BRDA:203,63,0,0 +BRDA:206,64,0,3 +BRDA:206,65,0,3 +BRDA:206,65,1,3 +BRDA:216,66,0,0 +BRDA:220,67,0,3 +BRDA:224,68,0,3 +BRDA:224,69,0,0 +BRDA:224,69,1,3 +BRDA:224,70,0,3 +BRDA:224,70,1,3 +BRDA:232,71,0,0 +BRDA:232,72,0,0 +BRDA:232,72,1,0 +BRDA:242,73,0,3 +BRDA:254,74,0,3 +BRDA:258,75,0,0 +BRDA:258,75,1,0 +BRDA:258,76,0,0 +BRDA:258,76,1,0 +BRDA:258,77,0,0 +BRDA:258,77,1,0 +BRDA:258,78,0,0 +BRDA:258,78,1,0 +BRDA:262,79,0,0 +BRF:140 +BRH:33 +end_of_record +TN: +SF:src/hooks/run-container-step.ts +FN:25,runContainerStep +FN:129,createContainerSpec +FN:162,(anonymous_23) +FNF:3 +FNH:0 +FNDA:0,runContainerStep +FNDA:0,createContainerSpec +FNDA:0,(anonymous_23) +DA:1,1 +DA:2,1 +DA:4,1 +DA:16,1 +DA:23,1 +DA:25,1 +DA:28,0 +DA:29,0 +DA:32,0 +DA:33,0 +DA:35,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:50,0 +DA:52,0 +DA:53,0 +DA:57,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:64,0 +DA:65,0 +DA:71,0 +DA:75,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:82,0 +DA:92,0 +DA:94,0 +DA:96,0 +DA:97,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:110,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:120,0 +DA:123,0 +DA:126,0 +DA:134,0 +DA:135,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:141,0 +DA:145,0 +DA:146,0 +DA:155,0 +DA:157,0 +DA:158,0 +DA:161,0 +DA:162,0 +DA:164,0 +DA:165,0 +DA:168,0 +LF:67 +LH:6 +BRDA:82,0,0,0 +BRDA:28,1,0,0 +BRDA:33,2,0,0 +BRDA:39,3,0,0 +BRDA:45,4,0,0 +BRDA:45,4,1,0 +BRDA:45,5,0,0 +BRDA:45,5,1,0 +BRDA:45,6,0,0 +BRDA:45,6,1,0 +BRDA:45,7,0,0 +BRDA:45,7,1,0 +BRDA:45,8,0,0 +BRDA:45,8,1,0 +BRDA:45,9,0,0 +BRDA:45,9,1,0 +BRDA:45,10,0,0 +BRDA:45,10,1,0 +BRDA:60,11,0,0 +BRDA:60,11,1,0 +BRDA:60,12,0,0 +BRDA:60,12,1,0 +BRDA:60,13,0,0 +BRDA:60,13,1,0 +BRDA:60,14,0,0 +BRDA:60,14,1,0 +BRDA:60,15,0,0 +BRDA:60,15,1,0 +BRDA:60,16,0,0 +BRDA:60,16,1,0 +BRDA:60,17,0,0 +BRDA:60,17,1,0 +BRDA:64,18,0,0 +BRDA:64,19,0,0 +BRDA:64,19,1,0 +BRDA:64,20,0,0 +BRDA:64,20,1,0 +BRDA:71,21,0,0 +BRDA:71,21,1,0 +BRDA:71,22,0,0 +BRDA:71,22,1,0 +BRDA:78,23,0,0 +BRDA:78,23,1,0 +BRDA:78,24,0,0 +BRDA:78,24,1,0 +BRDA:78,25,0,0 +BRDA:78,25,1,0 +BRDA:78,26,0,0 +BRDA:78,26,1,0 +BRDA:78,27,0,0 +BRDA:78,27,1,0 +BRDA:78,28,0,0 +BRDA:78,28,1,0 +BRDA:78,29,0,0 +BRDA:78,29,1,0 +BRDA:101,30,0,0 +BRDA:101,31,0,0 +BRDA:101,31,1,0 +BRDA:101,32,0,0 +BRDA:101,32,1,0 +BRDA:104,33,0,0 +BRDA:104,34,0,0 +BRDA:104,34,1,0 +BRDA:104,35,0,0 +BRDA:104,35,1,0 +BRDA:104,36,0,0 +BRDA:104,36,1,0 +BRDA:104,37,0,0 +BRDA:104,37,1,0 +BRDA:115,38,0,0 +BRDA:124,39,0,0 +BRDA:124,39,1,0 +BRDA:124,40,0,0 +BRDA:124,40,1,0 +BRDA:124,41,0,0 +BRDA:124,41,1,0 +BRDA:124,42,0,0 +BRDA:124,42,1,0 +BRDA:126,43,0,0 +BRDA:126,43,1,0 +BRDA:138,44,0,0 +BRDA:138,44,1,0 +BRDA:141,45,0,0 +BRDA:141,45,1,0 +BRDA:141,46,0,0 +BRDA:141,46,1,0 +BRDA:141,47,0,0 +BRDA:141,47,1,0 +BRDA:145,48,0,0 +BRDA:157,49,0,0 +BRDA:161,50,0,0 +BRDA:161,50,1,0 +BRDA:161,51,0,0 +BRDA:161,51,1,0 +BRDA:161,52,0,0 +BRDA:161,52,1,0 +BRDA:161,53,0,0 +BRDA:161,53,1,0 +BRDA:164,54,0,0 +BRF:99 +BRH:0 +end_of_record +TN: +SF:src/hooks/run-script-step.ts +FN:9,runScriptStep +FNF:1 +FNH:0 +FNDA:0,runScriptStep +DA:2,1 +DA:3,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:9,1 +DA:14,0 +DA:15,0 +DA:23,0 +DA:24,0 +DA:26,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:36,0 +LF:15 +LH:6 +BRDA:33,0,0,0 +BRDA:33,0,1,0 +BRDA:33,1,0,0 +BRDA:33,1,1,0 +BRDA:33,2,0,0 +BRDA:33,2,1,0 +BRDA:33,3,0,0 +BRDA:33,3,1,0 +BRDA:33,4,0,0 +BRDA:33,4,1,0 +BRDA:33,5,0,0 +BRDA:33,5,1,0 +BRDA:33,6,0,0 +BRDA:33,6,1,0 +BRF:14 +BRH:0 +end_of_record +TN: +SF:src/k8s/index.ts +FN:66,createPod +FN:134,createJob +FN:190,getContainerJobPodName +FN:218,deletePod +FN:228,execPodStep +FN:237,(anonymous_35) +FN:248,(anonymous_36) +FN:265,(anonymous_37) +FN:269,waitForJobToComplete +FN:283,createDockerSecret +FN:322,createSecretForEnvs +FN:347,deleteSecret +FN:351,pruneSecrets +FN:366,(anonymous_53) +FN:393,getUnrecoverableWaitingReasons +FN:408,getUnrecoverableEventReasons +FN:423,getUnrecoverableTerminatedReasons +FN:439,getContainerErrors +FN:459,getPodEventErrors +FN:493,getPodConditionErrors +FN:507,getContainerTerminatedErrors +FN:527,describePodFailure +FN:597,describePodWarningEvents +FN:617,(anonymous_69) +FN:622,(anonymous_70) +FN:626,(anonymous_71) +FN:629,(anonymous_72) +FN:643,waitForPodPhases +FN:696,getPrepareJobTimeoutSeconds +FN:715,readPod +FN:728,parsePodPhase +FN:735,isJobSucceeded +FN:744,getPodLogs +FN:750,(anonymous_87) +FN:755,(anonymous_88) +FN:764,(anonymous_89) +FN:764,(anonymous_90) +FN:767,prunePods +FN:782,(anonymous_94) +FN:787,getPodStatus +FN:794,isAuthPermissionsOK +FN:813,(anonymous_101) +FN:816,isPodContainerAlpine +FN:838,getCurrentNodeName +FN:848,getPodAffinity +FN:868,getPreferredPodAffinity +FN:896,namespace +FN:901,(anonymous_115) +FN:910,(anonymous_116) +FN:913,BackOffManager +FN:919,(anonymous_118) +FN:920,(anonymous_121) +FN:936,containerPorts +FN:958,(anonymous_123) +FN:978,getPodByName +FNF:55 +FNH:3 +FNDA:0,createPod +FNDA:0,createJob +FNDA:0,getContainerJobPodName +FNDA:0,deletePod +FNDA:0,execPodStep +FNDA:0,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:0,(anonymous_37) +FNDA:0,waitForJobToComplete +FNDA:0,createDockerSecret +FNDA:0,createSecretForEnvs +FNDA:0,deleteSecret +FNDA:0,pruneSecrets +FNDA:0,(anonymous_53) +FNDA:0,getUnrecoverableWaitingReasons +FNDA:0,getUnrecoverableEventReasons +FNDA:0,getUnrecoverableTerminatedReasons +FNDA:0,getContainerErrors +FNDA:0,getPodEventErrors +FNDA:0,getPodConditionErrors +FNDA:0,getContainerTerminatedErrors +FNDA:0,describePodFailure +FNDA:0,describePodWarningEvents +FNDA:0,(anonymous_69) +FNDA:0,(anonymous_70) +FNDA:0,(anonymous_71) +FNDA:0,(anonymous_72) +FNDA:0,waitForPodPhases +FNDA:3,getPrepareJobTimeoutSeconds +FNDA:0,readPod +FNDA:0,parsePodPhase +FNDA:0,isJobSucceeded +FNDA:0,getPodLogs +FNDA:0,(anonymous_87) +FNDA:0,(anonymous_88) +FNDA:0,(anonymous_89) +FNDA:0,(anonymous_90) +FNDA:0,prunePods +FNDA:0,(anonymous_94) +FNDA:0,getPodStatus +FNDA:0,isAuthPermissionsOK +FNDA:0,(anonymous_101) +FNDA:0,isPodContainerAlpine +FNDA:0,getCurrentNodeName +FNDA:0,getPodAffinity +FNDA:0,getPreferredPodAffinity +FNDA:0,namespace +FNDA:0,(anonymous_115) +FNDA:1,(anonymous_116) +FNDA:0,BackOffManager +FNDA:0,(anonymous_118) +FNDA:0,(anonymous_121) +FNDA:3,containerPorts +FNDA:0,(anonymous_123) +FNDA:0,getPodByName +DA:1,1 +DA:2,1 +DA:4,1 +DA:5,1 +DA:13,1 +DA:21,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:29,1 +DA:31,1 +DA:33,1 +DA:66,1 +DA:72,0 +DA:73,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:122,0 +DA:123,0 +DA:126,0 +DA:127,0 +DA:130,0 +DA:131,0 +DA:134,1 +DA:138,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:164,0 +DA:167,0 +DA:168,0 +DA:175,0 +DA:176,0 +DA:178,0 +DA:179,0 +DA:181,0 +DA:182,0 +DA:186,0 +DA:187,0 +DA:190,1 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:209,0 +DA:210,0 +DA:214,0 +DA:218,1 +DA:219,0 +DA:228,1 +DA:234,0 +DA:235,0 +DA:237,0 +DA:238,0 +DA:250,0 +DA:251,0 +DA:253,0 +DA:259,0 +DA:265,0 +DA:269,1 +DA:270,0 +DA:271,0 +DA:273,0 +DA:274,0 +DA:277,0 +DA:279,0 +DA:283,1 +DA:286,0 +DA:298,0 +DA:300,0 +DA:301,0 +DA:302,0 +DA:303,0 +DA:304,0 +DA:305,0 +DA:306,0 +DA:307,0 +DA:310,0 +DA:311,0 +DA:312,0 +DA:318,0 +DA:319,0 +DA:322,1 +DA:325,0 +DA:327,0 +DA:328,0 +DA:329,0 +DA:330,0 +DA:331,0 +DA:332,0 +DA:334,0 +DA:337,0 +DA:338,0 +DA:339,0 +DA:340,0 +DA:343,0 +DA:344,0 +DA:347,1 +DA:348,0 +DA:351,1 +DA:352,0 +DA:360,0 +DA:361,0 +DA:364,0 +DA:366,0 +DA:371,1 +DA:379,1 +DA:385,1 +DA:391,1 +DA:393,1 +DA:394,0 +DA:395,0 +DA:396,0 +DA:398,0 +DA:399,0 +DA:400,0 +DA:401,0 +DA:402,0 +DA:405,0 +DA:408,1 +DA:409,0 +DA:410,0 +DA:411,0 +DA:413,0 +DA:414,0 +DA:415,0 +DA:416,0 +DA:417,0 +DA:420,0 +DA:423,1 +DA:425,0 +DA:426,0 +DA:427,0 +DA:429,0 +DA:430,0 +DA:431,0 +DA:432,0 +DA:433,0 +DA:436,0 +DA:439,1 +DA:440,0 +DA:441,0 +DA:442,0 +DA:446,0 +DA:447,0 +DA:448,0 +DA:449,0 +DA:456,0 +DA:459,1 +DA:460,0 +DA:463,0 +DA:470,0 +DA:472,0 +DA:477,0 +DA:480,0 +DA:481,0 +DA:482,0 +DA:487,0 +DA:490,0 +DA:493,1 +DA:494,0 +DA:495,0 +DA:496,0 +DA:497,0 +DA:504,0 +DA:507,1 +DA:508,0 +DA:509,0 +DA:510,0 +DA:514,0 +DA:515,0 +DA:516,0 +DA:517,0 +DA:524,0 +DA:527,1 +DA:530,0 +DA:532,0 +DA:537,0 +DA:538,0 +DA:540,0 +DA:541,0 +DA:547,0 +DA:548,0 +DA:551,0 +DA:552,0 +DA:554,0 +DA:555,0 +DA:556,0 +DA:564,0 +DA:568,0 +DA:569,0 +DA:570,0 +DA:571,0 +DA:577,0 +DA:578,0 +DA:579,0 +DA:589,0 +DA:591,0 +DA:592,0 +DA:594,0 +DA:600,0 +DA:607,0 +DA:609,0 +DA:614,0 +DA:617,0 +DA:618,0 +DA:619,0 +DA:622,0 +DA:623,0 +DA:624,0 +DA:626,0 +DA:628,0 +DA:629,0 +DA:630,0 +DA:631,0 +DA:635,0 +DA:636,0 +DA:640,0 +DA:643,1 +DA:647,0 +DA:649,0 +DA:650,0 +DA:651,0 +DA:652,0 +DA:653,0 +DA:654,0 +DA:655,0 +DA:658,0 +DA:659,0 +DA:660,0 +DA:665,0 +DA:666,0 +DA:667,0 +DA:668,0 +DA:675,0 +DA:676,0 +DA:677,0 +DA:678,0 +DA:686,0 +DA:688,0 +DA:689,0 +DA:696,1 +DA:698,3 +DA:700,3 +DA:701,3 +DA:704,0 +DA:705,0 +DA:706,0 +DA:709,0 +DA:712,0 +DA:716,0 +DA:717,0 +DA:720,1 +DA:728,1 +DA:729,0 +DA:730,0 +DA:732,0 +DA:736,0 +DA:737,0 +DA:738,0 +DA:739,0 +DA:741,0 +DA:744,1 +DA:748,0 +DA:749,0 +DA:750,0 +DA:752,0 +DA:755,0 +DA:756,0 +DA:759,0 +DA:764,0 +DA:767,1 +DA:768,0 +DA:776,0 +DA:777,0 +DA:780,0 +DA:782,0 +DA:787,1 +DA:790,0 +DA:791,0 +DA:794,1 +DA:795,0 +DA:796,0 +DA:800,0 +DA:801,0 +DA:802,0 +DA:803,0 +DA:804,0 +DA:805,0 +DA:806,0 +DA:807,0 +DA:808,0 +DA:809,0 +DA:812,0 +DA:813,0 +DA:816,1 +DA:820,0 +DA:822,0 +DA:832,0 +DA:835,0 +DA:839,0 +DA:841,0 +DA:842,0 +DA:843,0 +DA:845,0 +DA:849,0 +DA:850,0 +DA:851,0 +DA:853,0 +DA:865,0 +DA:871,0 +DA:872,0 +DA:875,0 +DA:876,0 +DA:879,0 +DA:880,0 +DA:889,0 +DA:893,0 +DA:896,1 +DA:897,0 +DA:898,0 +DA:901,0 +DA:902,0 +DA:903,0 +DA:907,0 +DA:910,1 +DA:911,0 +DA:912,0 +DA:913,0 +DA:914,0 +DA:915,0 +DA:919,1 +DA:920,0 +DA:921,0 +DA:923,0 +DA:924,0 +DA:925,0 +DA:927,0 +DA:928,0 +DA:930,0 +DA:931,0 +DA:934,1 +DA:936,1 +DA:939,3 +DA:940,3 +DA:941,3 +DA:943,0 +DA:944,0 +DA:945,0 +DA:946,0 +DA:949,0 +DA:950,0 +DA:953,0 +DA:954,0 +DA:955,0 +DA:958,0 +DA:959,0 +DA:960,0 +DA:961,0 +DA:963,0 +DA:966,0 +DA:967,0 +DA:969,0 +DA:970,0 +DA:973,0 +DA:975,0 +DA:978,1 +DA:979,0 +DA:980,0 +LF:415 +LH:56 +BRDA:73,0,0,0 +BRDA:76,1,0,0 +BRDA:76,2,0,0 +BRDA:76,2,1,0 +BRDA:76,3,0,0 +BRDA:76,3,1,0 +BRDA:99,4,0,0 +BRDA:112,5,0,0 +BRDA:114,6,0,0 +BRDA:114,7,0,0 +BRDA:114,7,1,0 +BRDA:114,8,0,0 +BRDA:114,8,1,0 +BRDA:114,9,0,0 +BRDA:114,9,1,0 +BRDA:114,10,0,0 +BRDA:114,10,1,0 +BRDA:122,11,0,0 +BRDA:122,12,0,0 +BRDA:122,12,1,0 +BRDA:122,13,0,0 +BRDA:122,13,1,0 +BRDA:126,14,0,0 +BRDA:126,15,0,0 +BRDA:126,15,1,0 +BRDA:126,16,0,0 +BRDA:126,16,1,0 +BRDA:161,17,0,0 +BRDA:175,18,0,0 +BRDA:176,19,0,0 +BRDA:181,20,0,0 +BRDA:193,21,0,0 +BRDA:204,22,0,0 +BRDA:204,23,0,0 +BRDA:204,23,1,0 +BRDA:204,24,0,0 +BRDA:204,24,1,0 +BRDA:209,25,0,0 +BRDA:209,26,0,0 +BRDA:209,26,1,0 +BRDA:209,27,0,0 +BRDA:209,27,1,0 +BRDA:219,28,0,0 +BRDA:246,29,0,0 +BRDA:246,29,1,0 +BRDA:246,30,0,0 +BRDA:246,30,1,0 +BRDA:250,31,0,0 +BRDA:250,31,1,0 +BRDA:255,32,0,0 +BRDA:255,32,1,0 +BRDA:255,33,0,0 +BRDA:255,33,1,0 +BRDA:256,34,0,0 +BRDA:256,34,1,0 +BRDA:256,35,0,0 +BRDA:256,35,1,0 +BRDA:259,36,0,0 +BRDA:259,36,1,0 +BRDA:259,37,0,0 +BRDA:259,37,1,0 +BRDA:279,38,0,0 +BRDA:271,39,0,0 +BRDA:273,40,0,0 +BRDA:288,41,0,0 +BRDA:288,41,1,0 +BRDA:348,42,0,0 +BRDA:352,43,0,0 +BRDA:360,44,0,0 +BRDA:366,45,0,0 +BRDA:366,45,1,0 +BRDA:366,46,0,0 +BRDA:366,46,1,0 +BRDA:366,47,0,0 +BRDA:366,47,1,0 +BRDA:395,48,0,0 +BRDA:401,49,0,0 +BRDA:410,50,0,0 +BRDA:416,51,0,0 +BRDA:426,52,0,0 +BRDA:432,53,0,0 +BRDA:443,54,0,0 +BRDA:443,54,1,0 +BRDA:443,55,0,0 +BRDA:443,55,1,0 +BRDA:443,56,0,0 +BRDA:443,56,1,0 +BRDA:443,57,0,0 +BRDA:443,57,1,0 +BRDA:444,58,0,0 +BRDA:444,58,1,0 +BRDA:444,59,0,0 +BRDA:444,59,1,0 +BRDA:444,60,0,0 +BRDA:444,60,1,0 +BRDA:444,61,0,0 +BRDA:444,61,1,0 +BRDA:447,62,0,0 +BRDA:447,62,1,0 +BRDA:447,63,0,0 +BRDA:447,63,1,0 +BRDA:448,64,0,0 +BRDA:448,65,0,0 +BRDA:448,65,1,0 +BRDA:448,66,0,0 +BRDA:448,66,1,0 +BRDA:448,67,0,0 +BRDA:448,67,1,0 +BRDA:451,68,0,0 +BRDA:451,68,1,0 +BRDA:474,69,0,0 +BRDA:474,69,1,0 +BRDA:482,70,0,0 +BRDA:483,71,0,0 +BRDA:483,71,1,0 +BRDA:483,71,2,0 +BRDA:487,72,0,0 +BRDA:487,72,1,0 +BRDA:487,73,0,0 +BRDA:487,73,1,0 +BRDA:495,74,0,0 +BRDA:495,74,1,0 +BRDA:495,75,0,0 +BRDA:495,75,1,0 +BRDA:495,76,0,0 +BRDA:495,76,1,0 +BRDA:495,77,0,0 +BRDA:495,77,1,0 +BRDA:496,78,0,0 +BRDA:496,79,0,0 +BRDA:496,79,1,0 +BRDA:496,79,2,0 +BRDA:498,80,0,0 +BRDA:498,80,1,0 +BRDA:498,81,0,0 +BRDA:498,81,1,0 +BRDA:499,82,0,0 +BRDA:499,82,1,0 +BRDA:499,83,0,0 +BRDA:499,83,1,0 +BRDA:511,84,0,0 +BRDA:511,84,1,0 +BRDA:511,85,0,0 +BRDA:511,85,1,0 +BRDA:511,86,0,0 +BRDA:511,86,1,0 +BRDA:511,87,0,0 +BRDA:511,87,1,0 +BRDA:512,88,0,0 +BRDA:512,88,1,0 +BRDA:512,89,0,0 +BRDA:512,89,1,0 +BRDA:512,90,0,0 +BRDA:512,90,1,0 +BRDA:512,91,0,0 +BRDA:512,91,1,0 +BRDA:515,92,0,0 +BRDA:515,92,1,0 +BRDA:515,93,0,0 +BRDA:515,93,1,0 +BRDA:516,94,0,0 +BRDA:516,95,0,0 +BRDA:516,95,1,0 +BRDA:516,96,0,0 +BRDA:516,96,1,0 +BRDA:516,97,0,0 +BRDA:516,97,1,0 +BRDA:519,98,0,0 +BRDA:519,98,1,0 +BRDA:519,99,0,0 +BRDA:519,99,1,0 +BRDA:533,100,0,0 +BRDA:533,100,1,0 +BRDA:540,101,0,0 +BRDA:540,102,0,0 +BRDA:540,102,1,0 +BRDA:540,103,0,0 +BRDA:540,103,1,0 +BRDA:543,104,0,0 +BRDA:543,104,1,0 +BRDA:547,105,0,0 +BRDA:547,106,0,0 +BRDA:547,106,1,0 +BRDA:547,107,0,0 +BRDA:547,107,1,0 +BRDA:554,108,0,0 +BRDA:554,108,1,0 +BRDA:554,109,0,0 +BRDA:554,109,1,0 +BRDA:554,110,0,0 +BRDA:554,110,1,0 +BRDA:554,111,0,0 +BRDA:554,111,1,0 +BRDA:555,112,0,0 +BRDA:558,113,0,0 +BRDA:558,113,1,0 +BRDA:559,114,0,0 +BRDA:559,114,1,0 +BRDA:565,115,0,0 +BRDA:565,115,1,0 +BRDA:565,116,0,0 +BRDA:565,116,1,0 +BRDA:565,117,0,0 +BRDA:565,117,1,0 +BRDA:565,118,0,0 +BRDA:565,118,1,0 +BRDA:566,119,0,0 +BRDA:566,119,1,0 +BRDA:566,120,0,0 +BRDA:566,120,1,0 +BRDA:566,121,0,0 +BRDA:566,121,1,0 +BRDA:566,122,0,0 +BRDA:566,122,1,0 +BRDA:569,123,0,0 +BRDA:569,123,1,0 +BRDA:569,124,0,0 +BRDA:569,124,1,0 +BRDA:570,125,0,0 +BRDA:570,126,0,0 +BRDA:570,126,1,0 +BRDA:570,127,0,0 +BRDA:570,127,1,0 +BRDA:573,128,0,0 +BRDA:573,128,1,0 +BRDA:577,129,0,0 +BRDA:577,129,1,0 +BRDA:577,130,0,0 +BRDA:577,130,1,0 +BRDA:578,131,0,0 +BRDA:581,132,0,0 +BRDA:581,132,1,0 +BRDA:581,133,0,0 +BRDA:581,133,1,0 +BRDA:583,134,0,0 +BRDA:583,134,1,0 +BRDA:591,135,0,0 +BRDA:611,136,0,0 +BRDA:611,136,1,0 +BRDA:618,137,0,0 +BRDA:623,138,0,0 +BRDA:623,138,1,0 +BRDA:623,139,0,0 +BRDA:623,139,1,0 +BRDA:623,140,0,0 +BRDA:623,140,1,0 +BRDA:623,141,0,0 +BRDA:623,141,1,0 +BRDA:624,142,0,0 +BRDA:624,142,1,0 +BRDA:630,143,0,0 +BRDA:630,143,1,0 +BRDA:630,144,0,0 +BRDA:630,144,1,0 +BRDA:631,145,0,0 +BRDA:631,145,1,0 +BRDA:631,146,0,0 +BRDA:631,146,1,0 +BRDA:632,147,0,0 +BRDA:632,147,1,0 +BRDA:632,148,0,0 +BRDA:632,148,1,0 +BRDA:635,149,0,0 +BRDA:647,150,0,0 +BRDA:651,151,0,0 +BRDA:654,152,0,0 +BRDA:658,153,0,0 +BRDA:666,154,0,0 +BRDA:676,155,0,0 +BRDA:700,156,0,3 +BRDA:705,157,0,0 +BRDA:705,158,0,0 +BRDA:705,158,1,0 +BRDA:716,159,0,0 +BRDA:729,160,0,0 +BRDA:729,161,0,0 +BRDA:729,161,1,0 +BRDA:729,162,0,0 +BRDA:729,162,1,0 +BRDA:729,163,0,0 +BRDA:729,163,1,0 +BRDA:736,164,0,0 +BRDA:738,165,0,0 +BRDA:738,166,0,0 +BRDA:738,166,1,0 +BRDA:738,167,0,0 +BRDA:738,167,1,0 +BRDA:741,168,0,0 +BRDA:741,168,1,0 +BRDA:741,169,0,0 +BRDA:741,169,1,0 +BRDA:768,170,0,0 +BRDA:776,171,0,0 +BRDA:782,172,0,0 +BRDA:782,172,1,0 +BRDA:782,173,0,0 +BRDA:782,173,1,0 +BRDA:782,174,0,0 +BRDA:782,174,1,0 +BRDA:790,175,0,0 +BRDA:813,176,0,0 +BRDA:813,176,1,0 +BRDA:813,177,0,0 +BRDA:813,177,1,0 +BRDA:835,178,0,0 +BRDA:839,179,0,0 +BRDA:841,180,0,0 +BRDA:841,180,1,0 +BRDA:841,181,0,0 +BRDA:841,181,1,0 +BRDA:842,182,0,0 +BRDA:897,183,0,0 +BRDA:902,184,0,0 +BRDA:902,185,0,0 +BRDA:902,185,1,0 +BRDA:902,186,0,0 +BRDA:902,186,1,0 +BRDA:914,187,0,0 +BRDA:914,188,0,0 +BRDA:914,188,1,0 +BRDA:920,189,0,0 +BRDA:924,190,0,0 +BRDA:924,191,0,0 +BRDA:924,191,1,0 +BRDA:927,192,0,0 +BRDA:930,193,0,0 +BRDA:940,194,0,3 +BRDA:940,195,0,3 +BRDA:940,195,1,0 +BRDA:940,196,0,3 +BRDA:940,196,1,3 +BRDA:945,197,0,0 +BRDA:951,198,0,0 +BRDA:951,198,1,0 +BRDA:954,199,0,0 +BRDA:960,200,0,0 +BRDA:960,201,0,0 +BRDA:960,201,1,0 +BRDA:960,201,2,0 +BRDA:966,202,0,0 +BRDA:966,202,1,0 +BRDA:979,203,0,0 +BRF:342 +BRH:5 +end_of_record +TN: +SF:src/k8s/utils.ts +FN:18,containerVolumes +FN:112,writeEntryPointScript +FN:168,generateContainerName +FN:187,mergeContainerWithOptions +FN:215,mergePodSpecWithOptions +FN:223,(anonymous_11) +FN:235,mergeObjectMeta +FN:265,readExtensionFromFile +FN:277,useKubeScheduler +FN:281,(anonymous_15) +FN:290,mergeLists +FN:299,fixArgs +FNF:12 +FNH:4 +FNDA:3,containerVolumes +FNDA:0,writeEntryPointScript +FNDA:0,generateContainerName +FNDA:0,mergeContainerWithOptions +FNDA:0,mergePodSpecWithOptions +FNDA:0,(anonymous_11) +FNDA:0,mergeObjectMeta +FNDA:3,readExtensionFromFile +FNDA:0,useKubeScheduler +FNDA:1,(anonymous_15) +FNDA:0,mergeLists +FNDA:3,fixArgs +DA:2,1 +DA:3,1 +DA:4,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:9,1 +DA:10,1 +DA:12,1 +DA:13,1 +DA:15,1 +DA:16,1 +DA:18,1 +DA:19,6 +DA:20,3 +DA:21,6 +DA:23,3 +DA:30,3 +DA:31,3 +DA:32,0 +DA:33,0 +DA:34,0 +DA:56,0 +DA:59,3 +DA:60,0 +DA:63,3 +DA:81,3 +DA:82,3 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:94,0 +DA:98,0 +DA:101,0 +DA:109,0 +DA:112,1 +DA:119,0 +DA:120,0 +DA:123,0 +DA:124,0 +DA:126,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:137,0 +DA:141,0 +DA:149,0 +DA:152,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +DA:168,1 +DA:169,0 +DA:170,0 +DA:172,0 +DA:173,0 +DA:176,0 +DA:187,1 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:199,0 +DA:200,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:210,0 +DA:215,1 +DA:219,0 +DA:220,0 +DA:221,0 +DA:223,0 +DA:226,0 +DA:227,0 +DA:228,0 +DA:230,0 +DA:235,1 +DA:239,0 +DA:240,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:247,0 +DA:249,0 +DA:253,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:260,0 +DA:265,1 +DA:266,3 +DA:267,3 +DA:268,3 +DA:270,0 +DA:271,0 +DA:272,0 +DA:274,0 +DA:277,1 +DA:278,0 +DA:281,1 +DA:282,1 +DA:283,1 +DA:284,1 +DA:285,1 +DA:286,1 +DA:287,1 +DA:291,0 +DA:292,0 +DA:293,0 +DA:295,0 +DA:296,0 +DA:299,1 +DA:300,3 +LF:126 +LH:42 +BRDA:19,0,0,3 +BRDA:20,1,0,0 +BRDA:21,2,0,3 +BRDA:31,3,0,0 +BRDA:59,4,0,0 +BRDA:81,5,0,3 +BRDA:81,6,0,0 +BRDA:81,6,1,3 +BRDA:81,7,0,3 +BRDA:81,7,1,3 +BRDA:87,8,0,0 +BRDA:87,8,1,0 +BRDA:88,9,0,0 +BRDA:120,10,0,0 +BRDA:120,11,0,0 +BRDA:120,11,1,0 +BRDA:120,12,0,0 +BRDA:120,12,1,0 +BRDA:123,13,0,0 +BRDA:123,13,1,0 +BRDA:128,14,0,0 +BRDA:128,15,0,0 +BRDA:128,15,1,0 +BRDA:131,16,0,0 +BRDA:132,17,0,0 +BRDA:132,17,1,0 +BRDA:132,17,2,0 +BRDA:132,17,3,0 +BRDA:156,18,0,0 +BRDA:156,18,1,0 +BRDA:156,19,0,0 +BRDA:156,19,1,0 +BRDA:156,20,0,0 +BRDA:156,20,1,0 +BRDA:170,21,0,0 +BRDA:170,21,1,0 +BRDA:170,22,0,0 +BRDA:170,22,1,0 +BRDA:172,23,0,0 +BRDA:192,24,0,0 +BRDA:192,24,1,0 +BRDA:193,25,0,0 +BRDA:197,26,0,0 +BRDA:197,26,1,0 +BRDA:200,27,0,0 +BRDA:200,27,1,0 +BRDA:203,28,0,0 +BRDA:203,28,1,0 +BRDA:203,29,0,0 +BRDA:203,29,1,0 +BRDA:206,30,0,0 +BRDA:206,30,1,0 +BRDA:206,31,0,0 +BRDA:206,31,1,0 +BRDA:220,32,0,0 +BRDA:220,32,1,0 +BRDA:223,33,0,0 +BRDA:223,33,1,0 +BRDA:223,34,0,0 +BRDA:223,34,1,0 +BRDA:226,35,0,0 +BRDA:226,35,1,0 +BRDA:226,36,0,0 +BRDA:226,36,1,0 +BRDA:239,37,0,0 +BRDA:239,38,0,0 +BRDA:239,38,1,0 +BRDA:239,39,0,0 +BRDA:239,39,1,0 +BRDA:239,40,0,0 +BRDA:239,40,1,0 +BRDA:239,41,0,0 +BRDA:239,41,1,0 +BRDA:239,42,0,0 +BRDA:239,42,1,0 +BRDA:244,43,0,0 +BRDA:244,44,0,0 +BRDA:244,44,1,0 +BRDA:244,45,0,0 +BRDA:244,45,1,0 +BRDA:246,46,0,0 +BRDA:246,47,0,0 +BRDA:246,47,1,0 +BRDA:246,48,0,0 +BRDA:246,48,1,0 +BRDA:246,49,0,0 +BRDA:246,49,1,0 +BRDA:246,50,0,0 +BRDA:246,50,1,0 +BRDA:253,51,0,0 +BRDA:253,52,0,0 +BRDA:253,52,1,0 +BRDA:253,53,0,0 +BRDA:253,53,1,0 +BRDA:255,54,0,0 +BRDA:255,55,0,0 +BRDA:255,55,1,0 +BRDA:255,56,0,0 +BRDA:255,56,1,0 +BRDA:255,57,0,0 +BRDA:255,57,1,0 +BRDA:255,58,0,0 +BRDA:255,58,1,0 +BRDA:267,59,0,3 +BRDA:271,60,0,0 +BRDA:271,61,0,0 +BRDA:271,61,1,0 +BRDA:281,62,0,1 +BRDA:281,62,1,1 +BRDA:291,63,0,0 +BRDA:291,63,1,0 +BRDA:292,64,0,0 +BRDA:292,65,0,0 +BRDA:292,65,1,0 +BRDA:292,66,0,0 +BRDA:292,66,1,0 +BRF:116 +BRH:9 +end_of_record +TN: +SF:tests/test-setup.ts +FN:14,(anonymous_19) +FN:17,TestHelper +FN:22,(anonymous_21) +FN:47,(anonymous_24) +FN:53,(anonymous_27) +FN:62,(anonymous_30) +FN:63,(anonymous_31) +FN:64,(anonymous_32) +FN:67,(anonymous_33) +FN:76,(anonymous_34) +FN:78,(anonymous_35) +FN:84,(anonymous_36) +FN:89,(anonymous_37) +FN:108,(anonymous_40) +FN:154,(anonymous_43) +FN:164,(anonymous_44) +FN:171,(anonymous_45) +FN:183,(anonymous_46) +FNF:18 +FNH:1 +FNDA:1,(anonymous_19) +FNDA:0,TestHelper +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_27) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:0,(anonymous_33) +FNDA:0,(anonymous_34) +FNDA:0,(anonymous_35) +FNDA:0,(anonymous_36) +FNDA:0,(anonymous_37) +FNDA:0,(anonymous_40) +FNDA:0,(anonymous_43) +FNDA:0,(anonymous_44) +FNDA:0,(anonymous_45) +FNDA:0,(anonymous_46) +DA:1,1 +DA:2,1 +DA:4,1 +DA:5,1 +DA:7,1 +DA:9,1 +DA:11,1 +DA:12,1 +DA:14,1 +DA:18,0 +DA:19,0 +DA:22,1 +DA:23,0 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:33,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:47,1 +DA:49,0 +DA:50,0 +DA:53,1 +DA:54,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:68,0 +DA:78,1 +DA:79,0 +DA:80,0 +DA:81,0 +DA:84,1 +DA:85,0 +DA:86,0 +DA:89,1 +DA:90,0 +DA:96,0 +DA:105,0 +DA:108,1 +DA:109,0 +DA:116,0 +DA:118,0 +DA:134,0 +DA:135,0 +DA:151,0 +DA:154,1 +DA:155,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:168,0 +DA:171,1 +DA:172,0 +DA:179,0 +DA:180,0 +DA:183,1 +DA:184,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:196,1 +LF:70 +LH:20 +BRDA:54,0,0,0 +BRDA:79,1,0,0 +BRDA:79,1,1,0 +BRF:3 +BRH:0 +end_of_record diff --git a/packages/k8s/package-lock.json b/packages/k8s/package-lock.json index 079716a8..ba8653dd 100644 --- a/packages/k8s/package-lock.json +++ b/packages/k8s/package-lock.json @@ -26,22 +26,6 @@ "typescript": "^4.6.3" } }, - "../hooklib": { - "version": "0.1.0", - "license": "MIT", - "dependencies": { - "@actions/core": "^1.9.1" - }, - "devDependencies": { - "@types/node": "^17.0.23", - "@typescript-eslint/parser": "^5.18.0", - "@zeit/ncc": "^0.22.3", - "eslint": "^8.12.0", - "eslint-plugin-github": "^4.3.6", - "prettier": "^2.6.2", - "typescript": "^4.6.3" - } - }, "node_modules/@actions/core": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", @@ -2459,8 +2443,12 @@ } }, "node_modules/hooklib": { - "resolved": "../hooklib", - "link": true + "version": "0.1.0", + "resolved": "file:../hooklib", + "license": "MIT", + "dependencies": { + "@actions/core": "^1.9.1" + } }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", @@ -6995,16 +6983,9 @@ "dev": true }, "hooklib": { - "version": "file:../hooklib", + "version": "0.1.0", "requires": { - "@actions/core": "^1.9.1", - "@types/node": "^17.0.23", - "@typescript-eslint/parser": "^5.18.0", - "@zeit/ncc": "^0.22.3", - "eslint": "^8.12.0", - "eslint-plugin-github": "^4.3.6", - "prettier": "^2.6.2", - "typescript": "^4.6.3" + "@actions/core": "^1.9.1" } }, "html-encoding-sniffer": { diff --git a/packages/k8s/src/hooks/prepare-job.ts b/packages/k8s/src/hooks/prepare-job.ts index 1dc7ad3c..3072e8dc 100644 --- a/packages/k8s/src/hooks/prepare-job.ts +++ b/packages/k8s/src/hooks/prepare-job.ts @@ -99,8 +99,13 @@ export async function prepareJob( getPrepareJobTimeoutSeconds() ) } catch (err) { - await prunePods() - throw new Error(`pod failed to come online with error: ${err}`) + try { + await prunePods() + } catch (pruneErr) { + core.error(`Failed to prune pods: ${pruneErr instanceof Error ? pruneErr.message : String(pruneErr)}`) + } + const message = err instanceof Error ? err.message : String(err) + throw new Error(`pod failed to come online:\n${message}`) } core.debug('Job pod is ready for traffic') diff --git a/packages/k8s/src/hooks/run-container-step.ts b/packages/k8s/src/hooks/run-container-step.ts index e5261537..e544cd63 100644 --- a/packages/k8s/src/hooks/run-container-step.ts +++ b/packages/k8s/src/hooks/run-container-step.ts @@ -4,7 +4,10 @@ import { RunContainerStepArgs } from 'hooklib' import { createJob, createSecretForEnvs, + describePodFailure, getContainerJobPodName, + getContainerTerminatedErrors, + getPodByName, getPodLogs, getPodStatus, waitForJobToComplete, @@ -106,6 +109,17 @@ export async function runContainerStep( ) return 1 } + + const pod = await getPodByName(podName) + const terminatedErrors = getContainerTerminatedErrors(pod) + if (terminatedErrors.length > 0) { + const details = await describePodFailure(podName) + core.error( + `Pod ${podName} has unrecoverable container errors:\n${terminatedErrors.join('\n')}\n${details}` + ) + return 1 + } + const exitCode = status.containerStatuses[status.containerStatuses.length - 1].state ?.terminated?.exitCode diff --git a/packages/k8s/src/k8s/index.ts b/packages/k8s/src/k8s/index.ts index 249a0605..134e1e01 100644 --- a/packages/k8s/src/k8s/index.ts +++ b/packages/k8s/src/k8s/index.ts @@ -368,6 +368,278 @@ export async function pruneSecrets(): Promise { ) } +export const UNRECOVERABLE_WAITING_REASONS = new Set([ + 'ImagePullBackOff', + 'ErrImagePull', + 'InvalidImageName', + 'CreateContainerConfigError', + 'CreateContainerError' +]) + +export const UNRECOVERABLE_EVENT_REASONS = new Set([ + 'FailedScheduling', + 'FailedBinding', + 'FailedMount' +]) + +export const UNRECOVERABLE_TERMINATED_REASONS = new Set([ + 'OOMKilled', + 'Error', + 'FailedPostStartHookError' +]) + +const MAX_DIAGNOSTIC_EVENTS = 10 + +export function getUnrecoverableWaitingReasons(): Set { + const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS'] + if (!extra) { + return UNRECOVERABLE_WAITING_REASONS + } + const reasons = new Set(UNRECOVERABLE_WAITING_REASONS) + for (const reason of extra.split(',')) { + const trimmed = reason.trim() + if (trimmed) { + reasons.add(trimmed) + } + } + return reasons +} + +export function getUnrecoverableEventReasons(): Set { + const extra = process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS'] + if (!extra) { + return UNRECOVERABLE_EVENT_REASONS + } + const reasons = new Set(UNRECOVERABLE_EVENT_REASONS) + for (const reason of extra.split(',')) { + const trimmed = reason.trim() + if (trimmed) { + reasons.add(trimmed) + } + } + return reasons +} + +export function getUnrecoverableTerminatedReasons(): Set { + const extra = + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] + if (!extra) { + return UNRECOVERABLE_TERMINATED_REASONS + } + const reasons = new Set(UNRECOVERABLE_TERMINATED_REASONS) + for (const reason of extra.split(',')) { + const trimmed = reason.trim() + if (trimmed) { + reasons.add(trimmed) + } + } + return reasons +} + +export function getContainerErrors(pod: k8s.V1Pod): string[] { + const errors: string[] = [] + const unrecoverableReasons = getUnrecoverableWaitingReasons() + const allStatuses = [ + ...(pod.status?.initContainerStatuses ?? []), + ...(pod.status?.containerStatuses ?? []) + ] + for (const cs of allStatuses) { + const waiting = cs.state?.waiting + if (waiting?.reason && unrecoverableReasons.has(waiting.reason)) { + errors.push( + `container "${cs.name}": ${waiting.reason}${ + waiting.message ? ` - ${waiting.message}` : '' + }` + ) + } + } + return errors +} + +export async function getPodEventErrors(podName: string): Promise { + const unrecoverableReasons = getUnrecoverableEventReasons() + let items: k8s.CoreV1Event[] + try { + const { body } = await k8sApi.listNamespacedEvent( + namespace(), + undefined, + undefined, + undefined, + `involvedObject.name=${podName}` + ) + items = body.items + } catch (err) { + core.debug( + `Could not list events for pod ${podName} (the 'events' permission may be missing): ${ + err instanceof Error ? err.message : String(err) + }` + ) + return [] + } + + const errors: string[] = [] + for (const e of items) { + if ( + e.type === 'Warning' && + e.reason && + unrecoverableReasons.has(e.reason) + ) { + errors.push(`Event [Warning] ${e.reason}: ${e.message ?? ''}`) + } + } + return errors +} + +export function getPodConditionErrors(pod: k8s.V1Pod): string[] { + const errors: string[] = [] + for (const cond of pod.status?.conditions ?? []) { + if (cond.type === 'PodScheduled' && cond.status === 'False' && cond.reason === 'Unschedulable') { + errors.push( + `Condition ${cond.type}=False (reason: ${cond.reason ?? ''}): ${ + cond.message ?? '' + }` + ) + } + } + return errors +} + +export function getContainerTerminatedErrors(pod: k8s.V1Pod): string[] { + const errors: string[] = [] + const unrecoverableReasons = getUnrecoverableTerminatedReasons() + const allStatuses = [ + ...(pod.status?.initContainerStatuses ?? []), + ...(pod.status?.containerStatuses ?? []) + ] + for (const cs of allStatuses) { + const terminated = cs.state?.terminated + if (terminated?.reason && unrecoverableReasons.has(terminated.reason)) { + errors.push( + `container "${cs.name}": ${terminated.reason} (exit code ${terminated.exitCode}) - ${ + terminated.message ?? '' + }` + ) + } + } + return errors +} + +export async function describePodFailure(podName: string): Promise { + let pod: k8s.V1Pod + try { + pod = await readPod(podName) + } catch (err) { + return `Could not read pod ${podName} for diagnostics: ${ + err instanceof Error ? err.message : String(err) + }` + } + + const lines: string[] = [] + const status = pod.status + + if (status?.phase) { + lines.push( + `Phase: ${status.phase}${ + status.reason ? ` (reason: ${status.reason})` : '' + }` + ) + } + if (status?.message) { + lines.push(`Message: ${status.message}`) + } + + const separator = '────────────────────────────────────────────────────────────' + lines.push(separator) + + for (const cond of status?.conditions ?? []) { + if (cond.status === 'False') { + lines.push( + ` ✗ ${cond.type}=False${ + cond.reason ? ` (${cond.reason})` : '' + }${cond.message ? `: ${cond.message}` : ''}` + ) + } + } + + const allStatuses = [ + ...(status?.initContainerStatuses ?? []), + ...(status?.containerStatuses ?? []) + ] + for (const cs of allStatuses) { + const waiting = cs.state?.waiting + if (waiting?.reason) { + lines.push( + ` ✗ container "${cs.name}": ${waiting.reason}${ + waiting.message ? `\n ${waiting.message}` : '' + }` + ) + } + const terminated = cs.state?.terminated + if (terminated) { + lines.push( + ` ✗ container "${cs.name}": ${ + terminated.reason ?? 'Unknown' + } (exit code ${terminated.exitCode})${ + terminated.message ? `\n ${terminated.message}` : '' + }` + ) + } + } + + lines.push(...(await describePodWarningEvents(podName))) + + if (!lines.length) { + return `No additional diagnostic information available for pod ${podName}` + } + return lines.join('\n') +} + +async function describePodWarningEvents(podName: string): Promise { + let items: k8s.CoreV1Event[] + try { + const { body } = await k8sApi.listNamespacedEvent( + namespace(), + undefined, + undefined, + undefined, + `involvedObject.name=${podName}` + ) + items = body.items + } catch (err) { + core.debug( + `Could not list events for pod ${podName} (the 'events' permission may be missing): ${ + err instanceof Error ? err.message : String(err) + }` + ) + return [] + } + + const warnings = items.filter(e => e.type === 'Warning') + if (!warnings.length) { + return [] + } + + const eventTime = (e: k8s.CoreV1Event): number => { + const t = e.lastTimestamp ?? e.eventTime ?? e.firstTimestamp + return t ? new Date(t).getTime() : 0 + } + warnings.sort((a, b) => eventTime(a) - eventTime(b)) + + const recent = warnings.slice(-MAX_DIAGNOSTIC_EVENTS) + const lines = recent.map(e => { + const count = e.count && e.count > 1 ? ` (x${e.count})` : '' + return `Event [Warning] ${e.reason ?? ''}${count}: ${ + e.message ?? '' + }`.trim() + }) + if (warnings.length > recent.length) { + lines.unshift( + `(showing ${recent.length} of ${warnings.length} warning events)` + ) + } + return lines +} + export async function waitForPodPhases( podName: string, awaitingPhases: Set, @@ -376,22 +648,48 @@ export async function waitForPodPhases( ): Promise { const backOffManager = new BackOffManager(maxTimeSeconds) let phase: PodPhase = PodPhase.UNKNOWN - try { - while (true) { - phase = await getPodPhase(podName) - if (awaitingPhases.has(phase)) { - return - } + while (true) { + const pod = await readPod(podName) + phase = parsePodPhase(pod) + if (awaitingPhases.has(phase)) { + return + } - if (!backOffPhases.has(phase)) { - throw new Error( - `Pod ${podName} is unhealthy with phase status ${phase}` - ) - } + if (!backOffPhases.has(phase)) { + const details = await describePodFailure(podName) + throw new Error( + `Pod ${podName} is unhealthy with phase status ${phase}\n${details}` + ) + } + + const containerErrors = getContainerErrors(pod) + if (containerErrors.length > 0) { + const details = await describePodFailure(podName) + throw new Error( + `Pod ${podName} has unrecoverable container errors: ${containerErrors.join( + '; ' + )}\n${details}` + ) + } + + const conditionErrors = getPodConditionErrors(pod) + if (conditionErrors.length > 0) { + const details = await describePodFailure(podName) + throw new Error( + `Pod ${podName} has unrecoverable condition errors: ${conditionErrors.join( + '; ' + )}\n${details}` + ) + } + + try { await backOffManager.backOff() + } catch (error) { + const details = await describePodFailure(podName) + throw new Error( + `Pod ${podName} is unhealthy: timed out after ${maxTimeSeconds}s in phase ${phase}\n${details}` + ) } - } catch (error) { - throw new Error(`Pod ${podName} is unhealthy with phase status ${phase}`) } } @@ -414,21 +712,24 @@ export function getPrepareJobTimeoutSeconds(): number { return timeoutSeconds } -async function getPodPhase(podName: string): Promise { - const podPhaseLookup = new Set([ - PodPhase.PENDING, - PodPhase.RUNNING, - PodPhase.SUCCEEDED, - PodPhase.FAILED, - PodPhase.UNKNOWN - ]) +async function readPod(podName: string): Promise { const { body } = await k8sApi.readNamespacedPod(podName, namespace()) - const pod = body + return body +} + +const podPhaseLookup = new Set([ + PodPhase.PENDING, + PodPhase.RUNNING, + PodPhase.SUCCEEDED, + PodPhase.FAILED, + PodPhase.UNKNOWN +]) +export function parsePodPhase(pod: k8s.V1Pod): PodPhase { if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) { return PodPhase.UNKNOWN } - return pod.status?.phase as PodPhase + return pod.status.phase as PodPhase } async function isJobSucceeded(jobName: string): Promise { diff --git a/packages/k8s/tests/prepare-job-test.ts b/packages/k8s/tests/prepare-job-test.ts index ca94e6c5..a9dddf79 100644 --- a/packages/k8s/tests/prepare-job-test.ts +++ b/packages/k8s/tests/prepare-job-test.ts @@ -9,10 +9,13 @@ import { generateContainerName, readExtensionFromFile } from '../src/k8s/utils' -import { getPodByName } from '../src/k8s' +import { getPodByName, prunePods, waitForPodPhases } from '../src/k8s' import { V1Container } from '@kubernetes/client-node' import * as yaml from 'js-yaml' import { JOB_CONTAINER_NAME } from '../src/hooks/constants' +import * as io from '@actions/io' +import * as k8sModule from '../src/k8s' +import * as coreModule from '@actions/core' jest.useRealTimers() @@ -244,3 +247,93 @@ describe('Prepare job', () => { } ) }) + +describe('prepareJob error handling - prunePods try-catch', () => { + let coreErrorSpy: jest.SpyInstance + let prunePodsSpy: jest.SpyInstance + let waitForPodPhasesSpy: jest.SpyInstance + let createPodSpy: jest.SpyInstance + let ioCpSpy: jest.SpyInstance + + beforeEach(() => { + process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default' + delete process.env[ENV_HOOK_TEMPLATE_PATH] + delete process.env['RUNNER_WORKSPACE'] + + coreErrorSpy = jest.spyOn(coreModule, 'error').mockImplementation(() => {}) + prunePodsSpy = jest.spyOn(k8sModule, 'prunePods').mockResolvedValue(undefined) + createPodSpy = jest.spyOn(k8sModule, 'createPod').mockResolvedValue({ + metadata: { name: 'test-pod' } + } as any) + waitForPodPhasesSpy = jest + .spyOn(k8sModule, 'waitForPodPhases') + .mockRejectedValue(new Error('pod failed to come online: unrecoverable condition')) + ioCpSpy = jest.spyOn(io, 'cp').mockResolvedValue(undefined) + }) + + afterEach(() => { + jest.restoreAllMocks() + delete process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] + }) + + it('propagates original waitForPodPhases error even when prunePods succeeds', async () => { + const args = { + container: { + image: 'test-image:latest', + environmentVariables: {} + }, + services: [] + } as any + + await expect(prepareJob(args, '/tmp/test-output.json')).rejects.toThrow( + 'pod failed to come online' + ) + expect(prunePodsSpy).toHaveBeenCalledTimes(2) + }) + + it('propagates original waitForPodPhases error even when prunePods throws', async () => { + prunePodsSpy + .mockResolvedValueOnce(undefined) + .mockRejectedValueOnce(new Error('k8s API error: forbidden')) + + const args = { + container: { + image: 'test-image:latest', + environmentVariables: {} + }, + services: [] + } as any + + await expect(prepareJob(args, '/tmp/test-output.json')).rejects.toThrow( + 'pod failed to come online: unrecoverable condition' + ) + expect(coreErrorSpy).toHaveBeenCalledWith( + expect.stringContaining('Failed to prune pods') + ) + }) + + it('logs prunePods error via core.error without masking original error message', async () => { + prunePodsSpy + .mockResolvedValueOnce(undefined) + .mockRejectedValueOnce(new Error('k8s API error: forbidden')) + + const args = { + container: { + image: 'test-image:latest', + environmentVariables: {} + }, + services: [] + } as any + + try { + await prepareJob(args, '/tmp/test-output.json') + } catch (err) { + expect((err as Error).message).toContain('pod failed to come online') + expect((err as Error).message).toContain('unrecoverable condition') + expect((err as Error).message).not.toContain('k8s API error: forbidden') + } + expect(coreErrorSpy).toHaveBeenCalledWith( + expect.stringContaining('k8s API error: forbidden') + ) + }) +}) diff --git a/packages/k8s/tests/run-container-step-test.ts b/packages/k8s/tests/run-container-step-test.ts index 51a33b76..5c3fe669 100644 --- a/packages/k8s/tests/run-container-step-test.ts +++ b/packages/k8s/tests/run-container-step-test.ts @@ -4,6 +4,17 @@ import { ENV_HOOK_TEMPLATE_PATH } from '../src/k8s/utils' import * as fs from 'fs' import * as yaml from 'js-yaml' import { JOB_CONTAINER_EXTENSION_NAME } from '../src/hooks/constants' +import * as k8s from '@kubernetes/client-node' +import { + getContainerTerminatedErrors, + getUnrecoverableTerminatedReasons, + UNRECOVERABLE_TERMINATED_REASONS +} from '../src/k8s' +import * as k8sModule from '../src/k8s' +import * as coreModule from '@actions/core' +import { RunContainerStepArgs } from 'hooklib' + +import { PodPhase } from '../src/k8s/utils' jest.useRealTimers() @@ -11,6 +22,34 @@ let testHelper: TestHelper let runContainerStepData: any +function buildPod( + phase?: string, + opts: { + containerStatuses?: k8s.V1ContainerStatus[] + initContainerStatuses?: k8s.V1ContainerStatus[] + } = {} +): k8s.V1Pod { + return { + status: { + phase, + containerStatuses: opts.containerStatuses, + initContainerStatuses: opts.initContainerStatuses + } + } as k8s.V1Pod +} + +function terminatedContainer( + name: string, + reason?: string, + exitCode?: number, + message?: string +): k8s.V1ContainerStatus { + return { + name, + state: { terminated: { reason, exitCode, message } } + } as k8s.V1ContainerStatus +} + describe('Run container step', () => { beforeEach(async () => { testHelper = new TestHelper() @@ -90,3 +129,347 @@ describe('Run container step', () => { ).resolves.not.toThrow() }) }) + +describe('getContainerTerminatedErrors', () => { + it('returns no errors when there are no container statuses', () => { + expect(getContainerTerminatedErrors(buildPod(PodPhase.FAILED))).toEqual( + [] + ) + expect(getContainerTerminatedErrors({} as k8s.V1Pod)).toEqual([]) + }) + + it('returns no errors when containers have running state', () => { + const pod = buildPod(PodPhase.RUNNING, { + containerStatuses: [ + { name: 'job', state: { running: {} } } as k8s.V1ContainerStatus + ] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([]) + }) + + it('returns no errors for Completed terminated reason', () => { + const pod = buildPod(PodPhase.SUCCEEDED, { + containerStatuses: [terminatedContainer('job', 'Completed', 0)] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([]) + }) + + it('detects every unrecoverable terminated reason', () => { + for (const reason of Array.from(UNRECOVERABLE_TERMINATED_REASONS)) { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [terminatedContainer('job', reason, 1)] + }) + const errors = getContainerTerminatedErrors(pod) + expect(errors.length).toBe(1) + expect(errors[0]).toContain(reason) + expect(errors[0]).toContain('exit code 1') + } + }) + + it('detects OOMKilled with message', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'OOMKilled', 137, 'Memory limit exceeded') + ] + }) + const errors = getContainerTerminatedErrors(pod) + expect(errors).toEqual([ + 'container "job": OOMKilled (exit code 137) - Memory limit exceeded' + ]) + }) + + it('detects Error with non-zero exit code', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'Error', 1, 'container crashed') + ] + }) + const errors = getContainerTerminatedErrors(pod) + expect(errors).toEqual([ + 'container "job": Error (exit code 1) - container crashed' + ]) + }) + + it('detects FailedPostStartHookError', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer( + 'job', + 'FailedPostStartHookError', + 137, + 'postStart hook failed' + ) + ] + }) + const errors = getContainerTerminatedErrors(pod) + expect(errors).toEqual([ + 'container "job": FailedPostStartHookError (exit code 137) - postStart hook failed' + ]) + }) + + it('inspects init containers as well as regular containers', () => { + const pod = buildPod(PodPhase.FAILED, { + initContainerStatuses: [terminatedContainer('init', 'OOMKilled', 137)], + containerStatuses: [terminatedContainer('job', 'Error', 1)] + }) + const errors = getContainerTerminatedErrors(pod) + expect(errors.length).toBe(2) + expect(errors[0]).toContain('init') + expect(errors[1]).toContain('job') + }) + + it('returns empty for terminated reason not in the set', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [terminatedContainer('job', 'SomeOtherReason', 1)] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([]) + }) +}) + +describe('getUnrecoverableTerminatedReasons', () => { + afterEach(() => { + delete process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] + }) + + it('returns the built-in defaults when the env var is unset', () => { + expect(getUnrecoverableTerminatedReasons()).toEqual( + UNRECOVERABLE_TERMINATED_REASONS + ) + }) + + it('adds extra reasons from the env var without dropping the defaults', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] = + 'CustomReason, AnotherReason' + const reasons = getUnrecoverableTerminatedReasons() + for (const builtin of Array.from(UNRECOVERABLE_TERMINATED_REASONS)) { + expect(reasons.has(builtin)).toBe(true) + } + expect(reasons.has('CustomReason')).toBe(true) + expect(reasons.has('AnotherReason')).toBe(true) + }) + + it('filters empty strings from env var', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] = + ', CrashLoopBackOff, ' + const reasons = getUnrecoverableTerminatedReasons() + expect(reasons.has('CrashLoopBackOff')).toBe(true) + expect(reasons.has('')).toBe(false) + }) +}) + +describe('runContainerStep includes describePodFailure output for terminated errors', () => { + let coreErrorSpy: jest.SpyInstance + let createJobSpy: jest.SpyInstance + let getContainerJobPodNameSpy: jest.SpyInstance + let waitForPodPhasesSpy: jest.SpyInstance + let getPodLogsSpy: jest.SpyInstance + let waitForJobToCompleteSpy: jest.SpyInstance + let getPodStatusSpy: jest.SpyInstance + let getPodByNameSpy: jest.SpyInstance + let describePodFailureSpy: jest.SpyInstance + + const podName = 'test-pod-abc123' + const jobName = 'test-job-xyz789' + + const diagnosticOutput = [ + 'Phase: Failed', + '────────────────────────────────────────────────────────────', + ' ✗ Ready=False (ContainersNotReady): containers with unready status: [job]', + ' ✗ container "job": OOMKilled (exit code 137)', + ' Memory limit exceeded' + ].join('\n') + + function makeMinimalArgs(): RunContainerStepArgs { + return { + image: 'test-image:latest', + workingDirectory: '/__w/repo/repo', + entryPoint: 'bash', + entryPointArgs: ['-c', 'echo test'], + systemMountVolumes: [] + } as RunContainerStepArgs + } + + function podStatusWithTerminated( + reason: string, + exitCode: number, + message?: string + ): k8s.V1PodStatus { + return { + phase: 'Failed', + containerStatuses: [ + { + name: 'job', + image: 'test-image:latest', + imageID: '', + ready: false, + restartCount: 0, + state: { + terminated: { exitCode, reason, message } + } + } as k8s.V1ContainerStatus + ] + } + } + + beforeEach(() => { + process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default' + delete process.env[ENV_HOOK_TEMPLATE_PATH] + + coreErrorSpy = jest.spyOn(coreModule, 'error').mockImplementation(() => {}) + + createJobSpy = jest.spyOn(k8sModule, 'createJob').mockResolvedValue({ + metadata: { name: jobName } + } as k8s.V1Job) + + getContainerJobPodNameSpy = jest + .spyOn(k8sModule, 'getContainerJobPodName') + .mockResolvedValue(podName) + + waitForPodPhasesSpy = jest + .spyOn(k8sModule, 'waitForPodPhases') + .mockResolvedValue(undefined) + + getPodLogsSpy = jest + .spyOn(k8sModule, 'getPodLogs') + .mockResolvedValue(undefined) + + waitForJobToCompleteSpy = jest + .spyOn(k8sModule, 'waitForJobToComplete') + .mockResolvedValue(undefined) + + describePodFailureSpy = jest + .spyOn(k8sModule, 'describePodFailure') + .mockResolvedValue(diagnosticOutput) + }) + + afterEach(() => { + jest.restoreAllMocks() + delete process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] + }) + + it('includes describePodFailure output in core.error for OOMKilled container', async () => { + const pod: k8s.V1Pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'OOMKilled', 137, 'Memory limit exceeded') + ] + }) + getPodStatusSpy = jest + .spyOn(k8sModule, 'getPodStatus') + .mockResolvedValue(podStatusWithTerminated('OOMKilled', 137, 'Memory limit exceeded')) + getPodByNameSpy = jest + .spyOn(k8sModule, 'getPodByName') + .mockResolvedValue(pod) + + await runContainerStep(makeMinimalArgs()) + + expect(describePodFailureSpy).toHaveBeenCalledWith(podName) + expect(coreErrorSpy).toHaveBeenCalledTimes(1) + const errorMessage = coreErrorSpy.mock.calls[0][0] + expect(errorMessage).toContain('OOMKilled') + expect(errorMessage).toContain(diagnosticOutput) + }) + + it('includes describePodFailure output in core.error for Error (exit non-zero) container', async () => { + const pod: k8s.V1Pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'Error', 1, 'container crashed') + ] + }) + getPodStatusSpy = jest + .spyOn(k8sModule, 'getPodStatus') + .mockResolvedValue(podStatusWithTerminated('Error', 1, 'container crashed')) + getPodByNameSpy = jest + .spyOn(k8sModule, 'getPodByName') + .mockResolvedValue(pod) + + await runContainerStep(makeMinimalArgs()) + + expect(describePodFailureSpy).toHaveBeenCalledWith(podName) + expect(coreErrorSpy).toHaveBeenCalledTimes(1) + const errorMessage = coreErrorSpy.mock.calls[0][0] + expect(errorMessage).toContain('Error') + expect(errorMessage).toContain(diagnosticOutput) + }) + + it('includes describePodFailure output in core.error for FailedPostStartHookError container', async () => { + const pod: k8s.V1Pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer( + 'job', + 'FailedPostStartHookError', + 137, + 'postStart hook failed' + ) + ] + }) + getPodStatusSpy = jest + .spyOn(k8sModule, 'getPodStatus') + .mockResolvedValue( + podStatusWithTerminated('FailedPostStartHookError', 137, 'postStart hook failed') + ) + getPodByNameSpy = jest + .spyOn(k8sModule, 'getPodByName') + .mockResolvedValue(pod) + + await runContainerStep(makeMinimalArgs()) + + expect(describePodFailureSpy).toHaveBeenCalledWith(podName) + expect(coreErrorSpy).toHaveBeenCalledTimes(1) + const errorMessage = coreErrorSpy.mock.calls[0][0] + expect(errorMessage).toContain('FailedPostStartHookError') + expect(errorMessage).toContain(diagnosticOutput) + }) + + it('returns 1 when terminatedErrors are detected regardless of exitCode', async () => { + const pod: k8s.V1Pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'OOMKilled', 137, 'Memory limit exceeded') + ] + }) + getPodStatusSpy = jest + .spyOn(k8sModule, 'getPodStatus') + .mockResolvedValue(podStatusWithTerminated('OOMKilled', 137, 'Memory limit exceeded')) + getPodByNameSpy = jest + .spyOn(k8sModule, 'getPodByName') + .mockResolvedValue(pod) + + const exitCode = await runContainerStep(makeMinimalArgs()) + expect(exitCode).toBe(1) + }) + + it('returns 1 when init container has terminated error and main container exitCode is undefined', async () => { + const pod: k8s.V1Pod = { + status: { + phase: 'Failed', + initContainerStatuses: [ + terminatedContainer('init', 'OOMKilled', 137) + ], + containerStatuses: [ + { name: 'job', state: { running: {} } } as k8s.V1ContainerStatus + ] + } + } as k8s.V1Pod + const podStatus: k8s.V1PodStatus = { + phase: 'Failed', + containerStatuses: [ + { + name: 'job', + image: 'test-image:latest', + imageID: '', + ready: false, + restartCount: 0, + state: { running: {} } + } as k8s.V1ContainerStatus + ] + } + getPodStatusSpy = jest + .spyOn(k8sModule, 'getPodStatus') + .mockResolvedValue(podStatus) + getPodByNameSpy = jest + .spyOn(k8sModule, 'getPodByName') + .mockResolvedValue(pod) + + const exitCode = await runContainerStep(makeMinimalArgs()) + expect(exitCode).toBe(1) + }) +}) diff --git a/packages/k8s/tests/wait-for-pod-phases-test.ts b/packages/k8s/tests/wait-for-pod-phases-test.ts new file mode 100644 index 00000000..d2c0367f --- /dev/null +++ b/packages/k8s/tests/wait-for-pod-phases-test.ts @@ -0,0 +1,869 @@ +import * as k8s from '@kubernetes/client-node' +import { + describePodFailure, + getContainerErrors, + getContainerTerminatedErrors, + getPodConditionErrors, + getPodEventErrors, + getUnrecoverableEventReasons, + getUnrecoverableTerminatedReasons, + getUnrecoverableWaitingReasons, + parsePodPhase, + UNRECOVERABLE_EVENT_REASONS, + UNRECOVERABLE_TERMINATED_REASONS, + UNRECOVERABLE_WAITING_REASONS, + waitForPodPhases +} from '../src/k8s' +import { PodPhase } from '../src/k8s/utils' + +function buildPod( + phase?: string, + opts: { + containerStatuses?: k8s.V1ContainerStatus[] + initContainerStatuses?: k8s.V1ContainerStatus[] + conditions?: k8s.V1PodCondition[] + } = {} +): k8s.V1Pod { + return { + status: { + phase, + containerStatuses: opts.containerStatuses, + initContainerStatuses: opts.initContainerStatuses, + conditions: opts.conditions + } + } as k8s.V1Pod +} + +function waitingContainer( + name: string, + reason?: string, + message?: string +): k8s.V1ContainerStatus { + return { + name, + state: { waiting: { reason, message } } + } as k8s.V1ContainerStatus +} + +function terminatedContainer( + name: string, + reason?: string, + exitCode?: number, + message?: string +): k8s.V1ContainerStatus { + return { + name, + state: { terminated: { reason, exitCode, message } } + } as k8s.V1ContainerStatus +} + +describe('parsePodPhase', () => { + it('returns the phase when it is a known value', () => { + expect(parsePodPhase(buildPod(PodPhase.RUNNING))).toBe(PodPhase.RUNNING) + expect(parsePodPhase(buildPod(PodPhase.PENDING))).toBe(PodPhase.PENDING) + expect(parsePodPhase(buildPod(PodPhase.SUCCEEDED))).toBe(PodPhase.SUCCEEDED) + expect(parsePodPhase(buildPod(PodPhase.FAILED))).toBe(PodPhase.FAILED) + }) + + it('returns UNKNOWN when phase is missing', () => { + expect(parsePodPhase(buildPod(undefined))).toBe(PodPhase.UNKNOWN) + expect(parsePodPhase({} as k8s.V1Pod)).toBe(PodPhase.UNKNOWN) + }) + + it('returns UNKNOWN when phase is not a recognized value', () => { + expect(parsePodPhase(buildPod('SomethingElse'))).toBe(PodPhase.UNKNOWN) + }) +}) + +describe('getContainerErrors', () => { + it('returns no errors when there are no container statuses', () => { + expect(getContainerErrors(buildPod(PodPhase.PENDING))).toEqual([]) + expect(getContainerErrors({} as k8s.V1Pod)).toEqual([]) + }) + + it('returns no errors when containers are waiting for a recoverable reason', () => { + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [waitingContainer('job', 'ContainerCreating')] + }) + expect(getContainerErrors(pod)).toEqual([]) + }) + + it('does not detect FailedMount as a waiting reason', () => { + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [waitingContainer('job', 'FailedMount')] + }) + expect(getContainerErrors(pod)).toEqual([]) + }) + + it('detects every unrecoverable waiting reason', () => { + for (const reason of Array.from(UNRECOVERABLE_WAITING_REASONS)) { + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [waitingContainer('job', reason)] + }) + expect(getContainerErrors(pod)).toEqual([`container "job": ${reason}`]) + } + }) + + it('includes the waiting message when present', () => { + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [ + waitingContainer( + 'job', + 'ErrImagePull', + 'Back-off pulling image "does-not-exist:latest"' + ) + ] + }) + expect(getContainerErrors(pod)).toEqual([ + 'container "job": ErrImagePull - Back-off pulling image "does-not-exist:latest"' + ]) + }) + + it('inspects init containers as well as regular containers', () => { + const pod = buildPod(PodPhase.PENDING, { + initContainerStatuses: [waitingContainer('init', 'ImagePullBackOff')], + containerStatuses: [waitingContainer('job', 'CreateContainerError')] + }) + expect(getContainerErrors(pod)).toEqual([ + 'container "init": ImagePullBackOff', + 'container "job": CreateContainerError' + ]) + }) + + it('ignores running/terminated containers and only collects waiting errors', () => { + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [ + { name: 'running', state: { running: {} } } as k8s.V1ContainerStatus, + waitingContainer('bad', 'InvalidImageName') + ] + }) + expect(getContainerErrors(pod)).toEqual([ + 'container "bad": InvalidImageName' + ]) + }) +}) + +describe('getPodConditionErrors', () => { + it('returns empty array when no conditions', () => { + expect(getPodConditionErrors(buildPod(PodPhase.PENDING))).toEqual([]) + expect(getPodConditionErrors({} as k8s.V1Pod)).toEqual([]) + }) + + it('returns empty array when all conditions are True', () => { + const pod = buildPod(PodPhase.RUNNING, { + conditions: [ + { type: 'PodScheduled', status: 'True' } as k8s.V1PodCondition, + { type: 'Ready', status: 'True' } as k8s.V1PodCondition + ] + }) + expect(getPodConditionErrors(pod)).toEqual([]) + }) + + it('detects PodScheduled=False with Unschedulable reason only', () => { + const pod = buildPod(PodPhase.PENDING, { + conditions: [ + { + type: 'PodScheduled', + status: 'False', + reason: 'Unschedulable', + message: '0/1 nodes are available: 1 Insufficient memory.' + } as k8s.V1PodCondition + ] + }) + expect(getPodConditionErrors(pod)).toEqual([ + 'Condition PodScheduled=False (reason: Unschedulable): 0/1 nodes are available: 1 Insufficient memory.' + ]) + }) + + it('ignores Ready=False which is normal during Pending phase', () => { + const pod = buildPod(PodPhase.PENDING, { + conditions: [ + { + type: 'Ready', + status: 'False', + reason: 'ContainersNotReady', + message: 'containers with unready status: [job]' + } as k8s.V1PodCondition + ] + }) + expect(getPodConditionErrors(pod)).toEqual([]) + }) + + it('ignores PodScheduled=False with non-Unschedulable reason', () => { + const pod = buildPod(PodPhase.PENDING, { + conditions: [ + { + type: 'PodScheduled', + status: 'False', + reason: 'SomeOtherReason', + message: 'some message' + } as k8s.V1PodCondition + ] + }) + expect(getPodConditionErrors(pod)).toEqual([]) + }) + + it('detects PodScheduled=False/Unschedulable alongside other normal False conditions', () => { + const pod = buildPod(PodPhase.PENDING, { + conditions: [ + { + type: 'PodScheduled', + status: 'False', + reason: 'Unschedulable', + message: 'no nodes' + } as k8s.V1PodCondition, + { + type: 'Ready', + status: 'False', + reason: 'ContainersNotReady', + message: 'containers unready' + } as k8s.V1PodCondition + ] + }) + const errors = getPodConditionErrors(pod) + expect(errors.length).toBe(1) + expect(errors[0]).toContain('PodScheduled=False') + expect(errors[0]).toContain('Unschedulable') + }) + + it('handles PodScheduled=False/Unschedulable without message', () => { + const pod = buildPod(PodPhase.PENDING, { + conditions: [ + { type: 'PodScheduled', status: 'False', reason: 'Unschedulable' } as k8s.V1PodCondition + ] + }) + expect(getPodConditionErrors(pod)).toEqual([ + 'Condition PodScheduled=False (reason: Unschedulable): ' + ]) + }) +}) + +describe('getPodEventErrors', () => { + let eventSpy: jest.SpyInstance + + beforeEach(() => { + process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default' + eventSpy = jest.spyOn(k8s.CoreV1Api.prototype, 'listNamespacedEvent') + }) + + afterEach(() => { + jest.restoreAllMocks() + delete process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] + }) + + it('detects FailedScheduling event', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedScheduling', + message: '0/1 nodes are available' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([ + 'Event [Warning] FailedScheduling: 0/1 nodes are available' + ]) + }) + + it('detects FailedBinding event', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedBinding', + message: 'no persistent volumes available' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([ + 'Event [Warning] FailedBinding: no persistent volumes available' + ]) + }) + + it('detects FailedMount event', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedMount', + message: 'MountVolume.SetUp failed for volume' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([ + 'Event [Warning] FailedMount: MountVolume.SetUp failed for volume' + ]) + }) + + it('returns empty when events are Normal type', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Normal', + reason: 'Scheduled', + message: 'assigned' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([]) + }) + + it('returns empty when event reason is not in unrecoverable set', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'SomeOtherReason', + message: 'something happened' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([]) + }) + + it('returns empty array when event API is forbidden', async () => { + eventSpy.mockRejectedValue(new Error('events is forbidden') as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors).toEqual([]) + }) + + it('detects multiple unrecoverable events', async () => { + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedScheduling', + message: '0/1 nodes' + }, + { + type: 'Warning', + reason: 'FailedMount', + message: 'mount failed' + } + ] + } + } as never) + + const errors = await getPodEventErrors('my-pod') + expect(errors.length).toBe(2) + expect(errors[0]).toContain('FailedScheduling') + expect(errors[1]).toContain('FailedMount') + }) +}) + +describe('getContainerTerminatedErrors', () => { + it('returns empty when no container statuses', () => { + expect(getContainerTerminatedErrors(buildPod(PodPhase.FAILED))).toEqual([]) + expect(getContainerTerminatedErrors({} as k8s.V1Pod)).toEqual([]) + }) + + it('returns empty when containers are running or waiting', () => { + const pod = buildPod(PodPhase.RUNNING, { + containerStatuses: [ + { name: 'job', state: { running: {} } } as k8s.V1ContainerStatus, + waitingContainer('init', 'ContainerCreating') + ] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([]) + }) + + it('detects OOMKilled', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer('job', 'OOMKilled', 137, 'Memory limit exceeded') + ] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([ + 'container "job": OOMKilled (exit code 137) - Memory limit exceeded' + ]) + }) + + it('detects Error reason with non-zero exit code', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [terminatedContainer('job', 'Error', 1)] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([ + 'container "job": Error (exit code 1) - ' + ]) + }) + + it('detects FailedPostStartHookError', () => { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [ + terminatedContainer( + 'job', + 'FailedPostStartHookError', + 137, + 'postStart hook failed' + ) + ] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([ + 'container "job": FailedPostStartHookError (exit code 137) - postStart hook failed' + ]) + }) + + it('detects every unrecoverable terminated reason', () => { + for (const reason of Array.from(UNRECOVERABLE_TERMINATED_REASONS)) { + const pod = buildPod(PodPhase.FAILED, { + containerStatuses: [terminatedContainer('job', reason, 1)] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([ + `container "job": ${reason} (exit code 1) - ` + ]) + } + }) + + it('does not detect Completed reason (not in set)', () => { + const pod = buildPod(PodPhase.SUCCEEDED, { + containerStatuses: [ + terminatedContainer('job', 'Completed', 0) + ] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([]) + }) + + it('inspects init containers as well', () => { + const pod = buildPod(PodPhase.FAILED, { + initContainerStatuses: [ + terminatedContainer('init', 'OOMKilled', 137) + ], + containerStatuses: [terminatedContainer('job', 'Error', 1)] + }) + expect(getContainerTerminatedErrors(pod)).toEqual([ + 'container "init": OOMKilled (exit code 137) - ', + 'container "job": Error (exit code 1) - ' + ]) + }) +}) + +describe('waitForPodPhases', () => { + let readSpy: jest.SpyInstance + let eventSpy: jest.SpyInstance + + beforeEach(() => { + process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default' + readSpy = jest.spyOn(k8s.CoreV1Api.prototype, 'readNamespacedPod') + eventSpy = jest.spyOn(k8s.CoreV1Api.prototype, 'listNamespacedEvent') + eventSpy.mockResolvedValue({ body: { items: [] } } as never) + }) + + afterEach(() => { + jest.restoreAllMocks() + delete process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] + }) + + it('returns once the pod reaches an awaited phase', async () => { + readSpy.mockResolvedValue({ body: buildPod(PodPhase.RUNNING) } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).resolves.toBeUndefined() + }) + + it('surfaces unrecoverable container errors in the thrown message', async () => { + readSpy.mockResolvedValue({ + body: buildPod(PodPhase.PENDING, { + containerStatuses: [ + waitingContainer( + 'job', + 'ImagePullBackOff', + 'Back-off pulling image "nope:latest"' + ) + ] + }) + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).rejects.toThrow( + 'container "job": ImagePullBackOff - Back-off pulling image "nope:latest"' + ) + }) + + it('throws with the phase when the pod is in a non-backoff phase', async () => { + readSpy.mockResolvedValue({ + body: buildPod(PodPhase.FAILED) + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).rejects.toThrow('Pod my-pod is unhealthy with phase status Failed') + }) + + it('does NOT fail-fast on Ready=False condition (normal during Pending)', async () => { + readSpy + .mockResolvedValueOnce({ + body: buildPod(PodPhase.PENDING, { + conditions: [ + { type: 'Ready', status: 'False', reason: 'ContainersNotReady', message: 'containers unready' } as k8s.V1PodCondition, + { type: 'ContainersReady', status: 'False', reason: 'ContainersNotReady', message: 'containers unready' } as k8s.V1PodCondition + ] + }) + } as never) + .mockResolvedValueOnce({ body: buildPod(PodPhase.RUNNING) } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).resolves.toBeUndefined() + }) + + it('surfaces condition errors when PodScheduled=False with Unschedulable', async () => { + readSpy.mockResolvedValue({ + body: buildPod(PodPhase.PENDING, { + conditions: [ + { + type: 'PodScheduled', + status: 'False', + reason: 'Unschedulable', + message: '0/1 nodes are available' + } as k8s.V1PodCondition + ] + }) + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).rejects.toThrow('condition errors') + }) + + it('does NOT fail-fast on transient event errors like FailedScheduling', async () => { + readSpy + .mockResolvedValueOnce({ body: buildPod(PodPhase.PENDING) } as never) + .mockResolvedValueOnce({ body: buildPod(PodPhase.RUNNING) } as never) + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedScheduling', + message: '0/1 nodes are available' + } + ] + } + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).resolves.toBeUndefined() + }) + + it('does NOT fail-fast on FailedMount event errors', async () => { + readSpy + .mockResolvedValueOnce({ body: buildPod(PodPhase.PENDING) } as never) + .mockResolvedValueOnce({ body: buildPod(PodPhase.RUNNING) } as never) + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedMount', + message: 'MountVolume.SetUp failed for volume' + } + ] + } + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).resolves.toBeUndefined() + }) + + it('does NOT fail-fast on FailedBinding event errors', async () => { + readSpy + .mockResolvedValueOnce({ body: buildPod(PodPhase.PENDING) } as never) + .mockResolvedValueOnce({ body: buildPod(PodPhase.RUNNING) } as never) + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Warning', + reason: 'FailedBinding', + message: 'no persistent volumes available' + } + ] + } + } as never) + + await expect( + waitForPodPhases( + 'my-pod', + new Set([PodPhase.RUNNING]), + new Set([PodPhase.PENDING]) + ) + ).resolves.toBeUndefined() + }) +}) + +describe('getUnrecoverableWaitingReasons', () => { + afterEach(() => { + delete process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS'] + }) + + it('returns the built-in defaults when the env var is unset', () => { + expect(getUnrecoverableWaitingReasons()).toEqual( + UNRECOVERABLE_WAITING_REASONS + ) + }) + + it('adds extra reasons from the env var without dropping the defaults', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS'] = + 'CrashLoopBackOff, RunContainerError' + const reasons = getUnrecoverableWaitingReasons() + for (const builtin of Array.from(UNRECOVERABLE_WAITING_REASONS)) { + expect(reasons.has(builtin)).toBe(true) + } + expect(reasons.has('CrashLoopBackOff')).toBe(true) + expect(reasons.has('RunContainerError')).toBe(true) + }) + + it('makes getContainerErrors honor the extended whitelist', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS'] = + 'CrashLoopBackOff' + const pod = buildPod(PodPhase.PENDING, { + containerStatuses: [waitingContainer('job', 'CrashLoopBackOff')] + }) + expect(getContainerErrors(pod)).toEqual([ + 'container "job": CrashLoopBackOff' + ]) + }) + + it('filters empty strings from env var', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_WAITING_REASONS'] = ', , ' + const reasons = getUnrecoverableWaitingReasons() + expect(reasons).toEqual(UNRECOVERABLE_WAITING_REASONS) + }) +}) + +describe('getUnrecoverableEventReasons', () => { + afterEach(() => { + delete process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS'] + }) + + it('returns the built-in defaults when the env var is unset', () => { + expect(getUnrecoverableEventReasons()).toEqual(UNRECOVERABLE_EVENT_REASONS) + }) + + it('adds extra reasons from the env var without dropping the defaults', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS'] = + 'SomeOtherReason' + const reasons = getUnrecoverableEventReasons() + for (const builtin of Array.from(UNRECOVERABLE_EVENT_REASONS)) { + expect(reasons.has(builtin)).toBe(true) + } + expect(reasons.has('SomeOtherReason')).toBe(true) + }) + + it('filters empty strings from env var', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_EVENT_REASONS'] = ', , ' + const reasons = getUnrecoverableEventReasons() + expect(reasons).toEqual(UNRECOVERABLE_EVENT_REASONS) + }) +}) + +describe('getUnrecoverableTerminatedReasons', () => { + afterEach(() => { + delete process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] + }) + + it('returns the built-in defaults when the env var is unset', () => { + expect(getUnrecoverableTerminatedReasons()).toEqual( + UNRECOVERABLE_TERMINATED_REASONS + ) + }) + + it('adds extra reasons from the env var without dropping the defaults', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] = + 'DeadlineExceeded' + const reasons = getUnrecoverableTerminatedReasons() + for (const builtin of Array.from(UNRECOVERABLE_TERMINATED_REASONS)) { + expect(reasons.has(builtin)).toBe(true) + } + expect(reasons.has('DeadlineExceeded')).toBe(true) + }) + + it('filters empty strings from env var', () => { + process.env['ACTIONS_RUNNER_K8S_UNRECOVERABLE_TERMINATED_REASONS'] = ', , ' + const reasons = getUnrecoverableTerminatedReasons() + expect(reasons).toEqual(UNRECOVERABLE_TERMINATED_REASONS) + }) +}) + +describe('describePodFailure', () => { + let readSpy: jest.SpyInstance + let eventSpy: jest.SpyInstance + + beforeEach(() => { + process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] = 'default' + readSpy = jest.spyOn(k8s.CoreV1Api.prototype, 'readNamespacedPod') + eventSpy = jest.spyOn(k8s.CoreV1Api.prototype, 'listNamespacedEvent') + eventSpy.mockResolvedValue({ body: { items: [] } } as never) + }) + + afterEach(() => { + jest.restoreAllMocks() + delete process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] + }) + + it('reports phase, separator, ✗ conditions and ✗ terminated containers', async () => { + readSpy.mockResolvedValue({ + body: { + status: { + phase: PodPhase.FAILED, + reason: 'Evicted', + message: 'The node was low on resource: memory', + conditions: [ + { + type: 'PodScheduled', + status: 'False', + reason: 'Unschedulable', + message: 'no nodes available' + } + ], + containerStatuses: [ + { + name: 'job', + state: { + terminated: { exitCode: 137, reason: 'OOMKilled' } + } + } + ] + } + } + } as never) + + const description = await describePodFailure('my-pod') + expect(description).toContain('Phase: Failed (reason: Evicted)') + expect(description).toContain('Message: The node was low on resource: memory') + expect(description).toContain('────────────────────────────────────────────────────────────') + expect(description).toContain('✗ PodScheduled=False (Unschedulable): no nodes available') + expect(description).toContain( + '✗ container "job": OOMKilled (exit code 137)' + ) + }) + + it('includes recent Warning events and skips Normal ones', async () => { + readSpy.mockResolvedValue({ + body: { status: { phase: PodPhase.PENDING } } + } as never) + eventSpy.mockResolvedValue({ + body: { + items: [ + { + type: 'Normal', + reason: 'Scheduled', + message: 'assigned', + lastTimestamp: new Date('2026-01-01T00:00:00Z') + }, + { + type: 'Warning', + reason: 'FailedScheduling', + message: '0/1 nodes are available', + count: 3, + lastTimestamp: new Date('2026-01-01T00:01:00Z') + } + ] + } + } as never) + + const description = await describePodFailure('my-pod') + expect(description).toContain( + 'Event [Warning] FailedScheduling (x3): 0/1 nodes are available' + ) + expect(description).not.toContain('Scheduled') + }) + + it('degrades gracefully when listing events is forbidden', async () => { + readSpy.mockResolvedValue({ + body: { status: { phase: PodPhase.PENDING } } + } as never) + eventSpy.mockRejectedValue(new Error('events is forbidden') as never) + + const description = await describePodFailure('my-pod') + expect(description).toContain('Phase: Pending') + expect(description).not.toContain('Event [Warning]') + }) + + it('never throws when the pod cannot be read', async () => { + readSpy.mockRejectedValue(new Error('pod not found') as never) + + const description = await describePodFailure('my-pod') + expect(description).toContain('Could not read pod my-pod for diagnostics') + }) + + it('formats waiting container with ✗ marker', async () => { + readSpy.mockResolvedValue({ + body: { + status: { + phase: PodPhase.PENDING, + containerStatuses: [ + { + name: 'job', + state: { + waiting: { + reason: 'ErrImagePull', + message: 'image not found' + } + } + } + ] + } + } + } as never) + + const description = await describePodFailure('my-pod') + expect(description).toContain('✗ container "job": ErrImagePull') + expect(description).toContain(' image not found') + }) +})