-
Notifications
You must be signed in to change notification settings - Fork 3
Add --remote-source flag to create command #182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
794ab3f
a0d4c27
d122947
a05cdfe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,12 +20,14 @@ import type { | |
| } from '@rushstack/ts-command-line'; | ||
| import { | ||
| LocalFileSystemRepositorySource, | ||
| PublicGitHubRepositorySource, | ||
| type SPFxTemplateCollection, | ||
| SPFxTemplateRepositoryManager, | ||
| type SPFxTemplate, | ||
| SPFxTemplateWriter | ||
| } from '@microsoft/spfx-template-api'; | ||
|
|
||
| import { parseGitHubUrlAndRef } from '../../utilities/github'; | ||
| import { SOLUTION_NAME_PATTERN } from '../../utilities/validation'; | ||
| import { SPFxActionBase } from './SPFxActionBase'; | ||
|
|
||
|
|
@@ -50,6 +52,7 @@ export class CreateAction extends SPFxActionBase { | |
| private readonly _targetDirParameter: IRequiredCommandLineStringParameter; | ||
| private readonly _templateParameter: IRequiredCommandLineStringParameter; | ||
| private readonly _localTemplateSourcesParameter: CommandLineStringListParameter; | ||
| private readonly _remoteSourcesParameter: CommandLineStringListParameter; | ||
| private readonly _libraryNameParameter: IRequiredCommandLineStringParameter; | ||
| private readonly _componentNameParameter: IRequiredCommandLineStringParameter; | ||
| private readonly _componentAliasParameter: CommandLineStringParameter; | ||
|
|
@@ -80,6 +83,12 @@ export class CreateAction extends SPFxActionBase { | |
| description: 'Path to a local template folder' | ||
| }); | ||
|
|
||
| this._remoteSourcesParameter = this.defineStringListParameter({ | ||
| parameterLongName: '--remote-source', | ||
| argumentName: 'URL', | ||
| description: 'Public GitHub repository URL to use as an additional template source (repeatable)' | ||
| }); | ||
|
|
||
| this._templateParameter = this.defineStringParameter({ | ||
| parameterLongName: '--template', | ||
| argumentName: 'TEMPLATE_NAME', | ||
|
|
@@ -162,6 +171,23 @@ export class CreateAction extends SPFxActionBase { | |
| this._addGitHubTemplateSource(manager); | ||
| } | ||
|
|
||
| // Always process --remote-source URLs (additive with either local or default sources) | ||
| for (const remoteUrl of this._remoteSourcesParameter.values) { | ||
| const { repoUrl: additionalRepoUrl, urlBranch: additionalUrlBranch } = | ||
| parseGitHubUrlAndRef(remoteUrl); | ||
| terminal.writeLine( | ||
| `Adding remote template source: ${additionalRepoUrl}` + | ||
|
Comment on lines
+175
to
+179
|
||
| `${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}` | ||
| ); | ||
| manager.addSource( | ||
| new PublicGitHubRepositorySource({ | ||
| repoUrl: additionalRepoUrl, | ||
| branch: additionalUrlBranch, | ||
| terminal | ||
| }) | ||
| ); | ||
| } | ||
|
Comment on lines
+174
to
+189
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this into the base? |
||
|
|
||
| let templates: SPFxTemplateCollection; | ||
| try { | ||
| templates = await manager.getTemplatesAsync(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -171,6 +171,65 @@ describe('CreateAction', () => { | |||||||||||||||||||||||
| expect(MockedLocal).toHaveBeenNthCalledWith(2, '/b'); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| describe('with --remote-source', () => { | ||||||||||||||||||||||||
| it('adds an extra PublicGitHubRepositorySource alongside the default', async () => { | ||||||||||||||||||||||||
| await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates']); | ||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenCalledTimes(2); | ||||||||||||||||||||||||
| // First call: default source | ||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenNthCalledWith( | ||||||||||||||||||||||||
| 1, | ||||||||||||||||||||||||
| 'https://github.com/SharePoint/spfx', | ||||||||||||||||||||||||
| undefined, | ||||||||||||||||||||||||
| expect.anything() | ||||||||||||||||||||||||
|
Comment on lines
+180
to
+184
|
||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||
| // Second call: remote source | ||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenNthCalledWith( | ||||||||||||||||||||||||
| 2, | ||||||||||||||||||||||||
| 'https://github.com/my-org/my-templates', | ||||||||||||||||||||||||
| undefined, | ||||||||||||||||||||||||
| expect.anything() | ||||||||||||||||||||||||
|
Comment on lines
+187
to
+191
|
||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| it('adds multiple remote sources for multiple --remote-source flags', async () => { | ||||||||||||||||||||||||
| await runCreateAsync([ | ||||||||||||||||||||||||
| '--remote-source', | ||||||||||||||||||||||||
| 'https://github.com/org1/repo1', | ||||||||||||||||||||||||
| '--remote-source', | ||||||||||||||||||||||||
| 'https://github.com/org2/repo2' | ||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||
| // default + 2 remote = 3 total | ||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenCalledTimes(3); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| it('extracts branch from /tree/ in --remote-source URL', async () => { | ||||||||||||||||||||||||
| await runCreateAsync(['--remote-source', 'https://github.com/my-org/my-templates/tree/my-branch']); | ||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenNthCalledWith( | ||||||||||||||||||||||||
| 2, | ||||||||||||||||||||||||
| 'https://github.com/my-org/my-templates', | ||||||||||||||||||||||||
| 'my-branch', | ||||||||||||||||||||||||
| expect.anything() | ||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||
|
Comment on lines
+208
to
+213
|
||||||||||||||||||||||||
| expect(MockedGitHub).toHaveBeenNthCalledWith( | |
| 2, | |
| 'https://github.com/my-org/my-templates', | |
| 'my-branch', | |
| expect.anything() | |
| ); | |
| expect(MockedGitHub).toHaveBeenNthCalledWith(2, { | |
| repoUrl: 'https://github.com/my-org/my-templates', | |
| branch: 'my-branch', | |
| terminal: expect.anything() | |
| }); |
Copilot
AI
Mar 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This toHaveBeenCalledWith assertion uses positional args, but PublicGitHubRepositorySource is constructed with an options object throughout the codebase. Update this to assert the options-object call shape so the test matches the real constructor invocation.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "changes": [ | ||
| { | ||
| "packageName": "@microsoft/spfx-cli", | ||
| "comment": "", | ||
| "type": "none" | ||
| } | ||
| ], | ||
| "packageName": "@microsoft/spfx-cli" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into the base class and deduplicate with the list action.