Skip to content

Commit d3e77ea

Browse files
committed
fix: require an explicit attachment service URL
1 parent 1ef9c13 commit d3e77ea

4 files changed

Lines changed: 41 additions & 10 deletions

File tree

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ The service URL resolves separately:
4848
| ---: | --- | --- |
4949
| 1 | `GITHUB_ATTACHMENTS_URL` in the process environment | Current process override |
5050
| 2 | `${XDG_CONFIG_HOME:-~/.config}/github-pr-attachments/url` | User-level deployment |
51-
| 3 | `https://github-pr-attachments.none23.workers.dev` | Backward-compatible default |
5251

53-
Repository `.env` cannot redirect a user-level token to another service. User profile files and repository `.env` are parsed as data, never sourced as shell code.
52+
The URL is required; there is no shared-service fallback. Repository `.env` cannot redirect a user-level token to another service. User profile files and repository `.env` are parsed as data, never sourced as shell code.
5453

5554
The CLI prints only Markdown by default:
5655

5756
```markdown
58-
![Settings after the change](https://github-pr-attachments.none23.workers.dev/a/.../screenshot.png)
57+
![Settings after the change](https://your-worker.your-subdomain.workers.dev/a/.../screenshot.png)
5958
```
6059

6160
Pass `--json` to receive the complete upload response. Diagnostics and errors go to standard error.

bin/config.mjs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { homedir } from "node:os";
33
import { dirname, join, parse } from "node:path";
44
import process from "node:process";
55

6-
const DEFAULT_SERVICE_URL = "https://github-pr-attachments.none23.workers.dev";
7-
86
export async function loadConfiguration() {
97
const repositoryRoot = await findRepositoryRoot(process.cwd());
108
const repository = parseDotEnv(await readOptionalFile(join(repositoryRoot, ".env")));
@@ -24,11 +22,15 @@ export async function loadConfiguration() {
2422
);
2523
}
2624

25+
const serviceUrl = firstValue(process.env.GITHUB_ATTACHMENTS_URL, userUrl);
26+
if (serviceUrl === undefined) {
27+
throw new Error(
28+
"No service URL found in GITHUB_ATTACHMENTS_URL or ~/.config/github-pr-attachments/url",
29+
);
30+
}
31+
2732
return {
28-
serviceUrl: (
29-
firstValue(process.env.GITHUB_ATTACHMENTS_URL, userUrl, DEFAULT_SERVICE_URL) ??
30-
DEFAULT_SERVICE_URL
31-
).replace(/\/$/, ""),
33+
serviceUrl: serviceUrl.replace(/\/$/, ""),
3234
token,
3335
};
3436
}

skills/attach-github-pr-files/scripts/upload.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ url_file=$user_config_root/github-pr-attachments/url
3838
token=
3939
[ ! -r "$token_file" ] || token=$(sed -n '1p' "$token_file")
4040
[ -z "${GITHUB_ATTACHMENTS_TOKEN-}" ] || token=$GITHUB_ATTACHMENTS_TOKEN
41-
service_url=https://github-pr-attachments.none23.workers.dev
41+
service_url=
4242
[ ! -r "$url_file" ] || service_url=$(sed -n '1p' "$url_file")
4343
[ -z "${GITHUB_ATTACHMENTS_URL-}" ] || service_url=$GITHUB_ATTACHMENTS_URL
4444

@@ -50,6 +50,10 @@ if [ -z "$token" ]; then
5050
echo "No upload token found in repository .env, GITHUB_ATTACHMENTS_TOKEN, or ~/.config/github-pr-attachments/token" >&2
5151
exit 1
5252
fi
53+
if [ -z "$service_url" ]; then
54+
echo "No service URL found in GITHUB_ATTACHMENTS_URL or ~/.config/github-pr-attachments/url" >&2
55+
exit 1
56+
fi
5357

5458
output=$(mktemp)
5559
trap 'rm -f "$output"' EXIT HUP INT TERM

test-node/cli.test.mjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,32 @@ test("skill uploader reads the user-level service profile", async (context) => {
111111
assert.equal(result.stdout, EXPECTED_MARKDOWN);
112112
});
113113

114+
test("CLI refuses to upload without an explicitly configured service URL", async (context) => {
115+
const repository = await temporaryRepository(context);
116+
const environment = withoutAttachmentConfiguration();
117+
environment.GITHUB_ATTACHMENTS_TOKEN = "test-token";
118+
environment.XDG_CONFIG_HOME = join(repository, "empty-config");
119+
120+
const result = await run(process.execPath, [CLI, FIXTURE], environment, repository);
121+
122+
assert.equal(result.exitCode, 1);
123+
assert.match(result.stderr, /No service URL found/);
124+
assert.equal(result.stdout, "");
125+
});
126+
127+
test("skill uploader refuses to upload without an explicitly configured service URL", async (context) => {
128+
const repository = await temporaryRepository(context);
129+
const environment = withoutAttachmentConfiguration();
130+
environment.GITHUB_ATTACHMENTS_TOKEN = "test-token";
131+
environment.XDG_CONFIG_HOME = join(repository, "empty-config");
132+
133+
const result = await run(SKILL_UPLOADER, [FIXTURE], environment, repository);
134+
135+
assert.equal(result.exitCode, 1);
136+
assert.match(result.stderr, /No service URL found/);
137+
assert.equal(result.stdout, "");
138+
});
139+
114140
async function startServer(context, expected) {
115141
const server = createServer(async (request, response) => {
116142
assert.equal(request.method, "POST");

0 commit comments

Comments
 (0)