mirror of
				https://github.com/softprops/action-gh-release.git
				synced 2025-11-03 21:29:24 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			copilot/fi
			...
			v2.4.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6da8fa9354 | ||
| 
						 | 
					f38efdea4c | ||
| 
						 | 
					cec1a1113b | 
							
								
								
									
										3
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							@@ -12,6 +12,9 @@ updates:
 | 
				
			|||||||
      - dependency-name: node-fetch
 | 
					      - dependency-name: node-fetch
 | 
				
			||||||
        versions:
 | 
					        versions:
 | 
				
			||||||
          - ">=3.0.0"
 | 
					          - ">=3.0.0"
 | 
				
			||||||
 | 
					      - dependency-name: "@types/node"
 | 
				
			||||||
 | 
					        versions:
 | 
				
			||||||
 | 
					          - ">=22.0.0"
 | 
				
			||||||
    commit-message:
 | 
					    commit-message:
 | 
				
			||||||
      prefix: "chore(deps)"
 | 
					      prefix: "chore(deps)"
 | 
				
			||||||
  - package-ecosystem: github-actions
 | 
					  - package-ecosystem: github-actions
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,3 +1,12 @@
 | 
				
			|||||||
 | 
					## 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
 | 
					## 2.4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## What's Changed
 | 
					## What's Changed
 | 
				
			||||||
@@ -6,12 +15,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* feat(action): respect working_directory for files globs by @stephenway in https://github.com/softprops/action-gh-release/pull/667
 | 
					* feat(action): respect working_directory for files globs by @stephenway in https://github.com/softprops/action-gh-release/pull/667
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Other Changes 🔄
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Move action runtime to node24 and require Node >=24
 | 
					 | 
				
			||||||
* Update @types/node to ^22 for Node 24 compatibility
 | 
					 | 
				
			||||||
* Enable Dependabot updates for @types/node >=22
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.3.4
 | 
					## 2.3.4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## What's Changed
 | 
					## What's Changed
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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',
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ outputs:
 | 
				
			|||||||
  assets:
 | 
					  assets:
 | 
				
			||||||
    description: "JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/reference/repos#upload-a-release-asset--code-samples) (minus the `uploader` field)"
 | 
					    description: "JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/reference/repos#upload-a-release-asset--code-samples) (minus the `uploader` field)"
 | 
				
			||||||
runs:
 | 
					runs:
 | 
				
			||||||
  using: "node24"
 | 
					  using: "node20"
 | 
				
			||||||
  main: "dist/index.js"
 | 
					  main: "dist/index.js"
 | 
				
			||||||
