Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/sixty-cases-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'create-rock': patch
---

feat: add remote cache provider setup
7 changes: 7 additions & 0 deletions packages/config/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ export async function getConfig(
getRemoteCacheProvider: async () => {
// special case for github-actions
if (validatedConfig.remoteCacheProvider === 'github-actions') {
logger.warnOnce('github-actions')(
`Using shorthand "github-actions" as "remoteCacheProvider" value in ${colorLink(
'rock.config.mjs',
)} is deprecated. It will be removed in future releases.
Please use "@rock-js/provider-github" plugin explicitly instead.
Read more: ${colorLink('https://rockjs.dev/docs/configuration#github-actions-provider')}`,
);
const { providerGitHub } = await import('@rock-js/provider-github');
return providerGitHub();
}
Expand Down
84 changes: 81 additions & 3 deletions packages/create-app/src/lib/__tests__/bin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ test('should format config without plugins', () => {
ios: platformIOS(),
android: platformAndroid(),
},
remoteCacheProvider: null,
};
"
`);
Expand All @@ -33,7 +32,7 @@ test('should format config with plugins', () => {
},
];

expect(formatConfig([PLATFORMS[0]], plugins, BUNDLERS[1], 'github-actions'))
expect(formatConfig([PLATFORMS[0]], plugins, BUNDLERS[1], null))
.toMatchInlineSnapshot(`
"import { platformIOS } from '@rock-js/platform-ios';
import { pluginTest } from '@rock-js/plugin-test';
Expand All @@ -47,7 +46,86 @@ test('should format config with plugins', () => {
platforms: {
ios: platformIOS(),
},
remoteCacheProvider: 'github-actions',
};
"
`);
});

test(`should format config with the 'github-actions' provider`, () => {
expect(
formatConfig([PLATFORMS[0]], null, BUNDLERS[1], {
name: 'github-actions',
args: { owner: 'custom-owner', repository: 'repository-name' },
}),
).toMatchInlineSnapshot(`
"import { platformIOS } from '@rock-js/platform-ios';
import { pluginRepack } from '@rock-js/plugin-repack';
import { providerGitHub } from '@rock-js/provider-github';

export default {
bundler: pluginRepack(),
platforms: {
ios: platformIOS(),
},
remoteCacheProvider: providerGitHub({
owner: 'custom-owner',
repository: 'repository-name',
}),
};
"
`);
});

test(`should format config with the 's3' provider`, () => {
expect(
formatConfig([PLATFORMS[0]], null, BUNDLERS[1], {
name: 's3',
args: { bucket: 'custom-bucket', region: 'us-east-1' },
}),
).toMatchInlineSnapshot(`
"import { platformIOS } from '@rock-js/platform-ios';
import { pluginRepack } from '@rock-js/plugin-repack';
import { providerS3 } from '@rock-js/provider-s3';

export default {
bundler: pluginRepack(),
platforms: {
ios: platformIOS(),
},
remoteCacheProvider: providerS3({
bucket: 'custom-bucket',
region: 'us-east-1',
}),
};
"
`);
});

test(`should format config with the 's3' provider using a custom endpoint`, () => {
expect(
formatConfig([PLATFORMS[0]], null, BUNDLERS[1], {
name: 's3',
args: {
bucket: 'custom-bucket',
region: 'us-east-1',
endpoint: 'https://custom-endpoint.com',
},
}),
).toMatchInlineSnapshot(`
"import { platformIOS } from '@rock-js/platform-ios';
import { pluginRepack } from '@rock-js/plugin-repack';
import { providerS3 } from '@rock-js/provider-s3';

export default {
bundler: pluginRepack(),
platforms: {
ios: platformIOS(),
},
remoteCacheProvider: providerS3({
bucket: 'custom-bucket',
region: 'us-east-1',
endpoint: 'https://custom-endpoint.com',
}),
};
"
`);
Expand Down
63 changes: 46 additions & 17 deletions packages/create-app/src/lib/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
BUNDLERS,
PLATFORMS,
PLUGINS,
remoteCacheProviderToConfigTemplate,
remoteCacheProviderToImportTemplate,
resolveTemplate,
TEMPLATES,
} from './templates.js';
Expand Down Expand Up @@ -46,6 +48,7 @@ import {
promptPlugins,
promptProjectName,
promptRemoteCacheProvider,
promptRemoteCacheProviderArgs,
promptTemplate,
} from './utils/prompts.js';
import {
Expand Down Expand Up @@ -146,6 +149,10 @@ export async function run() {
? null
: await promptRemoteCacheProvider();

const remoteCacheProviderArgs = remoteCacheProvider
? await promptRemoteCacheProviderArgs(remoteCacheProvider)
: null;

const shouldInstallDependencies =
options.install || isInteractive()
? await promptInstallDependencies()
Expand All @@ -172,7 +179,12 @@ export async function run() {
platforms,
plugins,
bundler,
remoteCacheProvider,
remoteCacheProvider && remoteCacheProviderArgs
? {
name: remoteCacheProvider,
args: remoteCacheProviderArgs,
}
: null,
);
loader.stop('Applied template, platforms and plugins.');

Expand Down Expand Up @@ -296,7 +308,10 @@ function createConfig(
platforms: TemplateInfo[],
plugins: TemplateInfo[] | null,
bundler: TemplateInfo,
remoteCacheProvider: SupportedRemoteCacheProviders | null,
remoteCacheProvider: {
name: SupportedRemoteCacheProviders;
args: Record<string, string>;
} | null,
) {
const rockConfig = path.join(absoluteTargetDir, 'rock.config.mjs');
fs.writeFileSync(
Expand All @@ -309,40 +324,54 @@ export function formatConfig(
platforms: TemplateInfo[],
plugins: TemplateInfo[] | null,
bundler: TemplateInfo,
remoteCacheProvider: SupportedRemoteCacheProviders | null,
remoteCacheProvider: {
name: SupportedRemoteCacheProviders;
args: Record<string, string>;
} | null,
) {
const platformsWithImports = platforms.filter(
(template) => template.importName,
);
const pluginsWithImports = plugins
? plugins.filter((template) => template.importName)
: null;
return `${[...platformsWithImports, ...(pluginsWithImports ?? []), bundler]
.map(

return `${[
...[...platformsWithImports, ...(pluginsWithImports ?? []), bundler].map(
(template) =>
`import { ${template.importName} } from '${template.packageName}';`,
)
),
remoteCacheProvider?.name
? remoteCacheProviderToImportTemplate(remoteCacheProvider.name)
: '',
]
.filter(Boolean)
.join('\n')}

export default {${
export default {
${[
pluginsWithImports && pluginsWithImports.length > 0
? `
plugins: [
? `plugins: [
${pluginsWithImports
.map((template) => `${template.importName}(),`)
.join('\n ')}
],`
: ''
}
bundler: ${bundler.importName}(),
platforms: {
: '',
`bundler: ${bundler.importName}(),`,
`platforms: {
${platformsWithImports
.map((template) => `${template.name}: ${template.importName}(),`)
.join('\n ')}
},
remoteCacheProvider: ${
remoteCacheProvider === null ? null : `'${remoteCacheProvider}'`
},
},`,
remoteCacheProvider?.name
? remoteCacheProviderToConfigTemplate(
remoteCacheProvider.name,
remoteCacheProvider.args,
)
: '',
]
.filter(Boolean)
.join('\n ')}
};
`;
}
57 changes: 56 additions & 1 deletion packages/create-app/src/lib/templates.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as path from 'node:path';
import { resolveAbsolutePath } from '@rock-js/tools';
import {
resolveAbsolutePath,
type SupportedRemoteCacheProviders,
} from '@rock-js/tools';

export type TemplateInfo = NpmTemplateInfo | LocalTemplateInfo;

Expand Down Expand Up @@ -93,6 +96,58 @@ export const PLATFORMS: TemplateInfo[] = [
},
];

export function remoteCacheProviderToImportTemplate(
provider: SupportedRemoteCacheProviders,
) {
switch (provider) {
case 'github-actions':
return `import { providerGitHub } from '@rock-js/provider-github';`;
case 's3':
return `import { providerS3 } from '@rock-js/provider-s3';`;
}
}

export function remoteCacheProviderToConfigTemplate(
provider: SupportedRemoteCacheProviders,
args: Record<string, string>,
) {
switch (provider) {
case 'github-actions':
return template([
'remoteCacheProvider: providerGitHub({',
` owner: '${args['owner']}',`,
` repository: '${args['repository']}',`,
'}),',
]);
case 's3':
return template([
'remoteCacheProvider: providerS3({',
` bucket: '${args['bucket']}',`,
` region: '${args['region']}',`,
[` endpoint: '${args['endpoint']}',`, Boolean(args['endpoint'])],
'}),',
]);
}
}
Copy link

Choose a reason for hiding this comment

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

Bug: Cache Config Template Errors

The remoteCacheProviderToConfigTemplate function has two issues. It may return undefined for unhandled provider values. Additionally, user input for arguments like owner or bucket is directly interpolated into the generated config, which can lead to invalid JavaScript syntax if inputs contain single quotes.

Fix in Cursor Fix in Web


export function template(lines: Array<string | [string, boolean]>) {
return lines
.filter((line) => {
// If it's a [content, condition] pair, check the condition
if (Array.isArray(line)) {
return Boolean(line[1]);
}
// If it's just a string, always include it
return true;
})
.map((line) => {
// Extract content from [content, condition] pair or use string directly
const content = Array.isArray(line) ? line[0] : line;
return content;
})
.join('\n ');
}

export function resolveTemplate(
templates: TemplateInfo[],
name: string,
Expand Down
Loading
Loading