Compare commits

...

2 commits

Author SHA1 Message Date
Copilot
f38efdea4c
fix: gracefully fallback to body when body_path cannot be read (#671)
Some checks failed
main / build (push) Has been cancelled
* Initial plan

* fix: gracefully fallback to body when body_path cannot be read

Co-authored-by: chenrui333 <1580956+chenrui333@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: chenrui333 <1580956+chenrui333@users.noreply.github.com>
2025-10-06 23:50:32 -04:00
Copilot
cec1a1113b
fix(util): support brace expansion globs containing commas in parseInputFiles (#672)
* Initial plan

* fix(util): support brace expansion globs containing commas in parseInputFiles

Co-authored-by: chenrui333 <1580956+chenrui333@users.noreply.github.com>

* test(util): add comprehensive edge case coverage for brace expansion parsing

Co-authored-by: chenrui333 <1580956+chenrui333@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: chenrui333 <1580956+chenrui333@users.noreply.github.com>
2025-10-06 23:50:00 -04:00
3 changed files with 134 additions and 13 deletions

View file

@ -39,6 +39,18 @@ describe('util', () => {
'loom', 'loom',
]); ]);
}); });
it('handles globs with brace groups containing commas', () => {
assert.deepStrictEqual(parseInputFiles('./**/*.{exe,deb,tar.gz}\nfoo,bar'), [
'./**/*.{exe,deb,tar.gz}',
'foo',
'bar',
]);
});
it('handles single-line brace pattern correctly', () => {
assert.deepStrictEqual(parseInputFiles('./**/*.{exe,deb,tar.gz}'), [
'./**/*.{exe,deb,tar.gz}',
]);
});
}); });
describe('releaseBody', () => { describe('releaseBody', () => {
it('uses input body', () => { it('uses input body', () => {
@ -110,6 +122,52 @@ describe('util', () => {
}), }),
); );
}); });
it('falls back to body when body_path is missing', () => {
assert.equal(
releaseBody({
github_ref: '',
github_repository: '',
github_token: '',
input_body: 'fallback-body',
input_body_path: '__tests__/does-not-exist.txt',
input_draft: false,
input_prerelease: false,
input_files: [],
input_overwrite_files: undefined,
input_preserve_order: undefined,
input_name: undefined,
input_tag_name: undefined,
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
}),
'fallback-body',
);
});
it('returns undefined when body_path is missing and body is not provided', () => {
assert.equal(
releaseBody({
github_ref: '',
github_repository: '',
github_token: '',
input_body: undefined,
input_body_path: '__tests__/does-not-exist.txt',
input_draft: false,
input_prerelease: false,
input_files: [],
input_overwrite_files: undefined,
input_preserve_order: undefined,
input_name: undefined,
input_tag_name: undefined,
input_target_commitish: undefined,
input_discussion_category_name: undefined,
input_generate_release_notes: false,
input_make_latest: undefined,
}),
undefined,
);
});
}); });
describe('parseConfig', () => { describe('parseConfig', () => {
it('parses basic config', () => { it('parses basic config', () => {
@ -432,3 +490,36 @@ describe('util', () => {
}); });
}); });
}); });
describe('parseInputFiles edge cases', () => {
it('handles multiple brace groups on same line', () => {
assert.deepStrictEqual(parseInputFiles('./**/*.{exe,deb},./dist/**/*.{zip,tar.gz}'), [
'./**/*.{exe,deb}',
'./dist/**/*.{zip,tar.gz}',
]);
});
it('handles nested braces', () => {
assert.deepStrictEqual(parseInputFiles('path/{a,{b,c}}/file.txt'), ['path/{a,{b,c}}/file.txt']);
});
it('handles empty comma-separated values', () => {
assert.deepStrictEqual(parseInputFiles('foo,,bar'), ['foo', 'bar']);
});
it('handles commas with spaces around braces', () => {
assert.deepStrictEqual(parseInputFiles(' ./**/*.{exe,deb} , file.txt '), [
'./**/*.{exe,deb}',
'file.txt',
]);
});
it('handles mixed newlines and commas with braces', () => {
assert.deepStrictEqual(parseInputFiles('file1.txt\n./**/*.{exe,deb},file2.txt\nfile3.txt'), [
'file1.txt',
'./**/*.{exe,deb}',
'file2.txt',
'file3.txt',
]);
});
});

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

View file

@ -35,23 +35,53 @@ export const uploadUrl = (url: string): string => {
}; };
export const releaseBody = (config: Config): string | undefined => { export const releaseBody = (config: Config): string | undefined => {
return ( if (config.input_body_path) {
(config.input_body_path && readFileSync(config.input_body_path).toString('utf8')) || try {
config.input_body const contents = readFileSync(config.input_body_path, 'utf8');
return contents;
} catch (err: any) {
console.warn(
`⚠️ Failed to read body_path "${config.input_body_path}" (${err?.code ?? 'ERR'}). Falling back to 'body' input.`,
); );
}
}
return config.input_body;
}; };
type Env = { [key: string]: string | undefined }; type Env = { [key: string]: string | undefined };
const smartSplit = (input: string): string[] => {
const result: string[] = [];
let current = '';
let braceDepth = 0;
for (const ch of input) {
if (ch === '{') {
braceDepth++;
}
if (ch === '}') {
braceDepth--;
}
if (ch === ',' && braceDepth === 0) {
if (current.trim()) {
result.push(current.trim());
}
current = '';
} else {
current += ch;
}
}
if (current.trim()) {
result.push(current.trim());
}
return result;
};
export const parseInputFiles = (files: string): string[] => { export const parseInputFiles = (files: string): string[] => {
return files.split(/\r?\n/).reduce<string[]>( return files
(acc, line) => .split(/\r?\n/)
acc .flatMap((line) => smartSplit(line))
.concat(line.split(',')) .filter((pat) => pat.trim() !== '');
.filter((pat) => pat)
.map((pat) => pat.trim()),
[],
);
}; };
export const parseConfig = (env: Env): Config => { export const parseConfig = (env: Env): Config => {