Skip to content

Commit

Permalink
Relaxe required stage directory check for Buster
Browse files Browse the repository at this point in the history
  • Loading branch information
usimd committed Oct 15, 2024
1 parent d8f5ba5 commit da3805b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 38 deletions.
78 changes: 49 additions & 29 deletions __test__/pi-gen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,22 @@ jest.mock('../src/pi-gen-config', () => ({
}))

const mockPiGenDependencies = (
stageDirectories = Object.values(PiGenStages)
stageDirectories = Object.values(PiGenStages),
buildFiles = ['build-docker.sh', 'Dockerfile']
) => {
jest
.spyOn(fs.promises, 'stat')
.mockResolvedValueOnce({isDirectory: () => true} as fs.Stats)

jest.spyOn(fs.promises, 'readdir').mockResolvedValueOnce([
{
name: 'Dockerfile',
isFile: () => true,
isDirectory: () => false
} as Dirent,
{
name: 'build-docker.sh',
isFile: () => true,
isDirectory: () => false
} as Dirent,
...buildFiles.map(
fileName =>
({
name: fileName,
isFile: () => true,
isDirectory: () => false
}) as Dirent
),
...(stageDirectories.map(stage => ({
name: stage,
isDirectory: () => true,
Expand All @@ -53,23 +52,20 @@ describe('PiGen', () => {
}
)

it('should fail on missing entries at pi-gen path', async () => {
jest
.spyOn(fs.promises, 'stat')
.mockResolvedValue({isDirectory: () => true} as fs.Stats)
jest.spyOn(fs.promises, 'readdir').mockResolvedValue([
{
name: 'Dockerfile',
isFile: () => true,
isDirectory: () => false
} as Dirent,
{name: 'stage0', isDirectory: () => true, isFile: () => false} as Dirent
])
it.each(['build-docker.sh', 'Dockerfile'])(
'should fail if only pi-gen core build file %s is present and others missing',
async buildFile => {
mockPiGenDependencies(Object.values(PiGenStages), [buildFile])

await expect(
async () => await PiGen.getInstance('pi-gen-dir', DEFAULT_CONFIG)
).rejects.toThrow()
})
await expect(
async () =>
await PiGen.getInstance('pi-gen-dir', {
...DEFAULT_CONFIG,
stageList: ['stage0']
})
).rejects.toThrow()
}
)

it('should fail on missing required stage entries at pi-gen path', async () => {
mockPiGenDependencies(['stage0', 'stage1'])
Expand All @@ -78,7 +74,11 @@ describe('PiGen', () => {
.mockResolvedValue({isDirectory: () => true} as fs.Stats)

await expect(
async () => await PiGen.getInstance('pi-gen-dir', DEFAULT_CONFIG)
async () =>
await PiGen.getInstance('pi-gen-dir', {
...DEFAULT_CONFIG,
stageList: ['stage0', 'stage1', 'stage2']
})
).rejects.toThrow()
})

Expand Down Expand Up @@ -172,6 +172,23 @@ describe('PiGen', () => {
expect(fs.existsSync(`${stageList[1]}/EXPORT_NOOBS`)).toBeFalsy()
})

it('does not require a stage5 directory for Buster', async () => {
const piGenDir = 'pi-gen'
const busterStages = ['stage0', 'stage1', 'stage2', 'stage3', 'stage4']
mockPiGenDependencies(busterStages)
jest.spyOn(fs, 'realpathSync').mockReturnValueOnce('/pi-gen/stage0')
// If user added a 'stage5', don't fail
let config = {
...DEFAULT_CONFIG,
release: 'buster',
stageList: [...busterStages, 'stage5']
} as PiGenConfig

const pigen = PiGen.getInstance(piGenDir, config)

await expect(pigen).resolves.not.toThrow()
})

it.each([
[
false,
Expand Down Expand Up @@ -219,7 +236,10 @@ describe('PiGen', () => {
jest.spyOn(core, 'warning').mockImplementation(s => {})
mockPiGenDependencies()

const piGenSut = new PiGen('pi-gen', DEFAULT_CONFIG)
const piGenSut = new PiGen('pi-gen', {
...DEFAULT_CONFIG,
stageList: ['stage0']
})
piGenSut.logOutput(line, verbose, stream as 'info' | 'warning')

expect(
Expand Down
25 changes: 16 additions & 9 deletions src/pi-gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ export class PiGen {
piGenDirectory: string,
config: PiGenConfig
): Promise<PiGen> {
if (!(await PiGen.validatePigenDirectory(piGenDirectory))) {
const instance = new PiGen(piGenDirectory, config)

if (!(await instance.validatePigenDirectory())) {
throw new Error(`pi-gen directory at ${piGenDirectory} is invalid`)
}

const instance = new PiGen(piGenDirectory, config)
core.debug(`Writing user config to ${instance.configFilePath}`)
await writeToFile(
instance.config,
Expand Down Expand Up @@ -105,27 +106,33 @@ export class PiGen {
return foundImages.length > 0 ? path.dirname(foundImages[0]) : undefined
}

private static async validatePigenDirectory(
piGenDirectory: string
): Promise<boolean> {
private async validatePigenDirectory(): Promise<boolean> {
try {
const dirStat = await fs.promises.stat(piGenDirectory)
const dirStat = await fs.promises.stat(this.piGenDirectory)

if (!dirStat.isDirectory()) {
core.debug(`Not a directory: ${piGenDirectory}`)
core.debug(`Not a directory: ${this.piGenDirectory}`)
return false
}
} catch (error) {
return false
}

const piGenDirContent = await fs.promises.readdir(piGenDirectory, {
const piGenDirContent = await fs.promises.readdir(this.piGenDirectory, {
withFileTypes: true
})
const requiredFiles = ['build-docker.sh', 'Dockerfile']
const requiredDirectories = Object.values(PiGenStages).filter(
let requiredDirectories = Object.values(PiGenStages).filter(
value => typeof value === 'string'
) as string[]

// https://github.com/usimd/pi-gen-action/issues/125
// It seems like RaspiOS based on Buster is lacking a `stage5` while all
// other versions include one.
if (this.config.release?.toLowerCase().trim() == 'buster') {
requiredDirectories = requiredDirectories.filter(dir => dir !== 'stage5')
}

const existingFiles = piGenDirContent
.filter(entry => entry.isFile())
.map(entry => entry.name)
Expand Down

0 comments on commit da3805b

Please sign in to comment.