mirror of
				https://github.com/softprops/action-gh-release.git
				synced 2025-11-03 21:29:24 +00:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			v2.0.7
			...
			reintroduc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					5970a9ee86 | ||
| 
						 | 
					4d12fe762c | ||
| 
						 | 
					f20f71e9fd | ||
| 
						 | 
					040bca2f2d | 
							
								
								
									
										14
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,14 +0,0 @@
 | 
				
			|||||||
version: 2
 | 
					 | 
				
			||||||
updates:
 | 
					 | 
				
			||||||
- package-ecosystem: npm
 | 
					 | 
				
			||||||
  directory: "/"
 | 
					 | 
				
			||||||
  schedule:
 | 
					 | 
				
			||||||
    interval: weekly
 | 
					 | 
				
			||||||
  ignore:
 | 
					 | 
				
			||||||
  - dependency-name: node-fetch
 | 
					 | 
				
			||||||
    versions:
 | 
					 | 
				
			||||||
    - ">=3.0.0"
 | 
					 | 
				
			||||||
- package-ecosystem: github-actions
 | 
					 | 
				
			||||||
  directory: "/"
 | 
					 | 
				
			||||||
  schedule:
 | 
					 | 
				
			||||||
    interval: weekly
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								.github/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.github/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,22 +0,0 @@
 | 
				
			|||||||
changelog:
 | 
					 | 
				
			||||||
  exclude:
 | 
					 | 
				
			||||||
    labels:
 | 
					 | 
				
			||||||
      - ignore-for-release
 | 
					 | 
				
			||||||
      - github-actions
 | 
					 | 
				
			||||||
    authors:
 | 
					 | 
				
			||||||
      - octocat
 | 
					 | 
				
			||||||
      - renovate[bot]
 | 
					 | 
				
			||||||
  categories:
 | 
					 | 
				
			||||||
    - title: Breaking Changes 🛠
 | 
					 | 
				
			||||||
      labels:
 | 
					 | 
				
			||||||
        - breaking-change
 | 
					 | 
				
			||||||
    - title: Exciting New Features 🎉
 | 
					 | 
				
			||||||
      labels:
 | 
					 | 
				
			||||||
        - enhancement
 | 
					 | 
				
			||||||
        - feature
 | 
					 | 
				
			||||||
    - title: Bug fixes 🐛
 | 
					 | 
				
			||||||
      labels:
 | 
					 | 
				
			||||||
        - bug
 | 
					 | 
				
			||||||
    - title: Other Changes 🔄
 | 
					 | 
				
			||||||
      labels:
 | 
					 | 
				
			||||||
        - "*"
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							@@ -8,7 +8,7 @@ jobs:
 | 
				
			|||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      # https://github.com/actions/checkout
 | 
					      # https://github.com/actions/checkout
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Install
 | 
					      - name: Install
 | 
				
			||||||
        run: npm ci
 | 
					        run: npm ci
 | 
				
			||||||
      - name: Build
 | 
					      - name: Build
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,40 +1,3 @@
 | 
				
			|||||||
