Skip to content

Commit 7be731a

Browse files
authored
Merge pull request #142 from amir-s/fix-dev-open
Fix dev open
2 parents 1c7cbc6 + 3ec2ace commit 7be731a

File tree

2 files changed

+121
-6
lines changed

2 files changed

+121
-6
lines changed

WARP.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# WARP.md
2+
3+
This file provides guidance to WARP (warp.dev) when working with code in this repository.
4+
5+
## Commonly used commands
6+
7+
- Build (DIY):
8+
```bash
9+
deno compile --output dev-cli -A main.ts
10+
```
11+
12+
- Build with explicit includes (matches CI for dynamic imports):
13+
```bash
14+
INCLUDES=$(find modules -type f -name "*.ts" -exec echo --include={} \; | xargs); deno compile -A $INCLUDES --output dev-cli main.ts
15+
```
16+
17+
- Run all tests:
18+
```bash
19+
deno task test
20+
```
21+
22+
- Run a single test file:
23+
```bash
24+
deno run -A test.ts modules/{module}/tests/{file}.test.ts
25+
```
26+
27+
- Format and lint:
28+
```bash
29+
deno fmt
30+
deno fmt --check
31+
deno lint
32+
```
33+
34+
- Release (bumps version, tags and pushes):
35+
```bash
36+
deno task release
37+
```
38+
Note: release scripts enforce being on the correct branch with a clean working tree.
39+
40+
- Shell integration (for the dev function and cd/source hand-off):
41+
```bash
42+
dev-cli shell install
43+
```
44+
Toggle local build vs prod binary:
45+
```bash
46+
dev shell use local
47+
dev shell use prod
48+
```
49+
50+
## High-level architecture
51+
52+
- **Entry and dispatch:**
53+
main.ts parses argv, fuzzy-matches subcommands, and dynamically imports ./modules/NAME/index.ts. It can also route to a contextual module when an exact task name exists in package.json or deno.json of the current project.
54+
55+
- **Module pattern:**
56+
Each module resides under modules/NAME. index.ts exports run(), and help.ts exports help metadata. Tests live in modules/NAME/tests/*.test.ts and are invoked by the custom test runner (test.ts).
57+
58+
- **Configuration:**
59+
modules/config loads and persists ~/.dev.config.json, exposing config(key, default?) and writeConfig(). Notable keys: clone.path, clone.cd, clone.ssh, contextual.node.deno, contextual.node.yarn, shell.function, lan.scan.lookup.timeout, ip.ipinfoio.token.
60+
61+
- **Shell integration:**
62+
modules/shell provides init, install, and use local|prod. At runtime, main.ts writes cd: and source: commands to DEV_CLI_CMD_EXEC_FILE for the shell shim to consume, and checks DEV_CLI_BIN_PATH to display whether local dev is active.
63+
64+
- **Contextual commands:**
65+
modules/contextual chooses deno task CMD by default when tasks come from deno.json, else npm run CMD (or yarn if configured) for package.json scripts.
66+
67+
- **_cd hooks:**
68+
If a project's dev.json defines scripts._cd, modules/_cd prompts on first run and records allow/deny in a project-local .dev.json (auto-added to common ignore files). Approved commands then run non-interactively on future cd.
69+
70+
- **Notable utilities:**
71+
utils/spinner.ts wraps yurnalist activity spinners.
72+
utils/version.ts stores the current version used by main and release.
73+
utils/release.ts contains release guardrails.
74+
utils/knownhosts.ts supports SSH known_hosts checks used by clone.
75+
76+
- **Networking and system modules:**
77+
modules/lan uses arp, dns-sd, dig, chokidar, and a MAC vendor lookup to scan and group devices. modules/ip calls ipinfo.io to fetch IP metadata. Several modules rely on git, ssh-keyscan, rsync, and related tools.
78+
79+
- **CI and distribution:**
80+
GitHub Actions runs tests with Deno 2.x and builds multi-OS binaries using deno compile with explicit --include flags. install.sh downloads the appropriate artifact for the host OS/arch, installs it as dev-cli, and wires the shell init line.
81+
82+
## Important notes
83+
84+
- Deno 2.x is required. Avoid running the CLI with sudo (sudo-block enforces this).
85+
- deno compile with dynamic imports requires the explicit includes technique shown above; CI's release workflow demonstrates the correct pattern.
86+
- dev up supports exactly one dependency file per project (package.json, Gemfile, or requirements.txt); it errors if multiple are present.
87+
- dev open pr prevents PRs from protected branches and will offer to push the current branch if needed.
88+
- clone will ssh-keyscan and append unknown hosts to ~/.ssh/known_hosts if clone.ssh is true.

modules/open/index.ts

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,31 @@ const remoteExists = async (branch: string) => {
3535
);
3636
};
3737

38-
const getRemoteUrl = async () => {
39-
const { stdout } = await $`git config --get remote.origin.url`;
40-
const url = stdout.trim();
41-
if (url.trim().startsWith("git@")) {
42-
return `https://${url.trim().replace(":", "/").slice(4, -4)}`;
38+
const getRemoteUrl = async (): Promise<string | null> => {
39+
try {
40+
const stdout = (await $`git config --get remote.origin.url`).toString();
41+
const raw = stdout.trim();
42+
if (!raw) return null;
43+
if (raw.startsWith("git@")) {
44+
const hostPath = raw.replace(":", "/").replace(/^git@/, "");
45+
const withoutGit = hostPath.replace(/\.git$/, "");
46+
return `https://${withoutGit}`;
47+
}
48+
return raw.replace(/\.git$/, "");
49+
} catch (_) {
50+
// No remote configured (or git returned non-zero)
51+
return null;
52+
}
53+
};
54+
55+
const getCurrentBranch = async (): Promise<string | null> => {
56+
try {
57+
const out = (await $`git branch --show-current`).toString();
58+
const b = out.trim();
59+
return b.length > 0 ? b : null;
60+
} catch (_) {
61+
return null;
4362
}
44-
return url.trim().slice(0, -4);
4563
};
4664

4765
export const run = async ({ args }: ModuleRunOptions) => {
@@ -55,6 +73,15 @@ export const run = async ({ args }: ModuleRunOptions) => {
5573
const command = args[0];
5674

5775
const remoteUrl = await getRemoteUrl();
76+
if (!remoteUrl) {
77+
const branch = await getCurrentBranch();
78+
report.error('this repository does not have a git remote configured (missing "origin").');
79+
report.info("tip: add a remote and push your branch:".gray);
80+
report.info(` ${"git remote add origin URL".bold}`);
81+
report.info(` ${`git push -u origin ${branch ?? "BRANCH_NAME"}`.bold}`);
82+
return;
83+
}
84+
5885
const newPath = args[1] === "--new" ? "/new" : "";
5986

6087
if (!command) {

0 commit comments

Comments
 (0)