Merge pull request #220 from crazy-max/lima-custom-images

docker(install): allow specifying custom lima images
This commit is contained in:
CrazyMax 2023-12-12 15:01:26 +01:00 committed by GitHub
commit 7929028d80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 9 deletions

View File

@ -29,7 +29,9 @@ describe('install', () => {
jest.resetModules(); jest.resetModules();
process.env = { process.env = {
...originalEnv, ...originalEnv,
LIMA_START_ARGS: '--cpus 4 --memory 8' LIMA_START_ARGS: '--cpus 4 --memory 8',
LIMA_IMAGES: `x86_64:https://cloud.debian.org/images/cloud/bookworm/20231013-1532/debian-12-genericcloud-amd64-20231013-1532.qcow2@sha512:6b55e88b027c14da1b55c85a25a9f7069d4560a8fdb2d948c986a585db469728a06d2c528303e34bb62d8b2984def38fd9ddfc00965846ff6e05b01d6e883bfe
aarch64:https://cloud.debian.org/images/cloud/bookworm/20231013-1532/debian-12-genericcloud-arm64-20231013-1532.qcow2`
}; };
}); });
afterEach(() => { afterEach(() => {

View File

@ -71,3 +71,32 @@ describe('getRelease', () => {
await expect(Install.getRelease('foo')).rejects.toThrow(new Error('Cannot find Docker release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/docker-releases.json')); await expect(Install.getRelease('foo')).rejects.toThrow(new Error('Cannot find Docker release foo in https://raw.githubusercontent.com/docker/actions-toolkit/main/.github/docker-releases.json'));
}); });
}); });
describe('limaImage', () => {
const originalEnv = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {
...originalEnv,
LIMA_IMAGES: `x86_64:https://cloud-images.ubuntu.com/releases/23.10/release-20231011/ubuntu-23.10-server-cloudimg-amd64.img@sha256:f6529be56da3429a56e4f5ef202bf4958201bc63f8541e478caa6e8eb712e635
aarch64:https://cloud-images.ubuntu.com/releases/23.10/release-20231011/ubuntu-23.10-server-cloudimg-arm64.img`
};
});
afterEach(() => {
process.env = originalEnv;
});
it('returns custom images', async () => {
expect(Install.limaCustomImages()).toEqual([
{
location: 'https://cloud-images.ubuntu.com/releases/23.10/release-20231011/ubuntu-23.10-server-cloudimg-amd64.img',
arch: 'x86_64',
digest: 'sha256:f6529be56da3429a56e4f5ef202bf4958201bc63f8541e478caa6e8eb712e635'
},
{
location: 'https://cloud-images.ubuntu.com/releases/23.10/release-20231011/ubuntu-23.10-server-cloudimg-arm64.img',
arch: 'aarch64',
digest: ''
}
]);
});
});

View File

