mirror of
				https://github.com/softprops/action-gh-release.git
				synced 2025-11-04 13:49:25 +00:00 
			
		
		
		
	Compare commits
	
		
			12 Commits
		
	
	
		
			v2.3.4
			...
			dependabot
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0d3324bd4e | ||
| 
						 | 
					0adea5aa98 | ||
| 
						 | 
					aa05f9d779 | ||
| 
						 | 
					bbaccb3a0c | ||
| 
						 | 
					50fda3f773 | ||
| 
						 | 
					5434409c2b | ||
| 
						 | 
					6da8fa9354 | ||
| 
						 | 
					f38efdea4c | ||
| 
						 | 
					cec1a1113b | ||
| 
						 | 
					aec2ec56f9 | ||
| 
						 | 
					4db716b167 | ||
| 
						 | 
					14820f2cee | 
							
								
								
									
										2
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							@@ -10,7 +10,7 @@ jobs:
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
 | 
			
		||||
 | 
			
		||||
      - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v4
 | 
			
		||||
      - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
 | 
			
		||||
        with:
 | 
			
		||||
          node-version-file: ".tool-versions"
 | 
			
		||||
          cache: "npm"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,3 +1,20 @@
 | 
			
		||||
## 2.4.1
 | 
			
		||||
 | 
			
		||||
## What's Changed
 | 
			
		||||
 | 
			
		||||
### Other Changes 🔄
 | 
			
		||||
 | 
			
		||||
* fix(util): support brace expansion globs containing commas in parseInputFiles by @Copilot in https://github.com/softprops/action-gh-release/pull/672
 | 
			
		||||
* fix: gracefully fallback to body when body_path cannot be read by @Copilot in https://github.com/softprops/action-gh-release/pull/671
 | 
			
		||||
 | 
			
		||||
## 2.4.0
 | 
			
		||||
 | 
			
		||||
## What's Changed
 | 
			
		||||
 | 
			
		||||
### Exciting New Features 🎉
 | 
			
		||||
 | 
			
		||||
* feat(action): respect working_directory for files globs by @stephenway in https://github.com/softprops/action-gh-release/pull/667
 | 
			
		||||
 | 
			
		||||
## 2.3.4
 | 
			
		||||
 | 
			
		||||
