Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/busy-sides-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'skuba': minor
---

init: Add support for private SEEK templates

Adds support for downloading templates from the private SEEK-Jobs/skuba-templates repository. Users can now select "seek →" from the template list and specify a private template name, which will be downloaded using sparse checkout via SSH.
18 changes: 15 additions & 3 deletions src/cli/init/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import {
templateConfigSchema,
} from '../../utils/template.js';

import { downloadGitHubTemplate } from './git.js';
import { downloadGitHubTemplate, downloadPrivateTemplate } from './git.js';
import {
BASE_PROMPT_PROPS,
type BaseFields,
type Choice,
getGitPath,
getPrivateTemplateName,
getTemplateName,
shouldContinue,
} from './prompts.js';
Expand Down Expand Up @@ -94,12 +95,18 @@ const cloneTemplate = async (
templateName: string,
destinationDir: string,
): Promise<TemplateConfig> => {
const isCustomTemplate = templateName.startsWith('github:');
const isGitHubTemplate = templateName.startsWith('github:');
const isPrivateSeekTemplate = templateName.startsWith('seek:');
const isCustomTemplate = isGitHubTemplate || isPrivateSeekTemplate;

if (isCustomTemplate) {
if (isGitHubTemplate) {
const gitHubPath = templateName.slice('github:'.length);

await downloadGitHubTemplate(gitHubPath, destinationDir);
} else if (isPrivateSeekTemplate) {
const privateName = templateName.slice('seek:'.length);

await downloadPrivateTemplate(privateName, destinationDir);
} else {
const templateDir = path.join(TEMPLATE_DIR, templateName);

Expand Down Expand Up @@ -140,6 +147,11 @@ const selectTemplateName = async () => {
return `github:${gitHubPath}`;
}

if (templateSelection === 'seek →') {
const privateName = await getPrivateTemplateName();
return `seek:${privateName}`;
}

return templateSelection;
};

Expand Down
46 changes: 46 additions & 0 deletions src/cli/init/git.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { exec } from 'child_process';
import path from 'path';
import { promisify } from 'util';

import fs from 'fs-extra';
import git from 'isomorphic-git';
Expand Down Expand Up @@ -54,3 +56,47 @@ export const downloadGitHubTemplate = async (
recursive: true,
});
};

const execAsync = promisify(exec);

export const downloadPrivateTemplate = async (
templateName: string,
destinationDir: string,
) => {
log.newline();
log.plain(
'Downloading',
log.bold(templateName),
'from SEEK-Jobs/skuba-templates',
);

const repoUrl = 'git@github.com:SEEK-Jobs/skuba-templates.git';
const folderPath = `templates/${templateName}`;
const tempDir = `${destinationDir}_temp`;

try {
await execAsync(`
git init ${tempDir} &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this with isomorphic-git?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isomorphic-git doesn't support ssh 😢 so swapped out the gross hand rolled commands in favour of simple-git.

git -C ${tempDir} config core.sparseCheckout true &&
echo "${folderPath}/*" >> ${tempDir}/.git/info/sparse-checkout &&
git -C ${tempDir} remote add origin ${repoUrl} &&
git -C ${tempDir} pull origin main --depth 1 --quiet
`);

const templatePath = path.join(tempDir, folderPath);

try {
await fs.promises.access(templatePath);
} catch {
throw new Error(`Template "${templateName}" not found in repository`);
}

await fs.ensureDir(destinationDir);
await fs.copy(templatePath, destinationDir);

await fs.promises.rm(tempDir, { force: true, recursive: true });
} catch (error) {
await fs.promises.rm(tempDir, { force: true, recursive: true });
throw error;
}
};
7 changes: 7 additions & 0 deletions src/cli/init/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,10 @@ export const getTemplateName = async () =>
message: 'Select a template:',
choices: TEMPLATE_NAMES_WITH_BYO.map((name) => ({ name, value: name })),
});

export const getPrivateTemplateName = async () =>
input({
message: 'Private SEEK template name',
validate: (value: string) =>
value.length > 0 || 'Must be a valid template name',
});
6 changes: 5 additions & 1 deletion src/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export const TEMPLATE_NAMES = [

export type TemplateName = (typeof TEMPLATE_NAMES)[number];

export const TEMPLATE_NAMES_WITH_BYO = [...TEMPLATE_NAMES, 'github →'] as const;
export const TEMPLATE_NAMES_WITH_BYO = [
...TEMPLATE_NAMES,
'github →',
'seek →',
] as const;

interface TemplateDocumentationConfig {
/**
Expand Down