Skip to content

Add --remote-source flag to create command#182

Open
nick-pape wants to merge 4 commits intoSharePoint:mainfrom
nick-pape:nick-pape/remote-source
Open

Add --remote-source flag to create command#182
nick-pape wants to merge 4 commits intoSharePoint:mainfrom
nick-pape:nick-pape/remote-source

Conversation

@nick-pape
Copy link
Contributor

Description

Adds a repeatable --remote-source URL flag to the create command, letting users point at custom public GitHub repos containing SPFx templates.

Remote sources are additive — they work alongside both the default GitHub source and --local-template sources:

Command Sources used
spfx create --template foo default GitHub only (unchanged)
spfx create --template foo --local-template ./t local only (unchanged)
spfx create --template foo --remote-source URL default GitHub + remote
spfx create --template foo --local-template ./t --remote-source URL local + remote

The --remote-source flag also supports /tree/<ref> syntax in the URL for branch selection (using the existing parseGitHubUrlAndRef helper).

How was this tested

  • rushx build — 50/50 tests pass (4 new --remote-source tests, 45 existing, 1 help snapshot)
  • Tests were written TDD before the implementation
  • New tests cover: single remote source, multiple remote sources, branch extraction from /tree/, and interaction with --local-template

Type of change

  • New feature (non-breaking change which adds functionality)

Closes #90

🤖 Generated with Claude Code

Adds a repeatable --remote-source URL flag to the create command, letting
users point at custom public GitHub repos containing SPFx templates. Remote
sources are additive — they work alongside both the default GitHub source
and --local-template sources.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 24, 2026 18:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a repeatable --remote-source URL flag to spfx create so users can include additional public GitHub repositories as template sources, alongside the default GitHub source and/or any --local-template sources.

Changes:

  • Introduces --remote-source (repeatable) to create, and wires it into repository source selection.
  • Adds TDD coverage and updates help/output snapshots for the new flag.
  • Updates the CLI README and adds a Rush change file entry.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
common/changes/@microsoft/spfx-cli/remote-source_2026-03-24.json Rush change file for the CLI change set.
apps/spfx-cli/src/cli/test/snapshots/CommandLineHelp.test.ts.snap Updates CLI help snapshot to include --remote-source.
apps/spfx-cli/src/cli/actions/tests/snapshots/CreateAction.test.ts.snap Updates snapshots for new source-selection test cases.
apps/spfx-cli/src/cli/actions/tests/CreateAction.test.ts Adds tests for single/multiple remote sources, /tree/<ref> extraction, and interaction with --local-template.
apps/spfx-cli/src/cli/actions/CreateAction.ts Implements the new --remote-source parameter and adds remote sources to the repository manager.
apps/spfx-cli/README.md Documents --remote-source in the flags table and adds an example.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +218 to +222
for (const remoteUrl of this._remoteSourcesParameter.values) {
const { repoUrl: additionalRepoUrl, urlBranch: additionalUrlBranch } =
parseGitHubUrlAndRef(remoteUrl);
terminal.writeLine(
`Adding remote template source: ${additionalRepoUrl}` +
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

--remote-source URLs are passed through parseGitHubUrlAndRef() without any validation (e.g., empty/whitespace values, or non-github.com hosts). Since PublicGitHubRepositorySource ultimately only supports github.com (and builds downloads via codeload.github.com), invalid/unsupported URLs will fail later during getTemplatesAsync() with a less actionable error. Consider validating each remoteUrl up front (trim + non-empty + github.com host + expected path shape) and throwing a clear error that references --remote-source and the supported URL formats (including optional /tree/<ref>).

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Valid observation. Today PublicGitHubRepositorySource already throws with the URL and reason (e.g. Invalid GitHub repository URL: ... or Failed to download repository: 404 Not Found), so users do get an actionable error. Early validation would improve the message but isn't blocking for v0. Filed as a potential follow-up alongside #178 (error message improvements).

nick-pape and others added 3 commits March 24, 2026 14:34
Main merged PR SharePoint#175 which extracted parseGitHubUrlAndRef to
utilities/github.ts and introduced SPFxActionBase. Re-added
PublicGitHubRepositorySource import and parseGitHubUrlAndRef import
needed by the --remote-source loop.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
SharePoint#180 changed the constructor to take an options object. Updated the
--remote-source call site in CreateAction to use { repoUrl, branch, terminal }.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 24, 2026 19:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +180 to +184
expect(MockedGitHub).toHaveBeenNthCalledWith(
1,
'https://github.com/SharePoint/spfx',
undefined,
expect.anything()
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

PublicGitHubRepositorySource is constructed with an options object ({ repoUrl, branch, terminal }) in this test file and in the implementation. This expectation uses positional args, so it won’t match the actual constructor call. Update it to assert the options-object shape for the default source call.

Copilot uses AI. Check for mistakes.
Comment on lines +187 to +191
expect(MockedGitHub).toHaveBeenNthCalledWith(
2,
'https://github.com/my-org/my-templates',
undefined,
expect.anything()
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This expectation also assumes a positional constructor signature for PublicGitHubRepositorySource. Align it with the actual call shape by asserting { repoUrl: 'https://github.com/my-org/my-templates', branch: undefined, terminal: expect.anything() }.

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +213
expect(MockedGitHub).toHaveBeenNthCalledWith(
2,
'https://github.com/my-org/my-templates',
'my-branch',
expect.anything()
);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

PublicGitHubRepositorySource is instantiated with an options object, but this assertion checks positional args. Update it to validate the second call receives { repoUrl: 'https://github.com/my-org/my-templates', branch: 'my-branch', terminal: expect.anything() }.

Suggested change
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 uses AI. Check for mistakes.
Comment on lines +226 to +230
expect(MockedGitHub).toHaveBeenCalledWith(
'https://github.com/my-org/my-templates',
undefined,
expect.anything()
);
Copy link

Copilot AI Mar 24, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +90
this._remoteSourcesParameter = this.defineStringListParameter({
parameterLongName: '--remote-source',
argumentName: 'URL',
description: 'Public GitHub repository URL to use as an additional template source (repeatable)'
});
Copy link
Contributor

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.

Comment on lines +174 to +189
// 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}` +
`${additionalUrlBranch ? ` (branch: ${additionalUrlBranch})` : ''}`
);
manager.addSource(
new PublicGitHubRepositorySource({
repoUrl: additionalRepoUrl,
branch: additionalUrlBranch,
terminal
})
);
}
Copy link
Contributor

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add --remote-source / --github-source flag to CLI

3 participants