Validate GitHub URLs Before Spending Money
A CLI without input validation is a vending machine that accepts expired coupons, parking tickets, and emotional support receipts. It still tries to do the work, then fails in weird ways.
Worse, in our case "tries to do the work" means spinning up a Sandbox. That costs real time and real money. We'd rather catch a typo before we boot a microVM.
Outcome
Add a URL validator to the CLI that rejects anything that isn't a GitHub repo URL, and exit early when validation fails.
Fast Track
- Write
isValidGitHubRepoUrl(input)that returns a boolean. - Call it at the top of the
actioncallback. - On failure, log a clear error and
returnbefore any Sandbox call.
Hands-on exercise
Open src/cli.ts and add a validator above the program setup:
import { Command } from 'commander';
function isValidGitHubRepoUrl(input: string): boolean {
return /^https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/?$/.test(input);
}
const program = new Command();
program
.name('repo-review')
.description('Clone and review a GitHub repository in a Sandbox')
.version('0.1.0');
program
.command('review <repoUrl>')
.description('Run a Sandbox review against a GitHub repository URL')
.action(async (repoUrl: string) => {
if (!isValidGitHubRepoUrl(repoUrl)) {
console.error(`Invalid GitHub repository URL: ${repoUrl}`);
console.error('Expected format: https://github.com/<owner>/<repo>');
return;
}
console.log(`Would review: ${repoUrl}`);
});
program.parse();The regex is intentionally narrow. It matches the standard GitHub web URL (https://github.com/owner/repo with an optional trailing slash) and nothing else. We're not trying to support every Git URL format on earth, we're trying to keep junk out of our pipeline.
We're also returning early instead of throwing. Throwing would crash the Node process with an unhandled rejection, which is loud but not helpful. We'll wire up real exit codes in lesson 2.4. For now, "log and return" is enough.
If a real repo URL fails validation, try it with and without a trailing slash. The regex allows both, but typos like https://github.com//owner/repo (double slash) or http:// (no s) will be rejected. That's the regex doing its job.
If you want to support GitHub Enterprise URLs (https://github.mycompany.com/...), you'll need a different regex. For this course, public GitHub only.
Try It
Run an invalid URL:
pnpm review not-a-urlExpected output:
Invalid GitHub repository URL: not-a-url
Expected format: https://github.com/<owner>/<repo>Then a valid one:
pnpm review https://github.com/vercel/examplesExpected output:
Would review: https://github.com/vercel/examplesSame valid output as last lesson, plus a guardrail at the front door.
Commit
git add src/cli.ts
git commit -m "feat(cli): validate GitHub repository URLs before sandbox work"Done-When
isValidGitHubRepoUrlreturnstrueforhttps://github.com/owner/repo(with or without trailing slash)isValidGitHubRepoUrlreturnsfalsefor plain strings, non-GitHub hosts, and malformed URLs- Invalid URLs print a clear error message
- Valid URLs reach the
console.logline
Solution
import { Command } from 'commander';
function isValidGitHubRepoUrl(input: string): boolean {
return /^https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/?$/.test(input);
}
const program = new Command();
program
.name('repo-review')
.description('Clone and review a GitHub repository in a Sandbox')
.version('0.1.0');
program
.command('review <repoUrl>')
.description('Run a Sandbox review against a GitHub repository URL')
.action(async (repoUrl: string) => {
if (!isValidGitHubRepoUrl(repoUrl)) {
console.error(`Invalid GitHub repository URL: ${repoUrl}`);
console.error('Expected format: https://github.com/<owner>/<repo>');
return;
}
console.log(`Would review: ${repoUrl}`);
});
program.parse();Was this helpful?