mirror of
https://github.com/actions/runner-container-hooks.git
synced 2025-12-18 10:46:43 +00:00
Compare commits
3 Commits
nikola-jok
...
v0.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7da5474a5d | ||
|
|
375992cd31 | ||
|
|
aae800a69b |
@@ -4,7 +4,7 @@
|
|||||||
"state": {},
|
"state": {},
|
||||||
"args": {
|
"args": {
|
||||||
"container": {
|
"container": {
|
||||||
"image": "node:14.16",
|
"image": "node:22",
|
||||||
"workingDirectory": "/__w/repo/repo",
|
"workingDirectory": "/__w/repo/repo",
|
||||||
"createOptions": "--cpus 1",
|
"createOptions": "--cpus 1",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"args": {
|
"args": {
|
||||||
"image": "node:14.16",
|
"image": "node:22",
|
||||||
"dockerfile": null,
|
"dockerfile": null,
|
||||||
"entryPointArgs": [
|
"entryPointArgs": [
|
||||||
"-e",
|
"-e",
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "hooks",
|
"name": "hooks",
|
||||||
"version": "0.6.2",
|
"version": "0.7.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hooks",
|
"name": "hooks",
|
||||||
"version": "0.6.2",
|
"version": "0.7.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^27.5.1",
|
"@types/jest": "^27.5.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hooks",
|
"name": "hooks",
|
||||||
"version": "0.6.2",
|
"version": "0.7.0",
|
||||||
"description": "Three projects are included - k8s: a kubernetes hook implementation that spins up pods dynamically to run a job - docker: A hook implementation of the runner's docker implementation - A hook lib, which contains shared typescript definitions and utilities that the other packages consume",
|
"description": "Three projects are included - k8s: a kubernetes hook implementation that spins up pods dynamically to run a job - docker: A hook implementation of the runner's docker implementation - A hook lib, which contains shared typescript definitions and utilities that the other packages consume",
|
||||||
"main": "",
|
"main": "",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest --runInBand",
|
"test": "jest --runInBand",
|
||||||
"build": "npx tsc && npx ncc build"
|
"build": "npx tsc && npx ncc build",
|
||||||
|
"format": "prettier --write '**/*.ts'",
|
||||||
|
"format-check": "prettier --check '**/*.ts'",
|
||||||
|
"lint": "eslint src/**/*.ts"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -43,11 +43,16 @@ export async function createContainer(
|
|||||||
|
|
||||||
if (args.environmentVariables) {
|
if (args.environmentVariables) {
|
||||||
for (const [key] of Object.entries(args.environmentVariables)) {
|
for (const [key] of Object.entries(args.environmentVariables)) {
|
||||||
dockerArgs.push('-e')
|
dockerArgs.push('-e', key)
|
||||||
dockerArgs.push(key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dockerArgs.push('-e', 'GITHUB_ACTIONS=true')
|
||||||
|
// Use same behavior as the runner https://github.com/actions/runner/blob/27d9c886ab9a45e0013cb462529ac85d581f8c41/src/Runner.Worker/Container/DockerCommandManager.cs#L150
|
||||||
|
if (!('CI' in (args.environmentVariables ?? {}))) {
|
||||||
|
dockerArgs.push('-e', 'CI=true')
|
||||||
|
}
|
||||||
|
|
||||||
const mountVolumes = [
|
const mountVolumes = [
|
||||||
...(args.userMountVolumes || []),
|
...(args.userMountVolumes || []),
|
||||||
...(args.systemMountVolumes || [])
|
...(args.systemMountVolumes || [])
|
||||||
@@ -403,11 +408,16 @@ export async function containerRun(
|
|||||||
}
|
}
|
||||||
if (args.environmentVariables) {
|
if (args.environmentVariables) {
|
||||||
for (const [key] of Object.entries(args.environmentVariables)) {
|
for (const [key] of Object.entries(args.environmentVariables)) {
|
||||||
dockerArgs.push('-e')
|
dockerArgs.push('-e', key)
|
||||||
dockerArgs.push(key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dockerArgs.push('-e', 'GITHUB_ACTIONS=true')
|
||||||
|
// Use same behavior as the runner https://github.com/actions/runner/blob/27d9c886ab9a45e0013cb462529ac85d581f8c41/src/Runner.Worker/Container/DockerCommandManager.cs#L150
|
||||||
|
if (!('CI' in (args.environmentVariables ?? {}))) {
|
||||||
|
dockerArgs.push('-e', 'CI=true')
|
||||||
|
}
|
||||||
|
|
||||||
const mountVolumes = [
|
const mountVolumes = [
|
||||||
...(args.userMountVolumes || []),
|
...(args.userMountVolumes || []),
|
||||||
...(args.systemMountVolumes || [])
|
...(args.systemMountVolumes || [])
|
||||||
|
|||||||
@@ -75,4 +75,22 @@ describe('run script step', () => {
|
|||||||
runScriptStep(definitions.runScriptStep.args, prepareJobResponse.state)
|
runScriptStep(definitions.runScriptStep.args, prepareJobResponse.state)
|
||||||
).resolves.not.toThrow()
|
).resolves.not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should confirm that CI and GITHUB_ACTIONS are set', async () => {
|
||||||
|
definitions.runScriptStep.args.entryPoint = '/bin/bash'
|
||||||
|
definitions.runScriptStep.args.entryPointArgs = [
|
||||||
|
'-c',
|
||||||
|
`'if [[ ! $(env | grep "^CI=") = "CI=true" ]]; then exit 1; fi'`
|
||||||
|
]
|
||||||
|
await expect(
|
||||||
|
runScriptStep(definitions.runScriptStep.args, prepareJobResponse.state)
|
||||||
|
).resolves.not.toThrow()
|
||||||
|
definitions.runScriptStep.args.entryPointArgs = [
|
||||||
|
'-c',
|
||||||
|
`'if [[ ! $(env | grep "^GITHUB_ACTIONS=") = "GITHUB_ACTIONS=true" ]]; then exit 1; fi'`
|
||||||
|
]
|
||||||
|
await expect(
|
||||||
|
runScriptStep(definitions.runScriptStep.args, prepareJobResponse.state)
|
||||||
|
).resolves.not.toThrow()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -229,6 +229,18 @@ export function createContainerSpec(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
podContainer.env.push({
|
||||||
|
name: 'GITHUB_ACTIONS',
|
||||||
|
value: 'true'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!('CI' in container['environmentVariables'])) {
|
||||||
|
podContainer.env.push({
|
||||||
|
name: 'CI',
|
||||||
|
value: 'true'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
podContainer.volumeMounts = containerVolumes(
|
podContainer.volumeMounts = containerVolumes(
|
||||||
container.userMountVolumes,
|
container.userMountVolumes,
|
||||||
jobContainer
|
jobContainer
|
||||||
|
|||||||
@@ -29,7 +29,14 @@ export async function runContainerStep(
|
|||||||
let secretName: string | undefined = undefined
|
let secretName: string | undefined = undefined
|
||||||
if (stepContainer.environmentVariables) {
|
if (stepContainer.environmentVariables) {
|
||||||
try {
|
try {
|
||||||
secretName = await createSecretForEnvs(stepContainer.environmentVariables)
|
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) {
|
} catch (err) {
|
||||||
core.debug(`createSecretForEnvs failed: ${JSON.stringify(err)}`)
|
core.debug(`createSecretForEnvs failed: ${JSON.stringify(err)}`)
|
||||||
const message = (err as any)?.response?.body?.message || err
|
const message = (err as any)?.response?.body?.message || err
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: test
|
- name: test
|
||||||
image: node:14.16
|
image: node:22
|
||||||
- name: job
|
- name: job
|
||||||
image: ubuntu:latest`
|
image: ubuntu:latest`
|
||||||
)
|
)
|
||||||
@@ -407,7 +407,7 @@ spec:
|
|||||||
|
|
||||||
it('should merge container spec', () => {
|
it('should merge container spec', () => {
|
||||||
const base = {
|
const base = {
|
||||||
image: 'node:14.16',
|
image: 'node:22',
|
||||||
name: 'test',
|
name: 'test',
|
||||||
env: [
|
env: [
|
||||||
{
|
{
|
||||||
@@ -462,7 +462,7 @@ spec:
|
|||||||
const base = {
|
const base = {
|
||||||
containers: [
|
containers: [
|
||||||
{
|
{
|
||||||
image: 'node:14.16',
|
image: 'node:22',
|
||||||
name: 'test',
|
name: 'test',
|
||||||
env: [
|
env: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -62,6 +62,54 @@ describe('Prepare job', () => {
|
|||||||
).resolves.not.toThrow()
|
).resolves.not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should prepare job with envs CI and GITHUB_ACTIONS', async () => {
|
||||||
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
||||||
|
|
||||||
|
const content = JSON.parse(
|
||||||
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
const got = await getPodByName(content.state.jobPod)
|
||||||
|
expect(got.spec?.containers[0].env).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ name: 'CI', value: 'true' },
|
||||||
|
{ name: 'GITHUB_ACTIONS', value: 'true' }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
expect(got.spec?.containers[1].env).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ name: 'CI', value: 'true' },
|
||||||
|
{ name: 'GITHUB_ACTIONS', value: 'true' }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not override CI env var if already set', async () => {
|
||||||
|
prepareJobData.args.container.environmentVariables = {
|
||||||
|
CI: 'false'
|
||||||
|
}
|
||||||
|
|
||||||
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
||||||
|
|
||||||
|
const content = JSON.parse(
|
||||||
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
const got = await getPodByName(content.state.jobPod)
|
||||||
|
expect(got.spec?.containers[0].env).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ name: 'CI', value: 'false' },
|
||||||
|
{ name: 'GITHUB_ACTIONS', value: 'true' }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
expect(got.spec?.containers[1].env).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{ name: 'CI', value: 'true' },
|
||||||
|
{ name: 'GITHUB_ACTIONS', value: 'true' }
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('should throw an exception if the user volume mount is absolute path outside of GITHUB_WORKSPACE', async () => {
|
it('should throw an exception if the user volume mount is absolute path outside of GITHUB_WORKSPACE', async () => {
|
||||||
prepareJobData.args.container.userMountVolumes = [
|
prepareJobData.args.container.userMountVolumes = [
|
||||||
{
|
{
|
||||||
@@ -125,7 +173,7 @@ describe('Prepare job', () => {
|
|||||||
|
|
||||||
// job container
|
// job container
|
||||||
expect(got.spec?.containers[0].name).toBe(JOB_CONTAINER_NAME)
|
expect(got.spec?.containers[0].name).toBe(JOB_CONTAINER_NAME)
|
||||||
expect(got.spec?.containers[0].image).toBe('node:14.16')
|
expect(got.spec?.containers[0].image).toBe('node:22')
|
||||||
expect(got.spec?.containers[0].command).toEqual(['sh'])
|
expect(got.spec?.containers[0].command).toEqual(['sh'])
|
||||||
expect(got.spec?.containers[0].args).toEqual(['-c', 'sleep 50'])
|
expect(got.spec?.containers[0].args).toEqual(['-c', 'sleep 50'])
|
||||||
|
|
||||||
@@ -133,9 +181,13 @@ describe('Prepare job', () => {
|
|||||||
expect(got.spec?.containers[1].image).toBe('redis')
|
expect(got.spec?.containers[1].image).toBe('redis')
|
||||||
expect(got.spec?.containers[1].command).toBeFalsy()
|
expect(got.spec?.containers[1].command).toBeFalsy()
|
||||||
expect(got.spec?.containers[1].args).toBeFalsy()
|
expect(got.spec?.containers[1].args).toBeFalsy()
|
||||||
expect(got.spec?.containers[1].env).toEqual([
|
expect(got.spec?.containers[1].env).toEqual(
|
||||||
{ name: 'ENV2', value: 'value2' }
|
expect.arrayContaining([
|
||||||
])
|
{ name: 'CI', value: 'true' },
|
||||||
|
{ name: 'GITHUB_ACTIONS', value: 'true' },
|
||||||
|
{ name: 'ENV2', value: 'value2' }
|
||||||
|
])
|
||||||
|
)
|
||||||
expect(got.spec?.containers[1].resources).toEqual({
|
expect(got.spec?.containers[1].resources).toEqual({
|
||||||
requests: { memory: '1Mi', cpu: '1' },
|
requests: { memory: '1Mi', cpu: '1' },
|
||||||
limits: { memory: '1Gi', cpu: '2' }
|
limits: { memory: '1Gi', cpu: '2' }
|
||||||
|
|||||||
@@ -78,4 +78,15 @@ describe('Run container step', () => {
|
|||||||
runContainerStep(runContainerStepData.args)
|
runContainerStep(runContainerStepData.args)
|
||||||
).resolves.not.toThrow()
|
).resolves.not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should run container step with envs CI and GITHUB_ACTIONS', async () => {
|
||||||
|
runContainerStepData.args.entryPoint = 'bash'
|
||||||
|
runContainerStepData.args.entryPointArgs = [
|
||||||
|
'-c',
|
||||||
|
"'if [[ -z $GITHUB_ACTIONS ]] || [[ -z $CI ]]; then exit 1; fi'"
|
||||||
|
]
|
||||||
|
await expect(
|
||||||
|
runContainerStep(runContainerStepData.args)
|
||||||
|
).resolves.not.toThrow()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,10 +1,24 @@
|
|||||||
<!-- ## Features -->
|
## Features
|
||||||
|
|
||||||
<!-- ## Bugs -->
|
- k8s: Use pod affinity when KubeScheduler is enabled [#212]
|
||||||
|
- docker: support alternative network modes [#209]
|
||||||
|
|
||||||
|
## Bugs
|
||||||
|
|
||||||
|
- Expose CI=true and GITHUB_ACTIONS env variables [#215]
|
||||||
|
- k8s: add /github/home to containerAction mounts and surface createSecretForEnvs errors [#198]
|
||||||
|
- k8s: start logging from the beginning [#184]
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
- Bump `@kubernetes/client-node` from 0.18.1 to 0.22.0 in /packages/k8s [#182]
|
- Bump node in tests to node 22 since node14 is quite old [#216]
|
||||||
|
- Bump jsonpath-plus from 10.1.0 to 10.3.0 in /packages/k8s [#213]
|
||||||
|
- Bump braces from 3.0.2 to 3.0.3 in /packages/hooklib [#194]
|
||||||
|
- Bump cross-spawn from 7.0.3 to 7.0.6 in /packages/k8s [#196]
|
||||||
|
- Bump ws from 7.5.8 to 7.5.10 in /packages/k8s [#192]
|
||||||
|
- Remove dependency on deprecated release actions [#193]
|
||||||
|
- Update to the latest available actions [#191]
|
||||||
|
|
||||||
|
|
||||||
## SHA-256 Checksums
|
## SHA-256 Checksums
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user