branding:
 | 
					branding:
 | 
				
			||||||
  color: "green"
 | 
					  color: "green"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										15
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,12 +1,12 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "action-gh-release",
 | 
					  "name": "action-gh-release",
 | 
				
			||||||
  "version": "2.4.0",
 | 
					  "version": "2.4.1",
 | 
				
			||||||
  "lockfileVersion": 3,
 | 
					  "lockfileVersion": 3,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "packages": {
 | 
					  "packages": {
 | 
				
			||||||
    "": {
 | 
					    "": {
 | 
				
			||||||
      "name": "action-gh-release",
 | 
					      "name": "action-gh-release",
 | 
				
			||||||
      "version": "2.4.0",
 | 
					      "version": "2.4.1",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "@actions/core": "^1.11.1",
 | 
					        "@actions/core": "^1.11.1",
 | 
				
			||||||
        "@actions/github": "^6.0.1",
 | 
					        "@actions/github": "^6.0.1",
 | 
				
			||||||
@@ -18,7 +18,7 @@
 | 
				
			|||||||
      "devDependencies": {
 | 
					      "devDependencies": {
 | 
				
			||||||
        "@types/glob": "^9.0.0",
 | 
					        "@types/glob": "^9.0.0",
 | 
				
			||||||
        "@types/mime-types": "^3.0.1",
 | 
					        "@types/mime-types": "^3.0.1",
 | 
				
			||||||
        "@types/node": "^22",
 | 
					        "@types/node": "^20.19.19",
 | 
				
			||||||
        "@vercel/ncc": "^0.38.4",
 | 
					        "@vercel/ncc": "^0.38.4",
 | 
				
			||||||
        "@vitest/coverage-v8": "^3.2.4",
 | 
					        "@vitest/coverage-v8": "^3.2.4",
 | 
				
			||||||
        "prettier": "3.6.2",
 | 
					        "prettier": "3.6.2",
 | 
				
			||||||
@@ -26,9 +26,6 @@
 | 
				
			|||||||
        "typescript": "^5.9.3",
 | 
					        "typescript": "^5.9.3",
 | 
				
			||||||
        "typescript-formatter": "^7.2.2",
 | 
					        "typescript-formatter": "^7.2.2",
 | 
				
			||||||
        "vitest": "^3.1.4"
 | 
					        "vitest": "^3.1.4"
 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=24"
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@actions/core": {
 | 
					    "node_modules/@actions/core": {
 | 
				
			||||||
@@ -1485,9 +1482,9 @@
 | 
				
			|||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/node": {
 | 
					    "node_modules/@types/node": {
 | 
				
			||||||
      "version": "22.18.8",
 | 
					      "version": "20.19.19",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.19.tgz",
 | 
				
			||||||
      "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==",
 | 
					      "integrity": "sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "action-gh-release",
 | 
					  "name": "action-gh-release",
 | 
				
			||||||
  "version": "2.4.0",
 | 
					  "version": "2.4.1",
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "description": "GitHub Action for creating GitHub Releases",
 | 
					  "description": "GitHub Action for creating GitHub Releases",
 | 
				
			||||||
  "main": "lib/main.js",
 | 
					  "main": "lib/main.js",
 | 
				
			||||||
@@ -21,9 +21,6 @@
 | 
				
			|||||||
    "actions"
 | 
					    "actions"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "author": "softprops",
 | 
					  "author": "softprops",
 | 
				
			||||||
  "engines": {
 | 
					 | 
				
			||||||
    "node": ">=24"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@actions/core": "^1.11.1",
 | 
					    "@actions/core": "^1.11.1",
 | 
				
			||||||
    "@actions/github": "^6.0.1",
 | 
					    "@actions/github": "^6.0.1",
 | 
				
			||||||
@@ -35,7 +32,7 @@
 | 
				
			|||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/glob": "^9.0.0",
 | 
					    "@types/glob": "^9.0.0",
 | 
				
			||||||
    "@types/mime-types": "^3.0.1",
 | 
					    "@types/mime-types": "^3.0.1",
 | 
				
			||||||
    "@types/node": "^22",
 | 
					    "@types/node": "^20.19.19",
 | 
				
			||||||
    "@vercel/ncc": "^0.38.4",
 | 
					    "@vercel/ncc": "^0.38.4",
 | 
				
			||||||
    "@vitest/coverage-v8": "^3.2.4",
 | 
					    "@vitest/coverage-v8": "^3.2.4",
 | 
				
			||||||
    "prettier": "3.6.2",
 | 
					    "prettier": "3.6.2",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -183,7 +183,7 @@ export const upload = async (
 | 
				
			|||||||
        'content-type': mime,
 | 
					        'content-type': mime,
 | 
				
			||||||
        authorization: `token ${config.github_token}`,
 | 
					        authorization: `token ${config.github_token}`,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      data: fh.readableWebStream(),
 | 
					      data: fh.readableWebStream({ type: 'bytes' }),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    const json = resp.data;
 | 
					    const json = resp.data;
 | 
				
			||||||
    if (resp.status !== 201) {
 | 
					    if (resp.status !== 201) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								src/util.ts
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/util.ts
									
									
									
									
									
								
							@@ -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 => {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user