## What's Changed
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,18 @@ describe('util', () => {
 | 
			
		||||
        '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', () => {
 | 
			
		||||
    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', () => {
 | 
			
		||||
    it('parses basic config', () => {
 | 
			
		||||
@@ -128,6 +186,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -156,6 +215,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -183,6 +243,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -211,6 +272,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -243,6 +305,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: 'env-token',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -272,6 +335,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: 'input-token',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -300,6 +364,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -327,6 +392,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: false,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -354,6 +420,7 @@ describe('util', () => {
 | 
			
		||||
          github_ref: '',
 | 
			
		||||
          github_repository: '',
 | 
			
		||||
          github_token: '',
 | 
			
		||||
          input_working_directory: undefined,
 | 
			
		||||
          input_append_body: true,
 | 
			
		||||
          input_body: undefined,
 | 
			
		||||
          input_body_path: undefined,
 | 
			
		||||
@@ -388,6 +455,10 @@ describe('util', () => {
 | 
			
		||||
        'tests/data/foo/bar.txt',
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('resolves files relative to working_directory', async () => {
 | 
			
		||||
      assert.deepStrictEqual(paths(['data/**/*'], 'tests'), ['tests/data/foo/bar.txt']);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('unmatchedPatterns', () => {
 | 
			
		||||
@@ -397,6 +468,12 @@ describe('util', () => {
 | 
			
		||||
        ['tests/data/does/not/exist/*'],
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('resolves unmatched relative to working_directory', async () => {
 | 
			
		||||
      assert.deepStrictEqual(unmatchedPatterns(['data/does/not/exist/*'], 'tests'), [
 | 
			
		||||
        'data/does/not/exist/*',
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('replaceSpacesWithDots', () => {
 | 
			
		||||
@@ -413,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',
 | 
			
		||||
    ]);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,9 @@ inputs:
 | 
			
		||||
  files:
 | 
			
		||||
    description: "Newline-delimited list of path globs for asset files to upload"
 | 
			
		||||
    required: false
 | 
			
		||||
  working_directory:
 | 
			
		||||
    description: "Base directory to resolve 'files' globs against (defaults to job working-directory)"
 | 
			
		||||
    required: false
 | 
			
		||||
  overwrite_files:
 | 
			
		||||
    description: "Overwrite existing files with the same name. Defaults to true"
 | 
			
		||||
    required: false
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1129
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1129
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "action-gh-release",
 | 
			
		||||
  "version": "2.3.4",
 | 
			
		||||
  "version": "2.4.1",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "description": "GitHub Action for creating GitHub Releases",
 | 
			
		||||
  "main": "lib/main.js",
 | 
			
		||||
@@ -24,21 +24,21 @@
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@actions/core": "^1.11.1",
 | 
			
		||||
    "@actions/github": "^6.0.1",
 | 
			
		||||
    "@octokit/plugin-retry": "^8.0.2",
 | 
			
		||||
    "@octokit/plugin-throttling": "^11.0.2",
 | 
			
		||||
    "@octokit/plugin-retry": "^8.0.3",
 | 
			
		||||
    "@octokit/plugin-throttling": "^11.0.3",
 | 
			
		||||
    "glob": "^11.0.3",
 | 
			
		||||
    "mime-types": "^3.0.1"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/glob": "^9.0.0",
 | 
			
		||||
    "@types/mime-types": "^3.0.1",
 | 
			
		||||
    "@types/node": "^20.19.18",
 | 
			
		||||
    "@types/node": "^20.19.24",
 | 
			
		||||
    "@vercel/ncc": "^0.38.4",
 | 
			
		||||
    "@vitest/coverage-v8": "^3.2.4",
 | 
			
		||||
    "@vitest/coverage-v8": "^4.0.6",
 | 
			
		||||
    "prettier": "3.6.2",
 | 
			
		||||
    "ts-node": "^10.9.2",
 | 
			
		||||
    "typescript": "^5.9.2",
 | 
			
		||||
    "typescript": "^5.9.3",
 | 
			
		||||
    "typescript-formatter": "^7.2.2",
 | 
			
		||||
    "vitest": "^3.1.4"
 | 
			
		||||
    "vitest": "^4.0.4"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ async function run() {
 | 
			
		||||
      throw new Error(`⚠️ GitHub Releases requires a tag`);
 | 
			
		||||
    }
 | 
			
		||||
    if (config.input_files) {
 | 
			
		||||
      const patterns = unmatchedPatterns(config.input_files);
 | 
			
		||||
      const patterns = unmatchedPatterns(config.input_files, config.input_working_directory);
 | 
			
		||||
      patterns.forEach((pattern) => {
 | 
			
		||||
        if (config.input_fail_on_unmatched_files) {
 | 
			
		||||
          throw new Error(`⚠️  Pattern '${pattern}' does not match any files.`);
 | 
			
		||||
@@ -50,7 +50,7 @@ async function run() {
 | 
			
		||||
    //);
 | 
			
		||||
    const rel = await release(config, new GitHubReleaser(gh));
 | 
			
		||||
    if (config.input_files && config.input_files.length > 0) {
 | 
			
		||||
      const files = paths(config.input_files);
 | 
			
		||||
      const files = paths(config.input_files, config.input_working_directory);
 | 
			
		||||
      if (files.length == 0) {
 | 
			
		||||
        if (config.input_fail_on_unmatched_files) {
 | 
			
		||||
          throw new Error(`⚠️ ${config.input_files} does not include a valid file.`);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										84
									
								
								src/util.ts
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								src/util.ts
									
									
									
									
									
								
							@@ -1,5 +1,6 @@
 | 
			
		||||
import * as glob from 'glob';
 | 
			
		||||
import { statSync, readFileSync } from 'fs';
 | 
			
		||||
import * as pathLib from 'path';
 | 
			
		||||
 | 
			
		||||
export interface Config {
 | 
			
		||||
  github_token: string;
 | 
			
		||||
@@ -12,6 +13,7 @@ export interface Config {
 | 
			
		||||
  input_body?: string;
 | 
			
		||||
  input_body_path?: string;
 | 
			
		||||
  input_files?: string[];
 | 
			
		||||
  input_working_directory?: string;
 | 
			
		||||
  input_overwrite_files?: boolean;
 | 
			
		||||
  input_draft?: boolean;
 | 
			
		||||
  input_preserve_order?: boolean;
 | 
			
		||||
@@ -33,23 +35,53 @@ export const uploadUrl = (url: string): string => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const releaseBody = (config: Config): string | undefined => {
 | 
			
		||||
  return (
 | 
			
		||||
    (config.input_body_path && readFileSync(config.input_body_path).toString('utf8')) ||
 | 
			
		||||
    config.input_body
 | 
			
		||||
  if (config.input_body_path) {
 | 
			
		||||
    try {
 | 
			
		||||
      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 };
 | 
			
		||||
 | 
			
		||||
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[] => {
 | 
			
		||||
  return files.split(/\r?\n/).reduce<string[]>(
 | 
			
		||||
    (acc, line) =>
 | 
			
		||||
      acc
 | 
			
		||||
        .concat(line.split(','))
 | 
			
		||||
        .filter((pat) => pat)
 | 
			
		||||
        .map((pat) => pat.trim()),
 | 
			
		||||
    [],
 | 
			
		||||
  );
 | 
			
		||||
  return files
 | 
			
		||||
    .split(/\r?\n/)
 | 
			
		||||
    .flatMap((line) => smartSplit(line))
 | 
			
		||||
    .filter((pat) => pat.trim() !== '');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const parseConfig = (env: Env): Config => {
 | 
			
		||||
@@ -62,6 +94,7 @@ export const parseConfig = (env: Env): Config => {
 | 
			
		||||
    input_body: env.INPUT_BODY,
 | 
			
		||||
    input_body_path: env.INPUT_BODY_PATH,
 | 
			
		||||
    input_files: parseInputFiles(env.INPUT_FILES || ''),
 | 
			
		||||
    input_working_directory: env.INPUT_WORKING_DIRECTORY || undefined,
 | 
			
		||||
    input_overwrite_files: env.INPUT_OVERWRITE_FILES
 | 
			
		||||
      ? env.INPUT_OVERWRITE_FILES == 'true'
 | 
			
		||||
      : undefined,
 | 
			
		||||
@@ -84,17 +117,34 @@ const parseMakeLatest = (value: string | undefined): 'true' | 'false' | 'legacy'
 | 
			
		||||
  return undefined;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const paths = (patterns: string[]): string[] => {
 | 
			
		||||
export const paths = (patterns: string[], cwd?: string): string[] => {
 | 
			
		||||
  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
			
		||||
    return acc.concat(glob.sync(pattern).filter((path) => statSync(path).isFile()));
 | 
			
		||||
    const matches = glob.sync(pattern, { cwd, dot: true, absolute: false });
 | 
			
		||||
    const resolved = matches
 | 
			
		||||
      .map((p) => (cwd ? pathLib.join(cwd, p) : p))
 | 
			
		||||
      .filter((p) => {
 | 
			
		||||
        try {
 | 
			
		||||
          return statSync(p).isFile();
 | 
			
		||||
        } catch {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    return acc.concat(resolved);
 | 
			
		||||
  }, []);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const unmatchedPatterns = (patterns: string[]): string[] => {
 | 
			
		||||
export const unmatchedPatterns = (patterns: string[], cwd?: string): string[] => {
 | 
			
		||||
  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
			
		||||
    return acc.concat(
 | 
			
		||||
      glob.sync(pattern).filter((path) => statSync(path).isFile()).length == 0 ? [pattern] : [],
 | 
			
		||||
    );
 | 
			
		||||
    const matches = glob.sync(pattern, { cwd, dot: true, absolute: false });
 | 
			
		||||
    const files = matches.filter((p) => {
 | 
			
		||||
      try {
 | 
			
		||||
        const full = cwd ? pathLib.join(cwd, p) : p;
 | 
			
		||||
        return statSync(full).isFile();
 | 
			
		||||
      } catch {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    return acc.concat(files.length == 0 ? [pattern] : []);
 | 
			
		||||
  }, []);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user