@ -144,6 +144,11 @@ os: null
arch: null arch: null
images: images:
{{#each customImages}}
- location: "{{location}}"
arch: "{{arch}}"
digest: "{{digest}}"
{{/each}}
- location: "https://cloud-images.ubuntu.com/releases/22.04/release-20231026/ubuntu-22.04-server-cloudimg-amd64.img" - location: "https://cloud-images.ubuntu.com/releases/22.04/release-20231026/ubuntu-22.04-server-cloudimg-amd64.img"
arch: "x86_64" arch: "x86_64"
digest: "sha256:054db2d88c454bb0ad8dfd8883955e3946b57d2b0bf0d023f3ade3c93cdd14e5" digest: "sha256:054db2d88c454bb0ad8dfd8883955e3946b57d2b0bf0d023f3ade3c93cdd14e5"

View File

@ -41,6 +41,12 @@ export interface InstallOpts {
daemonConfig?: string; daemonConfig?: string;
} }
interface LimaImage {
location: string;
arch: string;
digest?: string;
}
export class Install { export class Install {
private readonly runDir: string; private readonly runDir: string;
private readonly version: string; private readonly version: string;
@ -136,8 +142,9 @@ export class Install {
await io.mkdirP(limaDir); await io.mkdirP(limaDir);
const dockerHost = `unix://${limaDir}/docker.sock`; const dockerHost = `unix://${limaDir}/docker.sock`;
// avoid brew to upgrade unrelated packages. // avoid brew to auto update and upgrade unrelated packages.
let envs = Object.assign({}, process.env, { let envs = Object.assign({}, process.env, {
HOMEBREW_NO_AUTO_UPDATE: '1',
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: '1' HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: '1'
}) as { }) as {
[key: string]: string; [key: string]: string;
@ -149,6 +156,10 @@ export class Install {
}); });
} }
await core.group('Lima version', async () => {
await Exec.exec('lima', ['--version'], {env: envs});
});
await core.group('Creating lima config', async () => { await core.group('Creating lima config', async () => {
let limaDaemonConfig = {}; let limaDaemonConfig = {};
if (this.daemonConfig) { if (this.daemonConfig) {
@ -158,6 +169,7 @@ export class Install {
return new handlebars.SafeString(JSON.stringify(obj)); return new handlebars.SafeString(JSON.stringify(obj));
}); });
const limaCfg = handlebars.compile(limaYamlData)({ const limaCfg = handlebars.compile(limaYamlData)({
customImages: Install.limaCustomImages(),
daemonConfig: limaDaemonConfig, daemonConfig: limaDaemonConfig,
dockerSock: `${limaDir}/docker.sock`, dockerSock: `${limaDir}/docker.sock`,
dockerBinVersion: this._version, dockerBinVersion: this._version,
@ -182,7 +194,7 @@ export class Install {
}; };
await core.group('Starting lima instance', async () => { await core.group('Starting lima instance', async () => {
const limaStartArgs = ['start', `--name=${this.limaInstanceName}`, '--tty=false']; const limaStartArgs = ['start', `--name=${this.limaInstanceName}`];
if (process.env.LIMA_START_ARGS) { if (process.env.LIMA_START_ARGS) {
limaStartArgs.push(process.env.LIMA_START_ARGS); limaStartArgs.push(process.env.LIMA_START_ARGS);
} }
@ -507,4 +519,25 @@ EOF`,
} }
return releases[version]; return releases[version];
} }
public static limaCustomImages(): LimaImage[] {
const res: LimaImage[] = [];
const env = process.env.LIMA_IMAGES;
if (!env) {
return res;
}
for (const input of Util.getList(env, {ignoreComma: true, comment: '#'})) {
const archIndex = input.indexOf(':');
const arch = input.substring(0, archIndex).trim();
const digestIndex = input.indexOf('@');
const location = input.substring(archIndex + 1, digestIndex !== -1 ? digestIndex : undefined).trim();
const digest = digestIndex !== -1 ? input.substring(digestIndex + 1).trim() : '';
res.push({
location: location,
arch: arch,
digest: digest
});
}
return res;
}
} }

View File

@ -19,22 +19,24 @@ import * as core from '@actions/core';
import * as io from '@actions/io'; import * as io from '@actions/io';
import {parse} from 'csv-parse/sync'; import {parse} from 'csv-parse/sync';
export interface InputListOpts { export interface ListOpts {
ignoreComma?: boolean; ignoreComma?: boolean;
comment?: string; comment?: string;
quote?: string | boolean | Buffer | null; quote?: string | boolean | Buffer | null;
} }
export class Util { export class Util {
public static getInputList(name: string, opts?: InputListOpts): string[] { public static getInputList(name: string, opts?: ListOpts): string[] {
const res: Array<string> = []; return this.getList(core.getInput(name), opts);
}
const items = core.getInput(name); public static getList(input: string, opts?: ListOpts): string[] {
if (items == '') { const res: Array<string> = [];
if (input == '') {
return res; return res;
} }
const records = parse(items, { const records = parse(input, {
columns: false, columns: false,
relaxQuotes: true, relaxQuotes: true,
comment: opts?.comment, comment: opts?.comment,