## 2.0.6
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- maintenance release with updated dependencies
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Factor in file names with spaces when upserting files [#446](https://github.com/softprops/action-gh-release/pull/446) via [@MystiPanda](https://github.com/MystiPanda)
 | 
					 | 
				
			||||||
- Improvements to error handling [#449](https://github.com/softprops/action-gh-release/pull/449) via [@till](https://github.com/till)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Minor follow up to [#417](https://github.com/softprops/action-gh-release/pull/417). [#425](https://github.com/softprops/action-gh-release/pull/425)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Declare `make_latest` as an input field in `action.yml` [#419](https://github.com/softprops/action-gh-release/pull/419)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Revisit approach to [#384](https://github.com/softprops/action-gh-release/pull/384) making unresolved pattern failures opt-in [#417](https://github.com/softprops/action-gh-release/pull/417)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Add support for make_latest property [#304](https://github.com/softprops/action-gh-release/pull/304) via [@samueljseay](https://github.com/samueljseay)
 | 
					 | 
				
			||||||
- Fail run if files setting contains invalid patterns [#384](https://github.com/softprops/action-gh-release/pull/384) via [@rpdelaney](https://github.com/rpdelaney)
 | 
					 | 
				
			||||||
- Add support for proxy env variables (don't use node-fetch) [#386](https://github.com/softprops/action-gh-release/pull/386/) via [@timor-raiman](https://github.com/timor-raiman)
 | 
					 | 
				
			||||||
- Suppress confusing warning when input_files is empty [#389](https://github.com/softprops/action-gh-release/pull/389) via [@Drowze](https://github.com/Drowze)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 2.0.0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- `2.0.0`!? this release corrects a disjunction between git tag versions used in the marketplace and versions list this file. Previous versions should have really been 1.\*. Going forward this should be better aligned.
 | 
					 | 
				
			||||||
- Upgrade action.yml declaration to node20 to address deprecations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 0.1.15
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Upgrade to action.yml declaration to node16 to address deprecations
 | 
					 | 
				
			||||||
- Upgrade dependencies
 | 
					 | 
				
			||||||
- Add `asset` output as a JSON array containing information about the uploaded assets
 | 
					- Add `asset` output as a JSON array containing information about the uploaded assets
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.1.14
 | 
					## 0.1.14
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
				
			|||||||
Copyright (c) 2019-current Doug Tangren
 | 
					Copyright (c) 2019 Doug Tangren
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Permission is hereby granted, free of charge, to any person obtaining
 | 
					Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
a copy of this software and associated documentation files (the
 | 
					a copy of this software and associated documentation files (the
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										55
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								README.md
									
									
									
									
									
								
							@@ -41,9 +41,9 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Release
 | 
					      - name: Release
 | 
				
			||||||
        uses: softprops/action-gh-release@v2
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
        if: startsWith(github.ref, 'refs/tags/')
 | 
					        if: startsWith(github.ref, 'refs/tags/')
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,9 +62,9 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Release
 | 
					      - name: Release
 | 
				
			||||||
        uses: softprops/action-gh-release@v2
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### ⬆️ Uploading release assets
 | 
					### ⬆️ Uploading release assets
 | 
				
			||||||
@@ -75,7 +75,6 @@ GitHub release and all are optional.
 | 
				
			|||||||
A common case for GitHub releases is to upload your binary after its been validated and packaged.
 | 
					A common case for GitHub releases is to upload your binary after its been validated and packaged.
 | 
				
			||||||
Use the `with.files` input to declare a newline-delimited list of glob expressions matching the files
 | 
					Use the `with.files` input to declare a newline-delimited list of glob expressions matching the files
 | 
				
			||||||
you wish to upload to GitHub releases. If you'd like you can just list the files by name directly.
 | 
					you wish to upload to GitHub releases. If you'd like you can just list the files by name directly.
 | 
				
			||||||
If a tag already has a GitHub release, the existing release will be updated with the release assets.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Below is an example of uploading a single asset named `Release.txt`
 | 
					Below is an example of uploading a single asset named `Release.txt`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,13 +88,13 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Build
 | 
					      - name: Build
 | 
				
			||||||
        run: echo ${{ github.sha }} > Release.txt
 | 
					        run: echo ${{ github.sha }} > Release.txt
 | 
				
			||||||
      - name: Test
 | 
					      - name: Test
 | 
				
			||||||
        run: cat Release.txt
 | 
					        run: cat Release.txt
 | 
				
			||||||
      - name: Release
 | 
					      - name: Release
 | 
				
			||||||
        uses: softprops/action-gh-release@v2
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
        if: startsWith(github.ref, 'refs/tags/')
 | 
					        if: startsWith(github.ref, 'refs/tags/')
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          files: Release.txt
 | 
					          files: Release.txt
 | 
				
			||||||
@@ -113,13 +112,13 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Build
 | 
					      - name: Build
 | 
				
			||||||
        run: echo ${{ github.sha }} > Release.txt
 | 
					        run: echo ${{ github.sha }} > Release.txt
 | 
				
			||||||
      - name: Test
 | 
					      - name: Test
 | 
				
			||||||
        run: cat Release.txt
 | 
					        run: cat Release.txt
 | 
				
			||||||
      - name: Release
 | 
					      - name: Release
 | 
				
			||||||
        uses: softprops/action-gh-release@v2
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
        if: startsWith(github.ref, 'refs/tags/')
 | 
					        if: startsWith(github.ref, 'refs/tags/')
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          files: |
 | 
					          files: |
 | 
				
			||||||
@@ -127,9 +126,7 @@ jobs:
 | 
				
			|||||||
            LICENSE
 | 
					            LICENSE
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That lets you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
 | 
					> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That let's you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
 | 
				
			||||||
 | 
					 | 
				
			||||||
> **⚠️ Note for Windows:** Paths must use `/` as a separator, not `\`, as `\` is used to escape characters with special meaning in the pattern; for example, instead of specifying `D:\Foo.txt`, you must specify `D:/Foo.txt`. If you're using PowerShell, you can do this with `$Path = $Path -replace '\\','/'`
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 📝 External release notes
 | 
					### 📝 External release notes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -147,18 +144,19 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
      - name: Generate Changelog
 | 
					      - name: Generate Changelog
 | 
				
			||||||
        run: echo "# Good things have arrived" > ${{ github.workspace }}-CHANGELOG.txt
 | 
					        run: echo "# Good things have arrived" > ${{ github.workspace }}-CHANGELOG.txt
 | 
				
			||||||
      - name: Release
 | 
					      - name: Release
 | 
				
			||||||
        uses: softprops/action-gh-release@v2
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
        if: startsWith(github.ref, 'refs/tags/')
 | 
					        if: startsWith(github.ref, 'refs/tags/')
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          body_path: ${{ github.workspace }}-CHANGELOG.txt
 | 
					          body_path: ${{ github.workspace }}-CHANGELOG.txt
 | 
				
			||||||
          repository: my_gh_org/my_gh_repo
 | 
					 | 
				
			||||||
          # note you'll typically need to create a personal access token
 | 
					          # note you'll typically need to create a personal access token
 | 
				
			||||||
          # with permissions to create releases in the other repo
 | 
					          # with permissions to create releases in the other repo
 | 
				
			||||||
          token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
 | 
					          token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					        env:
 | 
				
			||||||
 | 
					          GITHUB_REPOSITORY: my_gh_org/my_gh_repo
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 💅 Customizing
 | 
					### 💅 Customizing
 | 
				
			||||||
@@ -178,12 +176,10 @@ The following are optional as `step.with` keys
 | 
				
			|||||||
| `tag_name`                 | String  | Name of a tag. defaults to `github.ref`                                                                                                                                                                                                                                                                                                                                                                                                         |
 | 
					| `tag_name`                 | String  | Name of a tag. defaults to `github.ref`                                                                                                                                                                                                                                                                                                                                                                                                         |
 | 
				
			||||||
| `fail_on_unmatched_files`  | Boolean | Indicator of whether to fail if any of the `files` globs match nothing                                                                                                                                                                                                                                                                                                                                                                          |
 | 
					| `fail_on_unmatched_files`  | Boolean | Indicator of whether to fail if any of the `files` globs match nothing                                                                                                                                                                                                                                                                                                                                                                          |
 | 
				
			||||||
| `repository`               | String  | Name of a target repository in `<owner>/<repo>` format. Defaults to GITHUB_REPOSITORY env variable                                                                                                                                                                                                                                                                                                                                              |
 | 
					| `repository`               | String  | Name of a target repository in `<owner>/<repo>` format. Defaults to GITHUB_REPOSITORY env variable                                                                                                                                                                                                                                                                                                                                              |
 | 
				
			||||||
| `target_commitish`         | String  | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Defaults to repository default branch.                                                                                                                                                                                                                                                                                                      |
 | 
					| `target_commitish`         | String  | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA.                                                                                                                                                                                                                                                                                                                                             |
 | 
				
			||||||
| `token`                    | String  | Secret GitHub Personal Access Token. Defaults to `${{ github.token }}`                                                                                                                                                                                                                                                                                                                                                                          |
 | 
					| `token`                    | String  | Secret GitHub Personal Access Token. Defaults to `${{ github.token }}`                                                                                                                                                                                                                                                                                                                                                                          |
 | 
				
			||||||
| `discussion_category_name` | String  | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository)                                                     |
 | 
					| `discussion_category_name` | String  | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository)                                                     |
 | 
				
			||||||
| `generate_release_notes`   | Boolean | Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information |
 | 
					| `generate_release_notes`   | Boolean | Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information |
 | 
				
			||||||
| `append_body`              | Boolean | Append to existing body instead of overwriting it                                                                                                                                                                                                                                                                                                                                                                                               |
 | 
					 | 
				
			||||||
| `make_latest`              | String  | Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api defaults if not provided                                                                                                                                                                                                                            |
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
💡 When providing a `body` and `body_path` at the same time, `body_path` will be
 | 
					💡 When providing a `body` and `body_path` at the same time, `body_path` will be
 | 
				
			||||||
attempted first, then falling back on `body` if the path can not be read from.
 | 
					attempted first, then falling back on `body` if the path can not be read from.
 | 
				
			||||||
@@ -196,12 +192,12 @@ release will retain its original info.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
The following outputs can be accessed via `${{ steps.<step-id>.outputs }}` from this action
 | 
					The following outputs can be accessed via `${{ steps.<step-id>.outputs }}` from this action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name         | Type   | Description                                                                                                                                                                               |
 | 
					| Name         | Type   | Description                             |
 | 
				
			||||||
| ------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | 
					| ------------ | ------ | --------------------------------------- |
 | 
				
			||||||
| `url`        | String | Github.com URL for the release                                                                                                                                                            |
 | 
					| `url`        | String | Github.com URL for the release          |
 | 
				
			||||||
| `id`         | String | Release ID                                                                                                                                                                                |
 | 
					| `id`         | String | Release ID                              |
 | 
				
			||||||
| `upload_url` | String | URL for uploading assets to the release                                                                                                                                                   |
 | 
					| `upload_url` | String | URL for uploading assets to the release |
 | 
				
			||||||
| `assets`     | String | JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/releases/assets#get-a-release-asset) (minus the `uploader` field) |
 | 
					| `assets`     | String | 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) |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
As an example, you can use `${{ fromJSON(steps.<step-id>.outputs.assets)[0].browser_download_url }}` to get the download URL of the first asset.
 | 
					As an example, you can use `${{ fromJSON(steps.<step-id>.outputs.assets)[0].browser_download_url }}` to get the download URL of the first asset.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -225,17 +221,6 @@ permissions:
 | 
				
			|||||||
  contents: write
 | 
					  contents: write
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When used with `discussion_category_name`, additional permission is needed:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```yaml
 | 
					 | 
				
			||||||
permissions:
 | 
					 | 
				
			||||||
  contents: write
 | 
					 | 
				
			||||||
  discussions: write
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[GitHub token permissions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) can be set for an individual job, workflow, or for Actions as a whole.
 | 
					[GitHub token permissions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) can be set for an individual job, workflow, or for Actions as a whole.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note that if you intend to run workflows on the release event (`on: { release: { types: [published] } }`), you need to use
 | 
					 | 
				
			||||||
a personal access token for this action, as the [default `secrets.GITHUB_TOKEN` does not trigger another workflow](https://github.com/actions/create-release/issues/71).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Doug Tangren (softprops) 2019
 | 
					Doug Tangren (softprops) 2019
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import {
 | 
				
			|||||||
  parseConfig,
 | 
					  parseConfig,
 | 
				
			||||||
  parseInputFiles,
 | 
					  parseInputFiles,
 | 
				
			||||||
  unmatchedPatterns,
 | 
					  unmatchedPatterns,
 | 
				
			||||||
  uploadUrl,
 | 
					  uploadUrl
 | 
				
			||||||
} from "../src/util";
 | 
					} from "../src/util";
 | 
				
			||||||
import * as assert from "assert";
 | 
					import * as assert from "assert";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,8 +51,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_tag_name: undefined,
 | 
					          input_tag_name: undefined,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -72,8 +71,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_tag_name: undefined,
 | 
					          input_tag_name: undefined,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -93,8 +91,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_tag_name: undefined,
 | 
					          input_tag_name: undefined,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -110,13 +107,12 @@ describe("util", () => {
 | 
				
			|||||||
          // so we cover that in a test case here to ensure undefined values are actually
 | 
					          // so we cover that in a test case here to ensure undefined values are actually
 | 
				
			||||||
          // resolved as undefined and not empty strings
 | 
					          // resolved as undefined and not empty strings
 | 
				
			||||||
          INPUT_TARGET_COMMITISH: "",
 | 
					          INPUT_TARGET_COMMITISH: "",
 | 
				
			||||||
          INPUT_DISCUSSION_CATEGORY_NAME: "",
 | 
					          INPUT_DISCUSSION_CATEGORY_NAME: ""
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "",
 | 
					          github_token: "",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: undefined,
 | 
					          input_draft: undefined,
 | 
				
			||||||
@@ -127,8 +123,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -136,13 +131,12 @@ describe("util", () => {
 | 
				
			|||||||
    it("parses basic config with commitish", () => {
 | 
					    it("parses basic config with commitish", () => {
 | 
				
			||||||
      assert.deepStrictEqual(
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
        parseConfig({
 | 
					        parseConfig({
 | 
				
			||||||
          INPUT_TARGET_COMMITISH: "affa18ef97bc9db20076945705aba8c516139abd",
 | 
					          INPUT_TARGET_COMMITISH: "affa18ef97bc9db20076945705aba8c516139abd"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "",
 | 
					          github_token: "",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: undefined,
 | 
					          input_draft: undefined,
 | 
				
			||||||
@@ -153,21 +147,19 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: "affa18ef97bc9db20076945705aba8c516139abd",
 | 
					          input_target_commitish: "affa18ef97bc9db20076945705aba8c516139abd",
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it("supports discussion category names", () => {
 | 
					    it("supports discussion category names", () => {
 | 
				
			||||||
      assert.deepStrictEqual(
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
        parseConfig({
 | 
					        parseConfig({
 | 
				
			||||||
          INPUT_DISCUSSION_CATEGORY_NAME: "releases",
 | 
					          INPUT_DISCUSSION_CATEGORY_NAME: "releases"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "",
 | 
					          github_token: "",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: undefined,
 | 
					          input_draft: undefined,
 | 
				
			||||||
@@ -178,8 +170,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: "releases",
 | 
					          input_discussion_category_name: "releases",
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -187,13 +178,12 @@ describe("util", () => {
 | 
				
			|||||||
    it("supports generating release notes", () => {
 | 
					    it("supports generating release notes", () => {
 | 
				
			||||||
      assert.deepStrictEqual(
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
        parseConfig({
 | 
					        parseConfig({
 | 
				
			||||||
          INPUT_GENERATE_RELEASE_NOTES: "true",
 | 
					          INPUT_GENERATE_RELEASE_NOTES: "true"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "",
 | 
					          github_token: "",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: undefined,
 | 
					          input_draft: undefined,
 | 
				
			||||||
@@ -204,8 +194,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: true,
 | 
					          input_generate_release_notes: true
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -216,13 +205,12 @@ describe("util", () => {
 | 
				
			|||||||
          INPUT_DRAFT: "false",
 | 
					          INPUT_DRAFT: "false",
 | 
				
			||||||
          INPUT_PRERELEASE: "true",
 | 
					          INPUT_PRERELEASE: "true",
 | 
				
			||||||
          GITHUB_TOKEN: "env-token",
 | 
					          GITHUB_TOKEN: "env-token",
 | 
				
			||||||
          INPUT_TOKEN: "input-token",
 | 
					          INPUT_TOKEN: "input-token"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "env-token",
 | 
					          github_token: "env-token",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: false,
 | 
					          input_draft: false,
 | 
				
			||||||
@@ -233,8 +221,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -243,13 +230,12 @@ describe("util", () => {
 | 
				
			|||||||
        parseConfig({
 | 
					        parseConfig({
 | 
				
			||||||
          INPUT_DRAFT: "false",
 | 
					          INPUT_DRAFT: "false",
 | 
				
			||||||
          INPUT_PRERELEASE: "true",
 | 
					          INPUT_PRERELEASE: "true",
 | 
				
			||||||
          INPUT_TOKEN: "input-token",
 | 
					          INPUT_TOKEN: "input-token"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "input-token",
 | 
					          github_token: "input-token",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: false,
 | 
					          input_draft: false,
 | 
				
			||||||
@@ -260,8 +246,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -269,13 +254,12 @@ describe("util", () => {
 | 
				
			|||||||
      assert.deepStrictEqual(
 | 
					      assert.deepStrictEqual(
 | 
				
			||||||
        parseConfig({
 | 
					        parseConfig({
 | 
				
			||||||
          INPUT_DRAFT: "false",
 | 
					          INPUT_DRAFT: "false",
 | 
				
			||||||
          INPUT_PRERELEASE: "true",
 | 
					          INPUT_PRERELEASE: "true"
 | 
				
			||||||
        }),
 | 
					        }),
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          github_ref: "",
 | 
					          github_ref: "",
 | 
				
			||||||
          github_repository: "",
 | 
					          github_repository: "",
 | 
				
			||||||
          github_token: "",
 | 
					          github_token: "",
 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					          input_body: undefined,
 | 
				
			||||||
          input_body_path: undefined,
 | 
					          input_body_path: undefined,
 | 
				
			||||||
          input_draft: false,
 | 
					          input_draft: false,
 | 
				
			||||||
@@ -286,58 +270,7 @@ describe("util", () => {
 | 
				
			|||||||
          input_fail_on_unmatched_files: false,
 | 
					          input_fail_on_unmatched_files: false,
 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					          input_target_commitish: undefined,
 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					          input_discussion_category_name: undefined,
 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					          input_generate_release_notes: false
 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    it("parses basic config where make_latest is passed", () => {
 | 
					 | 
				
			||||||
      assert.deepStrictEqual(
 | 
					 | 
				
			||||||
        parseConfig({
 | 
					 | 
				
			||||||
          INPUT_MAKE_LATEST: "false",
 | 
					 | 
				
			||||||
        }),
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          github_ref: "",
 | 
					 | 
				
			||||||
          github_repository: "",
 | 
					 | 
				
			||||||
          github_token: "",
 | 
					 | 
				
			||||||
          input_append_body: false,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					 | 
				
			||||||
          input_body_path: undefined,
 | 
					 | 
				
			||||||
          input_draft: undefined,
 | 
					 | 
				
			||||||
          input_prerelease: undefined,
 | 
					 | 
				
			||||||
          input_files: [],
 | 
					 | 
				
			||||||
          input_name: undefined,
 | 
					 | 
				
			||||||
          input_tag_name: undefined,
 | 
					 | 
				
			||||||
          input_fail_on_unmatched_files: false,
 | 
					 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					 | 
				
			||||||
          input_make_latest: "false",
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    it("parses basic config with append_body", () => {
 | 
					 | 
				
			||||||
      assert.deepStrictEqual(
 | 
					 | 
				
			||||||
        parseConfig({
 | 
					 | 
				
			||||||
          INPUT_APPEND_BODY: "true",
 | 
					 | 
				
			||||||
        }),
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          github_ref: "",
 | 
					 | 
				
			||||||
          github_repository: "",
 | 
					 | 
				
			||||||
          github_token: "",
 | 
					 | 
				
			||||||
          input_append_body: true,
 | 
					 | 
				
			||||||
          input_body: undefined,
 | 
					 | 
				
			||||||
          input_body_path: undefined,
 | 
					 | 
				
			||||||
          input_draft: undefined,
 | 
					 | 
				
			||||||
          input_prerelease: undefined,
 | 
					 | 
				
			||||||
          input_files: [],
 | 
					 | 
				
			||||||
          input_name: undefined,
 | 
					 | 
				
			||||||
          input_tag_name: undefined,
 | 
					 | 
				
			||||||
          input_fail_on_unmatched_files: false,
 | 
					 | 
				
			||||||
          input_target_commitish: undefined,
 | 
					 | 
				
			||||||
          input_discussion_category_name: undefined,
 | 
					 | 
				
			||||||
          input_generate_release_notes: false,
 | 
					 | 
				
			||||||
          input_make_latest: undefined,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								action.yml
									
									
									
									
									
								
							@@ -43,14 +43,8 @@ inputs:
 | 
				
			|||||||
  generate_release_notes:
 | 
					  generate_release_notes:
 | 
				
			||||||
    description: "Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes."
 | 
					    description: "Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes."
 | 
				
			||||||
    required: false
 | 
					    required: false
 | 
				
			||||||
  append_body:
 | 
					 | 
				
			||||||
    description: "Append to existing body instead of overwriting it. Default is false."
 | 
					 | 
				
			||||||
    required: false
 | 
					 | 
				
			||||||
  make_latest:
 | 
					 | 
				
			||||||
    description: "Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api default if not provided"
 | 
					 | 
				
			||||||
    required: false
 | 
					 | 
				
			||||||
env:
 | 
					env:
 | 
				
			||||||
  GITHUB_TOKEN: "As provided by Github Actions"
 | 
					  "GITHUB_TOKEN": "As provided by Github Actions"
 | 
				
			||||||
outputs:
 | 
					outputs:
 | 
				
			||||||
  url:
 | 
					  url:
 | 
				
			||||||
    description: "URL to the Release HTML Page"
 | 
					    description: "URL to the Release HTML Page"
 | 
				
			||||||
@@ -61,7 +55,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: "node20"
 | 
					  using: "node12"
 | 
				
			||||||
  main: "dist/index.js"
 | 
					  main: "dist/index.js"
 | 
				
			||||||
branding:
 | 
					branding:
 | 
				
			||||||
  color: "green"
 | 
					  color: "green"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1139
									
								
								dist/contextify.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1139
									
								
								dist/contextify.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										83
									
								
								dist/fixasync.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								dist/fixasync.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// eslint-disable-next-line no-invalid-this, no-shadow
 | 
				
			||||||
 | 
					const {GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, global, internal, host, hook} = this;
 | 
				
			||||||
 | 
					const {Contextify, Decontextify} = internal;
 | 
				
			||||||
 | 
					// eslint-disable-next-line no-shadow
 | 
				
			||||||
 | 
					const {Function, eval: eval_, Promise, Object, Reflect} = global;
 | 
				
			||||||
 | 
					const {getOwnPropertyDescriptor, defineProperty, assign} = Object;
 | 
				
			||||||
 | 
					const {apply: rApply, construct: rConstruct} = Reflect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const FunctionHandler = {
 | 
				
			||||||
 | 
						__proto__: null,
 | 
				
			||||||
 | 
						apply(target, thiz, args) {
 | 
				
			||||||
 | 
							const type = this.type;
 | 
				
			||||||
 | 
							args = Decontextify.arguments(args);
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								args = Contextify.value(hook(type, args));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return rApply(target, thiz, args);
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						construct(target, args, newTarget) {
 | 
				
			||||||
 | 
							const type = this.type;
 | 
				
			||||||
 | 
							args = Decontextify.arguments(args);
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								args = Contextify.value(hook(type, args));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return rConstruct(target, args, newTarget);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function makeCheckFunction(type) {
 | 
				
			||||||
 | 
						return assign({
 | 
				
			||||||
 | 
							__proto__: null,
 | 
				
			||||||
 | 
							type
 | 
				
			||||||
 | 
						}, FunctionHandler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function override(obj, prop, value) {
 | 
				
			||||||
 | 
						const desc = getOwnPropertyDescriptor(obj, prop);
 | 
				
			||||||
 | 
						desc.value = value;
 | 
				
			||||||
 | 
						defineProperty(obj, prop, desc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const proxiedFunction = new host.Proxy(Function, makeCheckFunction('function'));
 | 
				
			||||||
 | 
					override(Function.prototype, 'constructor', proxiedFunction);
 | 
				
			||||||
 | 
					if (GeneratorFunction) {
 | 
				
			||||||
 | 
						Object.setPrototypeOf(GeneratorFunction, proxiedFunction);
 | 
				
			||||||
 | 
						override(GeneratorFunction.prototype, 'constructor', new host.Proxy(GeneratorFunction, makeCheckFunction('generator_function')));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					if (AsyncFunction) {
 | 
				
			||||||
 | 
						Object.setPrototypeOf(AsyncFunction, proxiedFunction);
 | 
				
			||||||
 | 
						override(AsyncFunction.prototype, 'constructor', new host.Proxy(AsyncFunction, makeCheckFunction('async_function')));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					if (AsyncGeneratorFunction) {
 | 
				
			||||||
 | 
						Object.setPrototypeOf(AsyncGeneratorFunction, proxiedFunction);
 | 
				
			||||||
 | 
						override(AsyncGeneratorFunction.prototype, 'constructor', new host.Proxy(AsyncGeneratorFunction, makeCheckFunction('async_generator_function')));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					global.Function = proxiedFunction;
 | 
				
			||||||
 | 
					global.eval = new host.Proxy(eval_, makeCheckFunction('eval'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (Promise) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Promise.prototype.then = new host.Proxy(Promise.prototype.then, makeCheckFunction('promise_then'));
 | 
				
			||||||
 | 
						// This seems not to work, and will produce
 | 
				
			||||||
 | 
						// UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
 | 
				
			||||||
 | 
						// This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
 | 
				
			||||||
 | 
						// Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (Promise.prototype.finally) {
 | 
				
			||||||
 | 
							Promise.prototype.finally = new host.Proxy(Promise.prototype.finally, makeCheckFunction('promise_finally'));
 | 
				
			||||||
 | 
							// Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (Promise.prototype.catch) {
 | 
				
			||||||
 | 
							Promise.prototype.catch = new host.Proxy(Promise.prototype.catch, makeCheckFunction('promise_catch'));
 | 
				
			||||||
 | 
							// Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										134
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										134
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										682
									
								
								dist/sandbox.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										682
									
								
								dist/sandbox.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,682 @@
 | 
				
			|||||||
 | 
					/* eslint-disable no-shadow, no-invalid-this */
 | 
				
			||||||
 | 
					/* global vm, host, Contextify, Decontextify, VMError, options */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const {Script} = host.require('vm');
 | 
				
			||||||
 | 
					const fs = host.require('fs');
 | 
				
			||||||
 | 
					const pa = host.require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const BUILTIN_MODULES = host.process.binding('natives');
 | 
				
			||||||
 | 
					const parseJSON = JSON.parse;
 | 
				
			||||||
 | 
					const importModuleDynamically = () => {
 | 
				
			||||||
 | 
						// We can't throw an error object here because since vm.Script doesn't store a context, we can't properly contextify that error object.
 | 
				
			||||||
 | 
						// eslint-disable-next-line no-throw-literal
 | 
				
			||||||
 | 
						throw 'Dynamic imports are not allowed.';
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {Object} host Hosts's internal objects.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return ((vm, host) => {
 | 
				
			||||||
 | 
						'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const global = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const TIMERS = new host.WeakMap(); // Contains map of timers created inside sandbox
 | 
				
			||||||
 | 
						const BUILTINS = {__proto__: null};
 | 
				
			||||||
 | 
						const CACHE = {__proto__: null};
 | 
				
			||||||
 | 
						const EXTENSIONS = {
 | 
				
			||||||
 | 
							__proto__: null,
 | 
				
			||||||
 | 
							['.json'](module, filename) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									const code = fs.readFileSync(filename, 'utf8');
 | 
				
			||||||
 | 
									module.exports = parseJSON(code);
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							['.node'](module, filename) {
 | 
				
			||||||
 | 
								if (vm.options.require.context === 'sandbox') throw new VMError('Native modules can be required only with context set to \'host\'.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									module.exports = Contextify.readonly(host.require(filename));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
 | 
				
			||||||
 | 
							const ext = vm.options.sourceExtensions[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							EXTENSIONS['.' + ext] = (module, filename, dirname) => {
 | 
				
			||||||
 | 
								if (vm.options.require.context !== 'sandbox') {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										module.exports = Contextify.readonly(host.require(filename));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									let script;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// Load module
 | 
				
			||||||
 | 
										let contents = fs.readFileSync(filename, 'utf8');
 | 
				
			||||||
 | 
										contents = vm._compiler(contents, filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										const code = host.STRICT_MODULE_PREFIX + contents + host.MODULE_SUFFIX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										const ccode = vm._hook('run', [code]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Precompile script
 | 
				
			||||||
 | 
										script = new Script(ccode, {
 | 
				
			||||||
 | 
											__proto__: null,
 | 
				
			||||||
 | 
											filename: filename || 'vm.js',
 | 
				
			||||||
 | 
											displayErrors: false,
 | 
				
			||||||
 | 
											importModuleDynamically
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									} catch (ex) {
 | 
				
			||||||
 | 
										throw Contextify.value(ex);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									const closure = script.runInContext(global, {
 | 
				
			||||||
 | 
										__proto__: null,
 | 
				
			||||||
 | 
										filename: filename || 'vm.js',
 | 
				
			||||||
 | 
										displayErrors: false,
 | 
				
			||||||
 | 
										importModuleDynamically
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// run the script
 | 
				
			||||||
 | 
									closure(module.exports, module.require, module, filename, dirname);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const _parseExternalOptions = (options) => {
 | 
				
			||||||
 | 
							if (host.Array.isArray(options)) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									__proto__: null,
 | 
				
			||||||
 | 
									external: options,
 | 
				
			||||||
 | 
									transitive: false
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								__proto__: null,
 | 
				
			||||||
 | 
								external: options.modules,
 | 
				
			||||||
 | 
								transitive: options.transitive
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Resolve filename.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const _resolveFilename = (path) => {
 | 
				
			||||||
 | 
							if (!path) return null;
 | 
				
			||||||
 | 
							let hasPackageJson;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								path = pa.resolve(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const exists = fs.existsSync(path);
 | 
				
			||||||
 | 
								const isdir = exists ? fs.statSync(path).isDirectory() : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// direct file match
 | 
				
			||||||
 | 
								if (exists && !isdir) return path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// load as file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
 | 
				
			||||||
 | 
									const ext = vm.options.sourceExtensions[i];
 | 
				
			||||||
 | 
									if (fs.existsSync(`${path}.${ext}`)) return `${path}.${ext}`;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (fs.existsSync(`${path}.json`)) return `${path}.json`;
 | 
				
			||||||
 | 
								if (fs.existsSync(`${path}.node`)) return `${path}.node`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// load as module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								hasPackageJson = fs.existsSync(`${path}/package.json`);
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (hasPackageJson) {
 | 
				
			||||||
 | 
								let pkg;
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									pkg = fs.readFileSync(`${path}/package.json`, 'utf8');
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									pkg = parseJSON(pkg);
 | 
				
			||||||
 | 
								} catch (ex) {
 | 
				
			||||||
 | 
									throw new VMError(`Module '${path}' has invalid package.json`, 'EMODULEINVALID');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let main;
 | 
				
			||||||
 | 
								if (pkg && pkg.main) {
 | 
				
			||||||
 | 
									main = _resolveFilename(`${path}/${pkg.main}`);
 | 
				
			||||||
 | 
									if (!main) main = _resolveFilename(`${path}/index`);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									main = _resolveFilename(`${path}/index`);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return main;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// load as directory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								for (let i = 0; i < vm.options.sourceExtensions.length; i++) {
 | 
				
			||||||
 | 
									const ext = vm.options.sourceExtensions[i];
 | 
				
			||||||
 | 
									if (fs.existsSync(`${path}/index.${ext}`)) return `${path}/index.${ext}`;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (fs.existsSync(`${path}/index.json`)) return `${path}/index.json`;
 | 
				
			||||||
 | 
								if (fs.existsSync(`${path}/index.node`)) return `${path}/index.node`;
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Builtin require.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const _requireBuiltin = (moduleName) => {
 | 
				
			||||||
 | 
							if (moduleName === 'buffer') return ({Buffer});
 | 
				
			||||||
 | 
							if (BUILTINS[moduleName]) return BUILTINS[moduleName].exports; // Only compiled builtins are stored here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (moduleName === 'util') {
 | 
				
			||||||
 | 
								return Contextify.readonly(host.require(moduleName), {
 | 
				
			||||||
 | 
									// Allows VM context to use util.inherits
 | 
				
			||||||
 | 
									__proto__: null,
 | 
				
			||||||
 | 
									inherits: (ctor, superCtor) => {
 | 
				
			||||||
 | 
										ctor.super_ = superCtor;
 | 
				
			||||||
 | 
										Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (moduleName === 'events' || moduleName === 'internal/errors') {
 | 
				
			||||||
 | 
								let script;
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									script = new Script(`(function (exports, require, module, process, internalBinding) {
 | 
				
			||||||
 | 
											'use strict';
 | 
				
			||||||
 | 
											const primordials = global;
 | 
				
			||||||
 | 
											${BUILTIN_MODULES[moduleName]}
 | 
				
			||||||
 | 
											\n
 | 
				
			||||||
 | 
										});`, {
 | 
				
			||||||
 | 
										filename: `${moduleName}.vm.js`
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// setup module scope
 | 
				
			||||||
 | 
								const module = BUILTINS[moduleName] = {
 | 
				
			||||||
 | 
									exports: {},
 | 
				
			||||||
 | 
									require: _requireBuiltin
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// run script
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									// FIXME binding should be contextified
 | 
				
			||||||
 | 
									script.runInContext(global)(module.exports, module.require, module, host.process, host.process.binding);
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									// e could be from inside or outside of sandbox
 | 
				
			||||||
 | 
									throw new VMError(`Error loading '${moduleName}'`);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return module.exports;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return Contextify.readonly(host.require(moduleName));
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Prepare require.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const _prepareRequire = (currentDirname, parentAllowsTransitive = false) => {
 | 
				
			||||||
 | 
							const _require = moduleName => {
 | 
				
			||||||
 | 
								let requireObj;
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									const optionsObj = vm.options;
 | 
				
			||||||
 | 
									if (optionsObj.nesting && moduleName === 'vm2') return {VM: Contextify.readonly(host.VM), NodeVM: Contextify.readonly(host.NodeVM)};
 | 
				
			||||||
 | 
									requireObj = optionsObj.require;
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!requireObj) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
 | 
				
			||||||
 | 
								if (moduleName == null) throw new VMError("Module '' not found.", 'ENOTFOUND');
 | 
				
			||||||
 | 
								if (typeof moduleName !== 'string') throw new VMError(`Invalid module name '${moduleName}'`, 'EINVALIDNAME');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let filename;
 | 
				
			||||||
 | 
								let allowRequireTransitive = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Mock?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									const {mock} = requireObj;
 | 
				
			||||||
 | 
									if (mock) {
 | 
				
			||||||
 | 
										const mockModule = mock[moduleName];
 | 
				
			||||||
 | 
										if (mockModule) {
 | 
				
			||||||
 | 
											return Contextify.readonly(mockModule);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Builtin?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (BUILTIN_MODULES[moduleName]) {
 | 
				
			||||||
 | 
									let allowed;
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										const builtinObj = requireObj.builtin;
 | 
				
			||||||
 | 
										if (host.Array.isArray(builtinObj)) {
 | 
				
			||||||
 | 
											if (builtinObj.indexOf('*') >= 0) {
 | 
				
			||||||
 | 
												allowed = builtinObj.indexOf(`-${moduleName}`) === -1;
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												allowed = builtinObj.indexOf(moduleName) >= 0;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										} else if (builtinObj) {
 | 
				
			||||||
 | 
											allowed = builtinObj[moduleName];
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											allowed = false;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (!allowed) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return _requireBuiltin(moduleName);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// External?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let externalObj;
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									externalObj = requireObj.external;
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!externalObj) throw new VMError(`Access denied to require '${moduleName}'`, 'EDENIED');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (/^(\.|\.\/|\.\.\/)/.exec(moduleName)) {
 | 
				
			||||||
 | 
									// Module is relative file, e.g. ./script.js or ../script.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									filename = _resolveFilename(`${currentDirname}/${moduleName}`);
 | 
				
			||||||
 | 
								} else if (/^(\/|\\|[a-zA-Z]:\\)/.exec(moduleName)) {
 | 
				
			||||||
 | 
									// Module is absolute file, e.g. /script.js or //server/script.js or C:\script.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									filename = _resolveFilename(moduleName);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// Check node_modules in path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!currentDirname) throw new VMError('You must specify script path to load relative modules.', 'ENOPATH');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (typeof externalObj === 'object') {
 | 
				
			||||||
 | 
										let isWhitelisted;
 | 
				
			||||||
 | 
										try {
 | 
				
			||||||
 | 
											const { external, transitive } = _parseExternalOptions(externalObj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											isWhitelisted = external.some(ext => host.helpers.match(ext, moduleName)) || (transitive && parentAllowsTransitive);
 | 
				
			||||||
 | 
										} catch (e) {
 | 
				
			||||||
 | 
											throw Contextify.value(e);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if (!isWhitelisted) {
 | 
				
			||||||
 | 
											throw new VMError(`The module '${moduleName}' is not whitelisted in VM.`, 'EDENIED');
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										allowRequireTransitive = true;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// FIXME the paths array has side effects
 | 
				
			||||||
 | 
									const paths = currentDirname.split(pa.sep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									while (paths.length) {
 | 
				
			||||||
 | 
										const path = paths.join(pa.sep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// console.log moduleName, "#{path}#{pa.sep}node_modules#{pa.sep}#{moduleName}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										filename = _resolveFilename(`${path}${pa.sep}node_modules${pa.sep}${moduleName}`);
 | 
				
			||||||
 | 
										if (filename) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										paths.pop();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!filename) {
 | 
				
			||||||
 | 
									let resolveFunc;
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										resolveFunc = requireObj.resolve;
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (resolveFunc) {
 | 
				
			||||||
 | 
										let resolved;
 | 
				
			||||||
 | 
										try {
 | 
				
			||||||
 | 
											resolved = requireObj.resolve(moduleName, currentDirname);
 | 
				
			||||||
 | 
										} catch (e) {
 | 
				
			||||||
 | 
											throw Contextify.value(e);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										filename = _resolveFilename(resolved);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (!filename) throw new VMError(`Cannot find module '${moduleName}'`, 'ENOTFOUND');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// return cache whenever possible
 | 
				
			||||||
 | 
								if (CACHE[filename]) return CACHE[filename].exports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const dirname = pa.dirname(filename);
 | 
				
			||||||
 | 
								const extname = pa.extname(filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								let allowedModule = true;
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									const rootObj = requireObj.root;
 | 
				
			||||||
 | 
									if (rootObj) {
 | 
				
			||||||
 | 
										const rootPaths = host.Array.isArray(rootObj) ? rootObj : host.Array.of(rootObj);
 | 
				
			||||||
 | 
										allowedModule = rootPaths.some(path => host.String.prototype.startsWith.call(dirname, pa.resolve(path)));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!allowedModule) {
 | 
				
			||||||
 | 
									throw new VMError(`Module '${moduleName}' is not allowed to be required. The path is outside the border!`, 'EDENIED');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const module = CACHE[filename] = {
 | 
				
			||||||
 | 
									filename,
 | 
				
			||||||
 | 
									exports: {},
 | 
				
			||||||
 | 
									require: _prepareRequire(dirname, allowRequireTransitive)
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// lookup extensions
 | 
				
			||||||
 | 
								if (EXTENSIONS[extname]) {
 | 
				
			||||||
 | 
									EXTENSIONS[extname](module, filename, dirname);
 | 
				
			||||||
 | 
									return module.exports;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								throw new VMError(`Failed to load '${moduleName}': Unknown type.`, 'ELOADFAIL');
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return _require;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Prepare sandbox.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This is a function and not an arrow function, since the original is also a function
 | 
				
			||||||
 | 
						global.setTimeout = function setTimeout(callback, delay, ...args) {
 | 
				
			||||||
 | 
							if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
 | 
				
			||||||
 | 
							let tmr;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								tmr = host.setTimeout(Decontextify.value(() => {
 | 
				
			||||||
 | 
									// FIXME ...args has side effects
 | 
				
			||||||
 | 
									callback(...args);
 | 
				
			||||||
 | 
								}), Decontextify.value(delay));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							const local = Contextify.value(tmr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TIMERS.set(local, tmr);
 | 
				
			||||||
 | 
							return local;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global.setInterval = function setInterval(callback, interval, ...args) {
 | 
				
			||||||
 | 
							if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
 | 
				
			||||||
 | 
							let tmr;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								tmr = host.setInterval(Decontextify.value(() => {
 | 
				
			||||||
 | 
									// FIXME ...args has side effects
 | 
				
			||||||
 | 
									callback(...args);
 | 
				
			||||||
 | 
								}), Decontextify.value(interval));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const local = Contextify.value(tmr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TIMERS.set(local, tmr);
 | 
				
			||||||
 | 
							return local;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global.setImmediate = function setImmediate(callback, ...args) {
 | 
				
			||||||
 | 
							if (typeof callback !== 'function') throw new TypeError('"callback" argument must be a function');
 | 
				
			||||||
 | 
							let tmr;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								tmr = host.setImmediate(Decontextify.value(() => {
 | 
				
			||||||
 | 
									// FIXME ...args has side effects
 | 
				
			||||||
 | 
									callback(...args);
 | 
				
			||||||
 | 
								}));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const local = Contextify.value(tmr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TIMERS.set(local, tmr);
 | 
				
			||||||
 | 
							return local;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global.clearTimeout = function clearTimeout(local) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								host.clearTimeout(TIMERS.get(local));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global.clearInterval = function clearInterval(local) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								host.clearInterval(TIMERS.get(local));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						global.clearImmediate = function clearImmediate(local) {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								host.clearImmediate(TIMERS.get(local));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function addListener(name, handler) {
 | 
				
			||||||
 | 
							if (name !== 'beforeExit' && name !== 'exit') {
 | 
				
			||||||
 | 
								throw new Error(`Access denied to listen for '${name}' event.`);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								host.process.on(name, Decontextify.value(handler));
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								throw Contextify.value(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const {argv: optionArgv, env: optionsEnv} = options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FIXME wrong class structure
 | 
				
			||||||
 | 
						global.process = {
 | 
				
			||||||
 | 
							argv: optionArgv !== undefined ? Contextify.value(optionArgv) : [],
 | 
				
			||||||
 | 
							title: host.process.title,
 | 
				
			||||||
 | 
							version: host.process.version,
 | 
				
			||||||
 | 
							versions: Contextify.readonly(host.process.versions),
 | 
				
			||||||
 | 
							arch: host.process.arch,
 | 
				
			||||||
 | 
							platform: host.process.platform,
 | 
				
			||||||
 | 
							env: optionsEnv !== undefined ? Contextify.value(optionsEnv) : {},
 | 
				
			||||||
 | 
							pid: host.process.pid,
 | 
				
			||||||
 | 
							features: Contextify.readonly(host.process.features),
 | 
				
			||||||
 | 
							nextTick: function nextTick(callback, ...args) {
 | 
				
			||||||
 | 
								if (typeof callback !== 'function') {
 | 
				
			||||||
 | 
									throw new Error('Callback must be a function.');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									host.process.nextTick(Decontextify.value(() => {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										callback(...args);
 | 
				
			||||||
 | 
									}));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							hrtime: function hrtime(time) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									return Contextify.value(host.process.hrtime(Decontextify.value(time)));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							cwd: function cwd() {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									return Contextify.value(host.process.cwd());
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							addListener,
 | 
				
			||||||
 | 
							on: addListener,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							once: function once(name, handler) {
 | 
				
			||||||
 | 
								if (name !== 'beforeExit' && name !== 'exit') {
 | 
				
			||||||
 | 
									throw new Error(`Access denied to listen for '${name}' event.`);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									host.process.once(name, Decontextify.value(handler));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							listeners: function listeners(name) {
 | 
				
			||||||
 | 
								if (name !== 'beforeExit' && name !== 'exit') {
 | 
				
			||||||
 | 
									// Maybe add ({__proto__:null})[name] to throw when name fails in https://tc39.es/ecma262/#sec-topropertykey.
 | 
				
			||||||
 | 
									return [];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Filter out listeners, which were not created in this sandbox
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									return Contextify.value(host.process.listeners(name).filter(listener => Contextify.isVMProxy(listener)));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							removeListener: function removeListener(name, handler) {
 | 
				
			||||||
 | 
								if (name !== 'beforeExit' && name !== 'exit') {
 | 
				
			||||||
 | 
									return this;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									host.process.removeListener(name, Decontextify.value(handler));
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							umask: function umask() {
 | 
				
			||||||
 | 
								if (arguments.length) {
 | 
				
			||||||
 | 
									throw new Error('Access denied to set umask.');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									return Contextify.value(host.process.umask());
 | 
				
			||||||
 | 
								} catch (e) {
 | 
				
			||||||
 | 
									throw Contextify.value(e);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vm.options.console === 'inherit') {
 | 
				
			||||||
 | 
							global.console = Contextify.readonly(host.console);
 | 
				
			||||||
 | 
						} else if (vm.options.console === 'redirect') {
 | 
				
			||||||
 | 
							global.console = {
 | 
				
			||||||
 | 
								debug(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.debug', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								log(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.log', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								info(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.info', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								warn(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.warn', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								error(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.error', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								dir(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										vm.emit('console.dir', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								time() {},
 | 
				
			||||||
 | 
								timeEnd() {},
 | 
				
			||||||
 | 
								trace(...args) {
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										// FIXME ...args has side effects
 | 
				
			||||||
 | 
										vm.emit('console.trace', ...Decontextify.arguments(args));
 | 
				
			||||||
 | 
									} catch (e) {
 | 
				
			||||||
 | 
										throw Contextify.value(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						Return contextified require.
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return _prepareRequire;
 | 
				
			||||||
 | 
					})(vm, host);
 | 
				
			||||||
							
								
								
									
										8989
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8989
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										41
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								package.json
									
									
									
									
									
								
							@@ -1,16 +1,14 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "action-gh-release",
 | 
					  "name": "action-gh-release",
 | 
				
			||||||
  "version": "2.0.6",
 | 
					  "version": "0.1.14",
 | 
				
			||||||
  "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",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "build": "ncc build src/main.ts --minify",
 | 
					    "build": "ncc build src/main.ts --minify",
 | 
				
			||||||
    "build-debug": "ncc build src/main.ts --v8-cache --source-map",
 | 
					 | 
				
			||||||
    "test": "jest",
 | 
					    "test": "jest",
 | 
				
			||||||
    "fmt": "prettier --write \"src/**/*.ts\" \"__tests__/**/*.ts\"",
 | 
					    "fmt": "prettier --write \"src/**/*.ts\" \"__tests__/**/*.ts\"",
 | 
				
			||||||
    "fmtcheck": "prettier --check \"src/**/*.ts\" \"__tests__/**/*.ts\"",
 | 
					    "fmtcheck": "prettier --check \"src/**/*.ts\" \"__tests__/**/*.ts\""
 | 
				
			||||||
    "updatetag": "git tag -d v2 && git push origin :v2 && git tag -a v2 -m '' && git push origin v2"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
@@ -20,25 +18,28 @@
 | 
				
			|||||||
    "actions"
 | 
					    "actions"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "author": "softprops",
 | 
					  "author": "softprops",
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@actions/core": "^1.10.0",
 | 
					    "@octokit/action": "^3.18.0",
 | 
				
			||||||
    "@actions/github": "^5.1.1",
 | 
					    "@actions/core": "^1.4.0",
 | 
				
			||||||
    "@octokit/plugin-retry": "^7.1.1",
 | 
					    "@octokit/plugin-retry": "^3.0.9",
 | 
				
			||||||
    "@octokit/plugin-throttling": "^9.3.0",
 | 
					    "@octokit/plugin-throttling": "^3.5.1",
 | 
				
			||||||
    "glob": "^10.4.2",
 | 
					    "glob": "^7.1.6",
 | 
				
			||||||
    "mime": "^3.0.0"
 | 
					    "mime": "^2.4.4",
 | 
				
			||||||
 | 
					    "node-fetch": "^2.6.1"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/glob": "^8.1.0",
 | 
					    "@types/glob": "^7.1.1",
 | 
				
			||||||
    "@types/jest": "^29.5.12",
 | 
					    "@types/jest": "^24.0.25",
 | 
				
			||||||
    "@types/mime": "^3.0.1",
 | 
					    "@types/mime": "^2.0.1",
 | 
				
			||||||
    "@types/node": "^20.14.9",
 | 
					    "@types/node": "^12.12.24",
 | 
				
			||||||
    "@vercel/ncc": "^0.38.1",
 | 
					    "@types/node-fetch": "^2.5.12",
 | 
				
			||||||
    "jest": "^29.3.1",
 | 
					    "@vercel/ncc": "^0.33.0",
 | 
				
			||||||
    "jest-circus": "^29.3.1",
 | 
					    "jest": "^24.9.0",
 | 
				
			||||||
    "prettier": "2.8.0",
 | 
					    "jest-circus": "^24.9.0",
 | 
				
			||||||
    "ts-jest": "^29.2.2",
 | 
					    "prettier": "1.19.1",
 | 
				
			||||||
    "typescript": "^5.5.3",
 | 
					    "ts-jest": "^24.2.0",
 | 
				
			||||||
 | 
					    "typescript": "^3.7.4",
 | 
				
			||||||
    "typescript-formatter": "^7.2.2"
 | 
					    "typescript-formatter": "^7.2.2"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								release.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								release.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					# actions requires a node_modules dir https://github.com/actions/toolkit/blob/master/docs/javascript-action.md#publish-a-releasesv1-action
 | 
				
			||||||
 | 
					# but its recommended not to check these in https://github.com/actions/toolkit/blob/master/docs/action-versioning.md#recommendations
 | 
				
			||||||
 | 
					# as such the following hack is how we dill with it
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ $# -ne 1 ]]; then
 | 
				
			||||||
 | 
						echo "please pass a release version. i.e. $0 v1"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					git checkout -b releases/$1 # If this branch already exists, omit the -b flag
 | 
				
			||||||
 | 
					rm -rf node_modules
 | 
				
			||||||
 | 
					sed -i '/node_modules/d' .gitignore # Bash command that removes node_modules from .gitignore
 | 
				
			||||||
 | 
					npm install --production
 | 
				
			||||||
 | 
					git add node_modules -f .gitignore
 | 
				
			||||||
 | 
					git commit -m node_modules
 | 
				
			||||||
 | 
					git push origin releases/$1
 | 
				
			||||||
							
								
								
									
										212
									
								
								src/github.ts
									
									
									
									
									
								
							
							
						
						
									
										212
									
								
								src/github.ts
									
									
									
									
									
								
							@@ -1,10 +1,11 @@
 | 
				
			|||||||
import { GitHub } from "@actions/github/lib/utils";
 | 
					import fetch from "node-fetch";
 | 
				
			||||||
 | 
					import { Octokit } from "@octokit/action";
 | 
				
			||||||
import { Config, isTag, releaseBody } from "./util";
 | 
					import { Config, isTag, releaseBody } from "./util";
 | 
				
			||||||
import { statSync, readFileSync } from "fs";
 | 
					import { statSync, readFileSync } from "fs";
 | 
				
			||||||
import { getType } from "mime";
 | 
					import { getType } from "mime";
 | 
				
			||||||
import { basename } from "path";
 | 
					import { basename } from "path";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GitHub = InstanceType<typeof GitHub>;
 | 
					type GitHub = InstanceType<typeof Octokit>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ReleaseAsset {
 | 
					export interface ReleaseAsset {
 | 
				
			||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
@@ -44,7 +45,6 @@ export interface Releaser {
 | 
				
			|||||||
    target_commitish: string | undefined;
 | 
					    target_commitish: string | undefined;
 | 
				
			||||||
    discussion_category_name: string | undefined;
 | 
					    discussion_category_name: string | undefined;
 | 
				
			||||||
    generate_release_notes: boolean | undefined;
 | 
					    generate_release_notes: boolean | undefined;
 | 
				
			||||||
    make_latest: string | undefined;
 | 
					 | 
				
			||||||
  }): Promise<{ data: Release }>;
 | 
					  }): Promise<{ data: Release }>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateRelease(params: {
 | 
					  updateRelease(params: {
 | 
				
			||||||
@@ -59,7 +59,6 @@ export interface Releaser {
 | 
				
			|||||||
    prerelease: boolean | undefined;
 | 
					    prerelease: boolean | undefined;
 | 
				
			||||||
    discussion_category_name: string | undefined;
 | 
					    discussion_category_name: string | undefined;
 | 
				
			||||||
    generate_release_notes: boolean | undefined;
 | 
					    generate_release_notes: boolean | undefined;
 | 
				
			||||||
    make_latest: string | undefined;
 | 
					 | 
				
			||||||
  }): Promise<{ data: Release }>;
 | 
					  }): Promise<{ data: Release }>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  allReleases(params: {
 | 
					  allReleases(params: {
 | 
				
			||||||
@@ -93,7 +92,6 @@ export class GitHubReleaser implements Releaser {
 | 
				
			|||||||
    target_commitish: string | undefined;
 | 
					    target_commitish: string | undefined;
 | 
				
			||||||
    discussion_category_name: string | undefined;
 | 
					    discussion_category_name: string | undefined;
 | 
				
			||||||
    generate_release_notes: boolean | undefined;
 | 
					    generate_release_notes: boolean | undefined;
 | 
				
			||||||
    make_latest: string | undefined;
 | 
					 | 
				
			||||||
  }): Promise<{ data: Release }> {
 | 
					  }): Promise<{ data: Release }> {
 | 
				
			||||||
    return this.github.rest.repos.createRelease(params);
 | 
					    return this.github.rest.repos.createRelease(params);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -110,7 +108,6 @@ export class GitHubReleaser implements Releaser {
 | 
				
			|||||||
    prerelease: boolean | undefined;
 | 
					    prerelease: boolean | undefined;
 | 
				
			||||||
    discussion_category_name: string | undefined;
 | 
					    discussion_category_name: string | undefined;
 | 
				
			||||||
    generate_release_notes: boolean | undefined;
 | 
					    generate_release_notes: boolean | undefined;
 | 
				
			||||||
    make_latest: string | undefined;
 | 
					 | 
				
			||||||
  }): Promise<{ data: Release }> {
 | 
					  }): Promise<{ data: Release }> {
 | 
				
			||||||
    return this.github.rest.repos.updateRelease(params);
 | 
					    return this.github.rest.repos.updateRelease(params);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -131,7 +128,7 @@ export const asset = (path: string): ReleaseAsset => {
 | 
				
			|||||||
    name: basename(path),
 | 
					    name: basename(path),
 | 
				
			||||||
    mime: mimeOrDefault(path),
 | 
					    mime: mimeOrDefault(path),
 | 
				
			||||||
    size: statSync(path).size,
 | 
					    size: statSync(path).size,
 | 
				
			||||||
    data: readFileSync(path),
 | 
					    data: readFileSync(path)
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -149,33 +146,29 @@ export const upload = async (
 | 
				
			|||||||
  const [owner, repo] = config.github_repository.split("/");
 | 
					  const [owner, repo] = config.github_repository.split("/");
 | 
				
			||||||
  const { name, size, mime, data: body } = asset(path);
 | 
					  const { name, size, mime, data: body } = asset(path);
 | 
				
			||||||
  const currentAsset = currentAssets.find(
 | 
					  const currentAsset = currentAssets.find(
 | 
				
			||||||
    // note: GitHub renames asset filenames that have special characters, non-alphanumeric characters, and leading or trailing periods. The "List release assets" endpoint lists the renamed filenames.
 | 
					    ({ name: currentName }) => currentName == name
 | 
				
			||||||
    // due to this renaming we need to be mindful when we compare the file name we're uploading with a name github may already have rewritten for logical comparison
 | 
					 | 
				
			||||||
    // see https://docs.github.com/en/rest/releases/assets?apiVersion=2022-11-28#upload-a-release-asset
 | 
					 | 
				
			||||||
    ({ name: currentName }) => currentName == name.replace(" ", ".")
 | 
					 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  if (currentAsset) {
 | 
					  if (currentAsset) {
 | 
				
			||||||
    console.log(`♻️ Deleting previously uploaded asset ${name}...`);
 | 
					    console.log(`♻️ Deleting previously uploaded asset ${name}...`);
 | 
				
			||||||
    await github.rest.repos.deleteReleaseAsset({
 | 
					    await github.rest.repos.deleteReleaseAsset({
 | 
				
			||||||
      asset_id: currentAsset.id || 1,
 | 
					      asset_id: currentAsset.id || 1,
 | 
				
			||||||
      owner,
 | 
					      owner,
 | 
				
			||||||
      repo,
 | 
					      repo
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  console.log(`⬆️ Uploading ${name}...`);
 | 
					  console.log(`⬆️ Uploading ${name}...`);
 | 
				
			||||||
  const endpoint = new URL(url);
 | 
					  const endpoint = new URL(url);
 | 
				
			||||||
  endpoint.searchParams.append("name", name);
 | 
					  endpoint.searchParams.append("name", name);
 | 
				
			||||||
  const resp = await github.request({
 | 
					  const resp = await fetch(endpoint, {
 | 
				
			||||||
    method: "POST",
 | 
					 | 
				
			||||||
    url: endpoint.toString(),
 | 
					 | 
				
			||||||
    headers: {
 | 
					    headers: {
 | 
				
			||||||
      "content-length": `${size}`,
 | 
					      "content-length": `${size}`,
 | 
				
			||||||
      "content-type": mime,
 | 
					      "content-type": mime,
 | 
				
			||||||
      authorization: `token ${config.github_token}`,
 | 
					      authorization: `token ${config.github_token}`
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    data: body,
 | 
					    method: "POST",
 | 
				
			||||||
 | 
					    body
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  const json = resp.data;
 | 
					  const json = await resp.json();
 | 
				
			||||||
  if (resp.status !== 201) {
 | 
					  if (resp.status !== 201) {
 | 
				
			||||||
    throw new Error(
 | 
					    throw new Error(
 | 
				
			||||||
      `Failed to upload release asset ${name}. received status code ${
 | 
					      `Failed to upload release asset ${name}. received status code ${
 | 
				
			||||||
@@ -208,80 +201,53 @@ export const release = async (
 | 
				
			|||||||
  try {
 | 
					  try {
 | 
				
			||||||
    // you can't get a an existing draft by tag
 | 
					    // you can't get a an existing draft by tag
 | 
				
			||||||
    // so we must find one in the list of all releases
 | 
					    // so we must find one in the list of all releases
 | 
				
			||||||
    let _release: Release | undefined = undefined;
 | 
					 | 
				
			||||||
    if (config.input_draft) {
 | 
					    if (config.input_draft) {
 | 
				
			||||||
      for await (const response of releaser.allReleases({
 | 
					      for await (const response of releaser.allReleases({
 | 
				
			||||||
        owner,
 | 
					        owner,
 | 
				
			||||||
        repo,
 | 
					        repo
 | 
				
			||||||
      })) {
 | 
					      })) {
 | 
				
			||||||
        _release = response.data.find((release) => release.tag_name === tag);
 | 
					        let release = response.data.find(release => release.tag_name === tag);
 | 
				
			||||||
 | 
					        if (release) {
 | 
				
			||||||
 | 
					          return release;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      _release = (
 | 
					 | 
				
			||||||
        await releaser.getReleaseByTag({
 | 
					 | 
				
			||||||
          owner,
 | 
					 | 
				
			||||||
          repo,
 | 
					 | 
				
			||||||
          tag,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      ).data;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (_release === null || _release === undefined) {
 | 
					 | 
				
			||||||
      return await createRelease(
 | 
					 | 
				
			||||||
        tag,
 | 
					 | 
				
			||||||
        config,
 | 
					 | 
				
			||||||
        releaser,
 | 
					 | 
				
			||||||
        owner,
 | 
					 | 
				
			||||||
        repo,
 | 
					 | 
				
			||||||
        discussion_category_name,
 | 
					 | 
				
			||||||
        generate_release_notes,
 | 
					 | 
				
			||||||
        maxRetries
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    let existingRelease = await releaser.getReleaseByTag({
 | 
				
			||||||
 | 
					      owner,
 | 
				
			||||||
 | 
					      repo,
 | 
				
			||||||
 | 
					      tag
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let existingRelease: Release = _release!;
 | 
					    const release_id = existingRelease.data.id;
 | 
				
			||||||
    console.log(
 | 
					 | 
				
			||||||
      `Found release ${existingRelease.name} (with id=${existingRelease.id})`
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const release_id = existingRelease.id;
 | 
					 | 
				
			||||||
    let target_commitish: string;
 | 
					    let target_commitish: string;
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
      config.input_target_commitish &&
 | 
					      config.input_target_commitish &&
 | 
				
			||||||
      config.input_target_commitish !== existingRelease.target_commitish
 | 
					      config.input_target_commitish !== existingRelease.data.target_commitish
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
      console.log(
 | 
					      console.log(
 | 
				
			||||||
        `Updating commit from "${existingRelease.target_commitish}" to "${config.input_target_commitish}"`
 | 
					        `Updating commit from "${existingRelease.data.target_commitish}" to "${config.input_target_commitish}"`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      target_commitish = config.input_target_commitish;
 | 
					      target_commitish = config.input_target_commitish;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      target_commitish = existingRelease.target_commitish;
 | 
					      target_commitish = existingRelease.data.target_commitish;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const tag_name = tag;
 | 
					    const tag_name = tag;
 | 
				
			||||||
    const name = config.input_name || existingRelease.name || tag;
 | 
					    const name = config.input_name || existingRelease.data.name || tag;
 | 
				
			||||||
    // revisit: support a new body-concat-strategy input for accumulating
 | 
					    // revisit: support a new body-concat-strategy input for accumulating
 | 
				
			||||||
    // body parts as a release gets updated. some users will likely want this while
 | 
					    // body parts as a release gets updated. some users will likely want this while
 | 
				
			||||||
    // others won't previously this was duplicating content for most which
 | 
					    // others won't previously this was duplicating content for most which
 | 
				
			||||||
    // no one wants
 | 
					    // no one wants
 | 
				
			||||||
    const workflowBody = releaseBody(config) || "";
 | 
					    let body = releaseBody(config) || existingRelease.data.body || "";
 | 
				
			||||||
    const existingReleaseBody = existingRelease.body || "";
 | 
					 | 
				
			||||||
    let body: string;
 | 
					 | 
				
			||||||
    if (config.input_append_body && workflowBody && existingReleaseBody) {
 | 
					 | 
				
			||||||
      body = existingReleaseBody + "\n" + workflowBody;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      body = workflowBody || existingReleaseBody;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const draft =
 | 
					    const draft =
 | 
				
			||||||
      config.input_draft !== undefined
 | 
					      config.input_draft !== undefined
 | 
				
			||||||
        ? config.input_draft
 | 
					        ? config.input_draft
 | 
				
			||||||
        : existingRelease.draft;
 | 
					        : existingRelease.data.draft;
 | 
				
			||||||
    const prerelease =
 | 
					    const prerelease =
 | 
				
			||||||
      config.input_prerelease !== undefined
 | 
					      config.input_prerelease !== undefined
 | 
				
			||||||
        ? config.input_prerelease
 | 
					        ? config.input_prerelease
 | 
				
			||||||
        : existingRelease.prerelease;
 | 
					        : existingRelease.data.prerelease;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const make_latest = config.input_make_latest;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const release = await releaser.updateRelease({
 | 
					    const release = await releaser.updateRelease({
 | 
				
			||||||
      owner,
 | 
					      owner,
 | 
				
			||||||
@@ -294,92 +260,54 @@ export const release = async (
 | 
				
			|||||||
      draft,
 | 
					      draft,
 | 
				
			||||||
      prerelease,
 | 
					      prerelease,
 | 
				
			||||||
      discussion_category_name,
 | 
					      discussion_category_name,
 | 
				
			||||||
      generate_release_notes,
 | 
					      generate_release_notes
 | 
				
			||||||
      make_latest,
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    return release.data;
 | 
					    return release.data;
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    if (error.status !== 404) {
 | 
					    if (error.status === 404) {
 | 
				
			||||||
 | 
					      const tag_name = tag;
 | 
				
			||||||
 | 
					      const name = config.input_name || tag;
 | 
				
			||||||
 | 
					      const body = releaseBody(config);
 | 
				
			||||||
 | 
					      const draft = config.input_draft;
 | 
				
			||||||
 | 
					      const prerelease = config.input_prerelease;
 | 
				
			||||||
 | 
					      const target_commitish = config.input_target_commitish;
 | 
				
			||||||
 | 
					      let commitMessage: string = "";
 | 
				
			||||||
 | 
					      if (target_commitish) {
 | 
				
			||||||
 | 
					        commitMessage = ` using commit "${target_commitish}"`;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      console.log(
 | 
				
			||||||
 | 
					        `👩🏭 Creating new GitHub release for tag ${tag_name}${commitMessage}...`
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        let release = await releaser.createRelease({
 | 
				
			||||||
 | 
					          owner,
 | 
				
			||||||
 | 
					          repo,
 | 
				
			||||||
 | 
					          tag_name,
 | 
				
			||||||
 | 
					          name,
 | 
				
			||||||
 | 
					          body,
 | 
				
			||||||
 | 
					          draft,
 | 
				
			||||||
 | 
					          prerelease,
 | 
				
			||||||
 | 
					          target_commitish,
 | 
				
			||||||
 | 
					          discussion_category_name,
 | 
				
			||||||
 | 
					          generate_release_notes
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return release.data;
 | 
				
			||||||
 | 
					      } catch (error) {
 | 
				
			||||||
 | 
					        // presume a race with competing metrix runs
 | 
				
			||||||
 | 
					        console.log(
 | 
				
			||||||
 | 
					          `⚠️ GitHub release failed with status: ${
 | 
				
			||||||
 | 
					            error.status
 | 
				
			||||||
 | 
					          }\n${JSON.stringify(
 | 
				
			||||||
 | 
					            error.response.data.errors
 | 
				
			||||||
 | 
					          )}\nretrying... (${maxRetries - 1} retries remaining)`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return release(config, releaser, maxRetries - 1);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
      console.log(
 | 
					      console.log(
 | 
				
			||||||
        `⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`
 | 
					        `⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      throw error;
 | 
					      throw error;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return await createRelease(
 | 
					 | 
				
			||||||
      tag,
 | 
					 | 
				
			||||||
      config,
 | 
					 | 
				
			||||||
      releaser,
 | 
					 | 
				
			||||||
      owner,
 | 
					 | 
				
			||||||
      repo,
 | 
					 | 
				
			||||||
      discussion_category_name,
 | 
					 | 
				
			||||||
      generate_release_notes,
 | 
					 | 
				
			||||||
      maxRetries
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
async function createRelease(
 | 
					 | 
				
			||||||
  tag: string,
 | 
					 | 
				
			||||||
  config: Config,
 | 
					 | 
				
			||||||
  releaser: Releaser,
 | 
					 | 
				
			||||||
  owner: string,
 | 
					 | 
				
			||||||
  repo: string,
 | 
					 | 
				
			||||||
  discussion_category_name: string | undefined,
 | 
					 | 
				
			||||||
  generate_release_notes: boolean | undefined,
 | 
					 | 
				
			||||||
  maxRetries: number
 | 
					 | 
				
			||||||
) {
 | 
					 | 
				
			||||||
  const tag_name = tag;
 | 
					 | 
				
			||||||
  const name = config.input_name || tag;
 | 
					 | 
				
			||||||
  const body = releaseBody(config);
 | 
					 | 
				
			||||||
  const draft = config.input_draft;
 | 
					 | 
				
			||||||
  const prerelease = config.input_prerelease;
 | 
					 | 
				
			||||||
  const target_commitish = config.input_target_commitish;
 | 
					 | 
				
			||||||
  const make_latest = config.input_make_latest;
 | 
					 | 
				
			||||||
  let commitMessage: string = "";
 | 
					 | 
				
			||||||
  if (target_commitish) {
 | 
					 | 
				
			||||||
    commitMessage = ` using commit "${target_commitish}"`;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  console.log(
 | 
					 | 
				
			||||||
    `👩🏭 Creating new GitHub release for tag ${tag_name}${commitMessage}...`
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    let release = await releaser.createRelease({
 | 
					 | 
				
			||||||
      owner,
 | 
					 | 
				
			||||||
      repo,
 | 
					 | 
				
			||||||
      tag_name,
 | 
					 | 
				
			||||||
      name,
 | 
					 | 
				
			||||||
      body,
 | 
					 | 
				
			||||||
      draft,
 | 
					 | 
				
			||||||
      prerelease,
 | 
					 | 
				
			||||||
      target_commitish,
 | 
					 | 
				
			||||||
      discussion_category_name,
 | 
					 | 
				
			||||||
      generate_release_notes,
 | 
					 | 
				
			||||||
      make_latest,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return release.data;
 | 
					 | 
				
			||||||
  } catch (error) {
 | 
					 | 
				
			||||||
    // presume a race with competing matrix runs
 | 
					 | 
				
			||||||
    console.log(`⚠️ GitHub release failed with status: ${error.status}`);
 | 
					 | 
				
			||||||
    console.log(`${JSON.stringify(error.response.data)}`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (error.status) {
 | 
					 | 
				
			||||||
      case 403:
 | 
					 | 
				
			||||||
        console.log(
 | 
					 | 
				
			||||||
          "Skip retry — your GitHub token/PAT does not have the required permission to create a release"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      case 404:
 | 
					 | 
				
			||||||
        console.log("Skip retry - discussion category mismatch");
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      case 422:
 | 
					 | 
				
			||||||
        console.log("Skip retry - validation failed");
 | 
					 | 
				
			||||||
        throw error;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log(`retrying... (${maxRetries - 1} retries remaining)`);
 | 
					 | 
				
			||||||
    return release(config, releaser, maxRetries - 1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								src/main.ts
									
									
									
									
									
								
							@@ -3,13 +3,13 @@ import {
 | 
				
			|||||||
  parseConfig,
 | 
					  parseConfig,
 | 
				
			||||||
  isTag,
 | 
					  isTag,
 | 
				
			||||||
  unmatchedPatterns,
 | 
					  unmatchedPatterns,
 | 
				
			||||||
  uploadUrl,
 | 
					  uploadUrl
 | 
				
			||||||
} from "./util";
 | 
					} from "./util";
 | 
				
			||||||
import { release, upload, GitHubReleaser } from "./github";
 | 
					import { release, upload, GitHubReleaser } from "./github";
 | 
				
			||||||
import { getOctokit } from "@actions/github";
 | 
					import { Octokit } from "@octokit/action";
 | 
				
			||||||
import { setFailed, setOutput } from "@actions/core";
 | 
					import { setFailed, setOutput } from "@actions/core";
 | 
				
			||||||
import { GitHub, getOctokitOptions } from "@actions/github/lib/utils";
 | 
					import { retry } from "@octokit/plugin-retry";
 | 
				
			||||||
 | 
					import { throttling } from "@octokit/plugin-throttling";
 | 
				
			||||||
import { env } from "process";
 | 
					import { env } from "process";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function run() {
 | 
					async function run() {
 | 
				
			||||||
@@ -24,25 +24,17 @@ async function run() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (config.input_files) {
 | 
					    if (config.input_files) {
 | 
				
			||||||
      const patterns = unmatchedPatterns(config.input_files);
 | 
					      const patterns = unmatchedPatterns(config.input_files);
 | 
				
			||||||
      patterns.forEach((pattern) => {
 | 
					      patterns.forEach(pattern =>
 | 
				
			||||||
        if (config.input_fail_on_unmatched_files) {
 | 
					        console.warn(`🤔 Pattern '${pattern}' does not match any files.`)
 | 
				
			||||||
          throw new Error(`⚠️  Pattern '${pattern}' does not match any files.`);
 | 
					      );
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          console.warn(`🤔 Pattern '${pattern}' does not match any files.`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      if (patterns.length > 0 && config.input_fail_on_unmatched_files) {
 | 
					      if (patterns.length > 0 && config.input_fail_on_unmatched_files) {
 | 
				
			||||||
        throw new Error(`⚠️ There were unmatched files`);
 | 
					        throw new Error(`⚠️ There were unmatched files`);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // const oktokit = GitHub.plugin(
 | 
					    const OctokitWithPlugins = Octokit.plugin(retry, throttling);
 | 
				
			||||||
    //   require("@octokit/plugin-throttling"),
 | 
					    const gh = new OctokitWithPlugins({
 | 
				
			||||||
    //   require("@octokit/plugin-retry")
 | 
					      auth: config.github_token,
 | 
				
			||||||
    // );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const gh = getOctokit(config.github_token, {
 | 
					 | 
				
			||||||
      //new oktokit(
 | 
					 | 
				
			||||||
      throttle: {
 | 
					      throttle: {
 | 
				
			||||||
        onRateLimit: (retryAfter, options) => {
 | 
					        onRateLimit: (retryAfter, options) => {
 | 
				
			||||||
          console.warn(
 | 
					          console.warn(
 | 
				
			||||||
@@ -59,23 +51,19 @@ async function run() {
 | 
				
			|||||||
          console.warn(
 | 
					          console.warn(
 | 
				
			||||||
            `Abuse detected for request ${options.method} ${options.url}`
 | 
					            `Abuse detected for request ${options.method} ${options.url}`
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
        },
 | 
					        }
 | 
				
			||||||
      },
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    //);
 | 
					    //);
 | 
				
			||||||
    const rel = await release(config, new GitHubReleaser(gh));
 | 
					    const rel = await release(config, new GitHubReleaser(gh));
 | 
				
			||||||
    if (config.input_files && config.input_files.length > 0) {
 | 
					    if (config.input_files) {
 | 
				
			||||||
      const files = paths(config.input_files);
 | 
					      const files = paths(config.input_files);
 | 
				
			||||||
      if (files.length == 0) {
 | 
					      if (files.length == 0) {
 | 
				
			||||||
        if (config.input_fail_on_unmatched_files) {
 | 
					        console.warn(`🤔 ${config.input_files} not include valid file.`);
 | 
				
			||||||
          throw new Error(`⚠️ ${config.input_files} not include valid file.`);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          console.warn(`🤔 ${config.input_files} not include valid file.`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      const currentAssets = rel.assets;
 | 
					      const currentAssets = rel.assets;
 | 
				
			||||||
      const assets = await Promise.all(
 | 
					      const assets = await Promise.all(
 | 
				
			||||||
        files.map(async (path) => {
 | 
					        files.map(async path => {
 | 
				
			||||||
          const json = await upload(
 | 
					          const json = await upload(
 | 
				
			||||||
            config,
 | 
					            config,
 | 
				
			||||||
            gh,
 | 
					            gh,
 | 
				
			||||||
@@ -86,7 +74,7 @@ async function run() {
 | 
				
			|||||||
          delete json.uploader;
 | 
					          delete json.uploader;
 | 
				
			||||||
          return json;
 | 
					          return json;
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      ).catch((error) => {
 | 
					      ).catch(error => {
 | 
				
			||||||
        throw error;
 | 
					        throw error;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      setOutput("assets", assets);
 | 
					      setOutput("assets", assets);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								src/util.ts
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/util.ts
									
									
									
									
									
								
							@@ -18,8 +18,6 @@ export interface Config {
 | 
				
			|||||||
  input_target_commitish?: string;
 | 
					  input_target_commitish?: string;
 | 
				
			||||||
  input_discussion_category_name?: string;
 | 
					  input_discussion_category_name?: string;
 | 
				
			||||||
  input_generate_release_notes?: boolean;
 | 
					  input_generate_release_notes?: boolean;
 | 
				
			||||||
  input_append_body?: boolean;
 | 
					 | 
				
			||||||
  input_make_latest: string | undefined;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const uploadUrl = (url: string): string => {
 | 
					export const uploadUrl = (url: string): string => {
 | 
				
			||||||
@@ -45,8 +43,8 @@ export const parseInputFiles = (files: string): string[] => {
 | 
				
			|||||||
    (acc, line) =>
 | 
					    (acc, line) =>
 | 
				
			||||||
      acc
 | 
					      acc
 | 
				
			||||||
        .concat(line.split(","))
 | 
					        .concat(line.split(","))
 | 
				
			||||||
        .filter((pat) => pat)
 | 
					        .filter(pat => pat)
 | 
				
			||||||
        .map((pat) => pat.trim()),
 | 
					        .map(pat => pat.trim()),
 | 
				
			||||||
    []
 | 
					    []
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -69,18 +67,14 @@ export const parseConfig = (env: Env): Config => {
 | 
				
			|||||||
    input_target_commitish: env.INPUT_TARGET_COMMITISH || undefined,
 | 
					    input_target_commitish: env.INPUT_TARGET_COMMITISH || undefined,
 | 
				
			||||||
    input_discussion_category_name:
 | 
					    input_discussion_category_name:
 | 
				
			||||||
      env.INPUT_DISCUSSION_CATEGORY_NAME || undefined,
 | 
					      env.INPUT_DISCUSSION_CATEGORY_NAME || undefined,
 | 
				
			||||||
    input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true",
 | 
					    input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true"
 | 
				
			||||||
    input_append_body: env.INPUT_APPEND_BODY == "true",
 | 
					 | 
				
			||||||
    input_make_latest: env.INPUT_MAKE_LATEST
 | 
					 | 
				
			||||||
      ? env.INPUT_MAKE_LATEST
 | 
					 | 
				
			||||||
      : undefined,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const paths = (patterns: string[]): string[] => {
 | 
					export const paths = (patterns: string[]): string[] => {
 | 
				
			||||||
  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
					  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
				
			||||||
    return acc.concat(
 | 
					    return acc.concat(
 | 
				
			||||||
      glob.sync(pattern).filter((path) => statSync(path).isFile())
 | 
					      glob.sync(pattern).filter(path => statSync(path).isFile())
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }, []);
 | 
					  }, []);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -88,7 +82,7 @@ export const paths = (patterns: string[]): string[] => {
 | 
				
			|||||||
export const unmatchedPatterns = (patterns: string[]): string[] => {
 | 
					export const unmatchedPatterns = (patterns: string[]): string[] => {
 | 
				
			||||||
  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
					  return patterns.reduce((acc: string[], pattern: string): string[] => {
 | 
				
			||||||
    return acc.concat(
 | 
					    return acc.concat(
 | 
				
			||||||
      glob.sync(pattern).filter((path) => statSync(path).isFile()).length == 0
 | 
					      glob.sync(pattern).filter(path => statSync(path).isFile()).length == 0
 | 
				
			||||||
        ? [pattern]
 | 
					        ? [pattern]
 | 
				
			||||||
        : []
 | 
					        : []
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "compilerOptions": {
 | 
					  "compilerOptions": {
 | 
				
			||||||
    "useUnknownInCatchVariables": false,
 | 
					 | 
				
			||||||
    /* Basic Options */
 | 
					    /* Basic Options */
 | 
				
			||||||
    // "incremental": true,                   /* Enable incremental compilation */
 | 
					    // "incremental": true,                   /* Enable incremental compilation */
 | 
				
			||||||
    "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
 | 
					    "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user