Skip to content

Commit

Permalink
Parallelize preparation steps
Browse files Browse the repository at this point in the history
  • Loading branch information
usimd committed Nov 9, 2024
1 parent b771736 commit 1f1fdd2
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 167 deletions.
5 changes: 3 additions & 2 deletions __test__/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('Actions', () => {
})

it('should only increase disk space if requested', async () => {
jest.spyOn(core, 'getBooleanInput').mockReturnValueOnce(true)
jest.spyOn(core, 'getBooleanInput').mockReturnValue(true)

await actions.piGen()

Expand All @@ -40,7 +40,7 @@ describe('Actions', () => {
.mockReturnValueOnce('')
.mockReturnValueOnce('true')
.mockReturnValueOnce('true')
process.env['INPUT_INCREASE-RUNNER-DISK-SIZE'] = 'false'
jest.spyOn(core, 'getBooleanInput').mockReturnValue(false)

// expect build here
await actions.run()
Expand All @@ -56,6 +56,7 @@ describe('Actions', () => {
'should catch errors thrown during build and set build safely as failed',
async error => {
const errorMessage = 'any error'
jest.spyOn(core, 'getBooleanInput').mockReturnValueOnce(true)
jest.spyOn(core, 'getInput').mockImplementation((name, options) => {
throw error
})
Expand Down
48 changes: 35 additions & 13 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as core from '@actions/core'
import {configure} from './configure'
import {PiGenConfig} from './pi-gen-config'
import {installHostDependencies} from './install-dependencies'
import {build} from './build'
import {clonePigen} from './clone-pigen'
Expand All @@ -14,6 +15,8 @@ export async function piGen(): Promise<void> {
// See also https://github.com/chalk/supports-color/issues/106
process.env['FORCE_COLOR'] = '2'

const verbose = core.getBooleanInput('verbose-output')

const piGenDirectory = core.getInput('pi-gen-dir')
core.debug(`Using pi-gen directory: ${piGenDirectory}`)

Expand All @@ -25,22 +28,41 @@ export async function piGen(): Promise<void> {
)
core.debug(`Increase runner disk size: ${increaseRunnerDiskSize}`)

const userConfig = await configure()
const promisesToWait: Array<Promise<PiGenConfig | void>> = []

promisesToWait.push(configure())

if (increaseRunnerDiskSize) {
core.info('Removing unused runner components to increase disk space')
await removeRunnerComponents()
promisesToWait.push(
core.group(
'Removing runner components to increase disk build space',
() => removeRunnerComponents(verbose)
)
)
}

await clonePigen(piGenRepo, piGenDirectory, core.getInput('pi-gen-version'))
await installHostDependencies(
core.getInput('extra-host-dependencies'),
core.getInput('extra-host-modules'),
piGenDirectory
promisesToWait.push(
clonePigen(piGenRepo, piGenDirectory, core.getInput('pi-gen-version'))
)

promisesToWait.push(
core.group('Installing build dependencies on host', () =>
installHostDependencies(
core.getInput('extra-host-dependencies'),
core.getInput('extra-host-modules'),
piGenDirectory,
verbose
)
)
)

core.saveState(piGenBuildStartedState, true)
await build(piGenDirectory, userConfig)
Promise.all(promisesToWait).then(results => {
const filteredResults = results.filter(
result => typeof result !== 'undefined'
)
core.saveState(piGenBuildStartedState, true)
return build(piGenDirectory, filteredResults.at(0) as PiGenConfig)
})
} catch (error) {
core.setFailed((error as Error)?.message ?? error)
}
Expand All @@ -49,7 +71,7 @@ export async function piGen(): Promise<void> {
export async function cleanup(): Promise<void> {
try {
if (core.getState(piGenBuildStartedState)) {
await removeContainer('pigen_work')
return removeContainer('pigen_work')
} else {
core.info('No build started, nothing to clean')
}
Expand All @@ -60,9 +82,9 @@ export async function cleanup(): Promise<void> {

export async function run(): Promise<void> {
if (core.getState('main-executed')) {
await cleanup()
return cleanup()
} else {
core.saveState('main-executed', true)
await piGen()
return piGen()
}
}
175 changes: 86 additions & 89 deletions src/increase-runner-disk-size.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,105 @@
import * as exec from '@actions/exec'
import * as core from '@actions/core'

export async function removeRunnerComponents(): Promise<void> {
try {
core.startGroup('Removing runner components to increase disk build space')
export async function removeRunnerComponents(
verbose: boolean = false
): Promise<void> {
const availableDiskSizeBeforeCleanup = await getAvailableDiskSize()
core.debug(
`Available disk space before cleanup: ${availableDiskSizeBeforeCleanup / 1024 / 1024}G`
)

const availableDiskSizeBeforeCleanup = await getAvailableDiskSize()
core.debug(
`Available disk space before cleanup: ${availableDiskSizeBeforeCleanup / 1024 / 1024}G`
const actions = []
actions.push(
exec.getExecOutput(
'sudo',
['docker', 'system', 'prune', '--all', '--force'],
{
silent: !verbose,
failOnStdErr: false
}
)
)

await exec
.getExecOutput(
'sudo',
['docker', 'system', 'prune', '--all', '--force'],
{
silent: true,
failOnStdErr: false,
ignoreReturnCode: true
}
)
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))

await exec
.getExecOutput(
'sudo',
[
'sh',
'-c',
'snap list | sed 1d | cut -d" " -f1 | xargs -I{} snap remove {}'
],
{
silent: true,
failOnStdErr: false,
ignoreReturnCode: true
}
)
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
actions.push(
exec.getExecOutput(
'sudo',
[
'sh',
'-c',
'snap list | sed 1d | cut -d" " -f1 | xargs -I{} snap remove {}'
],
{
silent: !verbose,
failOnStdErr: false
}
)
)

await exec
.getExecOutput('sudo', ['swapoff', '-a'], {
silent: true,
failOnStdErr: false,
ignoreReturnCode: true
})
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
actions.push(
exec.getExecOutput('sudo', ['swapoff', '-a'], {
silent: !verbose,
failOnStdErr: false
})
)

// See https://github.com/actions/runner-images/issues/2840#issuecomment-2272410832
const hostPathsToRemove = [
'/opt/google/chrome',
'/opt/microsoft/msedge',
'/opt/microsoft/powershell',
'/opt/mssql-tools',
'/opt/hostedtoolcache',
'/opt/pipx',
'/usr/lib/mono',
'/usr/local/julia*',
'/usr/local/lib/android',
'/usr/local/lib/node_modules',
'/usr/local/share/chromium',
'/usr/local/share/powershell',
'/usr/share/dotnet',
'/usr/share/swift',
'/mnt/swapfile',
'/swapfile',
'/var/cache/snapd',
'/var/lib/snapd',
'/tmp/*',
'/usr/share/doc'
]
// See https://github.com/actions/runner-images/issues/2840#issuecomment-2272410832
const hostPathsToRemove = [
'/opt/google/chrome',
'/opt/microsoft/msedge',
'/opt/microsoft/powershell',
'/opt/mssql-tools',
'/opt/hostedtoolcache',
'/opt/pipx',
'/usr/lib/mono',
'/usr/local/julia*',
'/usr/local/lib/android',
'/usr/local/lib/node_modules',
'/usr/local/share/chromium',
'/usr/local/share/powershell',
'/usr/share/dotnet',
'/usr/share/swift',
'/mnt/swapfile',
'/swapfile',
'/var/cache/snapd',
'/var/lib/snapd',
'/tmp/*',
'/usr/share/doc'
]

await exec
.getExecOutput('sudo', ['rm', '-rf', ...hostPathsToRemove], {
silent: true,
ignoreReturnCode: true,
failOnStdErr: false
})
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
actions.push(
exec.getExecOutput('sudo', ['rm', '-rf', ...hostPathsToRemove], {
silent: !verbose,
failOnStdErr: false
})
)

await exec
actions.push(
exec
.getExecOutput(
'sudo',
['apt', 'purge', 'snapd', 'php8*', 'r-base', 'imagemagick'],
{
silent: true,
ignoreReturnCode: true
silent: !verbose,
failOnStdErr: false
}
)
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
await exec
.getExecOutput('sudo', ['apt-get', 'autoremove'], {
silent: true,
ignoreReturnCode: true
})
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
await exec
.getExecOutput('sudo', ['apt-get', 'autoclean'], {
silent: true,
ignoreReturnCode: true
})
.then((returnValue: exec.ExecOutput) => core.debug(returnValue.stdout))
.then(res =>
exec
.getExecOutput('sudo', ['apt-get', 'autoremove'], {
silent: !verbose,
failOnStdErr: false
})
.then(ret =>
exec.getExecOutput('sudo', ['apt-get', 'autoclean'], {
silent: !verbose,
failOnStdErr: false
})
)
)
)

return Promise.all(actions).then(async res => {
const availableDiskSizeAfterCleanup = await getAvailableDiskSize()
core.debug(
`Available disk space after cleanup: ${availableDiskSizeAfterCleanup / 1024 / 1024}G`
Expand All @@ -109,9 +108,7 @@ export async function removeRunnerComponents(): Promise<void> {
core.info(
`Reclaimed runner disk space: ${((availableDiskSizeAfterCleanup - availableDiskSizeBeforeCleanup) / 1024 / 1024).toFixed(2)}G`
)
} finally {
core.endGroup()
}
})
}

async function getAvailableDiskSize(): Promise<number> {
Expand Down
Loading

0 comments on commit 1f1fdd2

Please sign in to comment.