mirror of
https://github.com/hashicorp/setup-terraform.git
synced 2025-12-17 08:52:37 +00:00
Compare commits
No commits in common. "main" and "v2.0.1" have entirely different histories.
48 changed files with 26344 additions and 68697 deletions
|
|
@ -1,169 +0,0 @@
|
|||
# [2.0.3] (2022-11-01)
|
||||
|
||||
### NOTES
|
||||
|
||||
* Reduced occurrences of GitHub Actions warnings for setting output [#247](https://github.com/hashicorp/setup-terraform/pull/247)
|
||||
|
||||
# [2.0.2] (2022-10-12)
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
* Update 2.0.1 release metadata by @jpogran in https://github.com/hashicorp/setup-terraform/pull/253
|
||||
* `README.md` updates - direct links to license and code of conduct, updated GitHub documents link by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/244
|
||||
|
||||
### INTERNAL
|
||||
|
||||
* Bump jest from 29.0.3 to 29.1.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/248
|
||||
|
||||
# [2.0.1] (2022-10-12)
|
||||
|
||||
### ENHANCEMENTS
|
||||
|
||||
* Do not fail when theres an exit-code 2 by @dannyibishev in https://github.com/hashicorp/setup-terraform/pull/125
|
||||
* Updated README to reflect GitHub limitations by @rnsc in https://github.com/hashicorp/setup-terraform/pull/205
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
* Fix terraform extract by @cpc-camarj in https://github.com/hashicorp/setup-terraform/pull/187
|
||||
* Add new-style readme build badges, bump `actions/checkout` in `README.md` examples by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/188
|
||||
* Fixed `master` to `main` workflow branch triggers by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/216
|
||||
* Fix the example of how to comment on pull request. by @acarmel in https://github.com/hashicorp/setup-terraform/pull/220
|
||||
|
||||
### INTERNAL
|
||||
|
||||
* Bump @actions/core from 1.6.0 to 1.7.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/185
|
||||
* Bump @vercel/ncc from 0.33.3 to 0.33.4 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/182
|
||||
* Bump jest from 27.5.1 to 28.0.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/184
|
||||
* Bump jest from 28.0.0 to 28.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/190
|
||||
* Bump husky from 7.0.4 to 8.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/193
|
||||
* Bump jest from 28.0.3 to 28.1.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/194
|
||||
* Bump @actions/github from 5.0.1 to 5.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/201
|
||||
* Bump @actions/core from 1.7.0 to 1.8.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/200
|
||||
* Bump @actions/tool-cache from 1.7.2 to 2.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/199
|
||||
* TF DevEx: repo adoption by @detro in https://github.com/hashicorp/setup-terraform/pull/204
|
||||
* Bump nock from 13.2.4 to 13.2.6 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/212
|
||||
* Bump @vercel/ncc from 0.33.4 to 0.34.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/210
|
||||
* Bump jest from 28.1.0 to 28.1.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/215
|
||||
* Bump nock from 13.2.6 to 13.2.7 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/217
|
||||
* Bump jest from 28.1.1 to 28.1.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/221
|
||||
* Bump jest from 28.1.2 to 28.1.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/224
|
||||
* Bump nock from 13.2.7 to 13.2.9 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/225
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 1.2.1 to 1.3.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/233
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 1.3.0 to 2.0.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/243
|
||||
* Bump jest from 28.1.3 to 29.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/242
|
||||
* Bump @hashicorp/js-releases from 1.5.1 to 1.6.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/226
|
||||
* Bump @actions/core from 1.8.2 to 1.9.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/235
|
||||
* Bump @actions/core from 1.6.0 to 1.9.1 in /wrapper by @dependabot in https://github.com/hashicorp/setup-terraform/pull/236
|
||||
* Bump @actions/github from 5.0.3 to 5.1.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/249
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 2.0.0 to 2.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/250
|
||||
|
||||
# [2.0.0] (2022-04-18)
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
||||
* Support Actions Runners v2.285.0 or later by upgrading to Nodejs v16 runtime by @chenrui333 in https://github.com/hashicorp/setup-terraform/pull/170
|
||||
|
||||
NOTES:
|
||||
|
||||
* docs: Update existing PR comments example by @tobiasbueschel in https://github.com/hashicorp/setup-terraform/pull/178
|
||||
* Update Terraform versions and usage in README examples by @ksatirli in https://github.com/hashicorp/setup-terraform/pull/176
|
||||
* Update grammar in README.md by @dustindortch in https://github.com/hashicorp/setup-terraform/pull/180
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Bump @actions/github from 5.0.0 to 5.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/177
|
||||
* dependabot: track github-actions dependency changes by @chenrui333 in https://github.com/hashicorp/setup-terraform/pull/179
|
||||
|
||||
# [1.4.0] (2022-04-04)
|
||||
|
||||
NOTES:
|
||||
|
||||
- Update readme using github-script@v5 by @krrrr38 in ([#135](https://github.com/hashicorp/setup-terraform/pull/135))
|
||||
- Update actions/github-script to v6 in README by @shouichi in ([#148](https://github.com/hashicorp/setup-terraform/pull/148))
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Improve output for PR comment by @skpy in ([#129](https://github.com/hashicorp/setup-terraform/pull/129))
|
||||
- Allow proxy values to be set by @rabun788 in ([#147](https://github.com/hashicorp/setup-terraform/pull/147))
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Allow dependabot to check node modules by @jlosito in ([#87](https://github.com/hashicorp/setup-terraform/pull/87))
|
||||
- Update js-releases to v1.4.0 by @aeschright in ([#111](https://github.com/hashicorp/setup-terraform/pull/111))
|
||||
- Updates Readme by @ndrone-kr in ([#86](https://github.com/hashicorp/setup-terraform/pull/86))
|
||||
- Update husky to v6.0 by @aeschright in ([#113](https://github.com/hashicorp/setup-terraform/pull/113))
|
||||
- Bump development dependencies by @jpogran in ([#153](https://github.com/hashicorp/setup-terraform/pull/153))
|
||||
- Bump node-fetch from 2.6.1 to 2.6.7 by @dependabot in ([#154](https://github.com/hashicorp/setup-terraform/pull/154))
|
||||
- Bump @actions/github from 4.0.0 to 5.0.0 by @dependabot in ([#114](https://github.com/hashicorp/setup-terraform/pull/114))
|
||||
- Bump @actions/io from 1.1.0 to 1.1.1 by @dependabot in ([#156](https://github.com/hashicorp/setup-terraform/pull/156))
|
||||
- Bump @actions/core from 1.2.7 to 1.6.0 by @dependabot in ([#158](https://github.com/hashicorp/setup-terraform/pull/158))
|
||||
- Bump @actions/tool-cache from 1.6.1 to 1.7.1 by @dependabot in ([#159](https://github.com/hashicorp/setup-terraform/pull/159))
|
||||
- Bump @actions/core from 1.2.7 to 1.6.0 by @jpogran in ([#160](https://github.com/hashicorp/setup-terraform/pull/160))
|
||||
- Bump @actions/exec from 1.0.4 to 1.1.0 by @jpogran in ([#161](https://github.com/hashicorp/setup-terraform/pull/161))
|
||||
- Bump @actions/io from 1.1.0 to 1.1.1 by @jpogran in ([#162](https://github.com/hashicorp/setup-terraform/pull/162))
|
||||
- Bump @hashicorp/js-releases from 1.5.0 to 1.5.1 by @dependabot in ([#166](https://github.com/hashicorp/setup-terraform/pull/166))
|
||||
- Bump minimist from 1.2.5 to 1.2.6 by @dependabot in ([#168](https://github.com/hashicorp/setup-terraform/pull/168))
|
||||
- Bump @actions/tool-cache from 1.7.1 to 1.7.2 by @dependabot in ([#164](https://github.com/hashicorp/setup-terraform/pull/164))
|
||||
- Bump @actions/io from 1.1.1 to 1.1.2 by @dependabot in ([#165](https://github.com/hashicorp/setup-terraform/pull/165))
|
||||
- Bump minimist from 1.2.5 to 1.2.6 in /wrapper by @dependabot in ([#169](https://github.com/hashicorp/setup-terraform/pull/169))
|
||||
- Add GitHub automatic release by @jpogran in ([#173](https://github.com/hashicorp/setup-terraform/pull/173))
|
||||
|
||||
# [1.3.2] (2020-12-09)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Update js-releases to fix missing dep in bundle ([#78](https://github.com/hashicorp/setup-terraform/pull/78))
|
||||
|
||||
# [1.3.1] (2020-12-08)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Fix build dependency ([#76](https://github.com/hashicorp/setup-terraform/pull/76))
|
||||
|
||||
# [1.3.0] (2020-12-08)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Use `@hashicorp/js-releases` package to identify and download the specified version of Terraform. This will ensure that our tooling is consistent in how it works with the releases API, especially when handling pre-releases. ([#70](https://github.com/hashicorp/setup-terraform/pull/70), [#73](https://github.com/hashicorp/setup-terraform/pull/73))
|
||||
|
||||
# [1.2.1] (2020-10-30)
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Update dependencies to resolve CVE-2020-15228 ([#63](https://github.com/hashicorp/setup-terraform/pull/63))
|
||||
|
||||
# [1.2.0]
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Allow `terraform_version` to take a version constraint. ([#38](https://github.com/hashicorp/setup-terraform/pull/38))
|
||||
|
||||
# [1.1.0]
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Ignore pre-release versions when `terraform_version` is set to `latest`. ([#19](https://github.com/hashicorp/setup-terraform/pull/19))
|
||||
|
||||
# [1.0.1]
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Bump @actions/http-client from 1.0.6 to 1.0.8. ([#1](https://github.com/hashicorp/setup-terraform/pull/1))
|
||||
|
||||
# [1.0.0]
|
||||
|
||||
- Initial release.
|
||||
|
||||
<!-- Links to tag comparisons -->
|
||||
[Unreleased]: https://github.com/hashicorp/setup-terraform/compare/v2.0.2...main
|
||||
[2.0.2]: https://github.com/hashicorp/setup-terraform/compare/v2.0.1...v2.0.2
|
||||
[2.0.1]: https://github.com/hashicorp/setup-terraform/compare/v2.0.0...v2.0.1
|
||||
[2.0.0]: https://github.com/hashicorp/setup-terraform/compare/v1.4.0...v2.0.0
|
||||
[1.4.0]: https://github.com/hashicorp/setup-terraform/compare/v1.3.2...v1.4.0
|
||||
[1.3.2]: https://github.com/hashicorp/setup-terraform/compare/v1.3.1...v1.3.2
|
||||
[1.3.1]: https://github.com/hashicorp/setup-terraform/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/hashicorp/setup-terraform/compare/v1.2.1...v1.3.0
|
||||
[1.2.1]: https://github.com/hashicorp/setup-terraform/compare/v1.2.0...v1.2.1
|
||||
[1.2.0]: https://github.com/hashicorp/setup-terraform/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/hashicorp/setup-terraform/compare/v1.0.1...v1.1.0
|
||||
[1.0.1]: https://github.com/hashicorp/setup-terraform/compare/v1.0.0...v1.0.1
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
## 3.0.0 (2023-10-30)
|
||||
|
||||
NOTES:
|
||||
|
||||
* Updated default runtime to node20 ([#346](https://github.com/hashicorp/setup-terraform/issues/346))
|
||||
* The wrapper around the installed Terraform binary has been fixed to return the exact STDOUT and STDERR from Terraform when executing commands. Previous versions of setup-terraform may have required workarounds to process the STDOUT in bash, such as filtering out the first line or selectively parsing STDOUT with jq. These workarounds may need to be adjusted with `v3.0.0`, which will now return just the STDOUT/STDERR from Terraform with no errant characters/statements. ([#367](https://github.com/hashicorp/setup-terraform/issues/367))
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fixed malformed stdout when wrapper is enabled ([#367](https://github.com/hashicorp/setup-terraform/issues/367))
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
## 3.1.0 (2024-04-23)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* Automatically fallback to darwin/amd64 for Terraform versions before 1.0.2 as releases for darwin/arm64 are not available ([#409](https://github.com/hashicorp/setup-terraform/issues/409))
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
## 3.1.1 (2024-05-07)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* wrapper: Fix wrapper to output to stdout and stderr immediately when data is received ([#395](https://github.com/hashicorp/setup-terraform/issues/395))
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
## 3.1.2 (2024-08-19)
|
||||
|
||||
NOTES:
|
||||
|
||||
* This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#430](https://github.com/hashicorp/setup-terraform/issues/430))
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
changesDir: .changes
|
||||
unreleasedDir: unreleased
|
||||
changelogPath: CHANGELOG.md
|
||||
versionExt: md
|
||||
versionFormat: '## {{.Version}} ({{.Time.Format "2006-01-02"}})'
|
||||
kindFormat: '{{.Kind}}:'
|
||||
changeFormat: '* {{.Body}} ([#{{.Custom.Issue}}](https://github.com/hashicorp/setup-terraform/issues/{{.Custom.Issue}}))'
|
||||
custom:
|
||||
- key: Issue
|
||||
label: Issue/PR Number
|
||||
type: int
|
||||
minInt: 1
|
||||
kinds:
|
||||
- label: BREAKING CHANGES
|
||||
- label: NOTES
|
||||
- label: FEATURES
|
||||
- label: ENHANCEMENTS
|
||||
- label: BUG FIXES
|
||||
newlines:
|
||||
afterKind: 1
|
||||
beforeKind: 1
|
||||
endOfVersion: 2
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
schema_version = 1
|
||||
|
||||
project {
|
||||
license = "MPL-2.0"
|
||||
copyright_year = 2020
|
||||
|
||||
header_ignore = [
|
||||
# internal catalog metadata (prose)
|
||||
"META.d/**/*.yaml",
|
||||
|
||||
# changie tooling configuration and CHANGELOG entries (prose)
|
||||
".changes/unreleased/*.yaml",
|
||||
".changie.yaml",
|
||||
|
||||
# GitHub issue template configuration
|
||||
".github/ISSUE_TEMPLATE/*.yml",
|
||||
|
||||
# GitHub Actions workflow-specific configurations
|
||||
".github/labeler-*.yml",
|
||||
|
||||
# Github Action linting configuration
|
||||
".github/actionlint.yaml",
|
||||
|
||||
# Release Engineering tooling configuration
|
||||
".release/*.hcl",
|
||||
|
||||
# Auto-generated /dist
|
||||
"dist/**",
|
||||
|
||||
# GitHub Action metadata file
|
||||
"action.yml",
|
||||
]
|
||||
}
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
|
@ -1 +1 @@
|
|||
* @hashicorp/terraform-core-plugins
|
||||
* @hashicorp/terraform-devex
|
||||
|
|
|
|||
7
.github/dependabot.yml
vendored
7
.github/dependabot.yml
vendored
|
|
@ -6,12 +6,5 @@ updates:
|
|||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
groups:
|
||||
"github-actions":
|
||||
patterns:
|
||||
- "*" # Group all GitHub Actions dependencies together
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "09:00"
|
||||
timezone: "Etc/UTC"
|
||||
|
|
|
|||
16
.github/pull_request_template.md
vendored
16
.github/pull_request_template.md
vendored
|
|
@ -1,16 +0,0 @@
|
|||
## Related Issue
|
||||
|
||||
Fixes # <!-- INSERT ISSUE NUMBER -->
|
||||
|
||||
## Description
|
||||
|
||||
In plain English, describe your approach to addressing the issue linked above. For example, if you made a particular design decision, let us know why you chose this path instead of another solution.
|
||||
|
||||
<!-- heimdall_github_prtemplate:grc-pci_dss-2024-01-05 -->
|
||||
## Rollback Plan
|
||||
|
||||
- [ ] If a change needs to be reverted, we will roll out an update to the code within 7 days.
|
||||
|
||||
## Changes to Security Controls
|
||||
|
||||
Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.
|
||||
26
.github/release.yml
vendored
Normal file
26
.github/release.yml
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
changelog:
|
||||
categories:
|
||||
- title: NOTES
|
||||
labels:
|
||||
- note
|
||||
- documentation
|
||||
- title: FEATURES
|
||||
labels:
|
||||
- feature
|
||||
- title: ENHANCEMENTS
|
||||
labels:
|
||||
- enhancement
|
||||
- documentation
|
||||
- title: BUG FIXES
|
||||
labels:
|
||||
- bug
|
||||
- title: INTERNAL
|
||||
labels:
|
||||
- dependencies
|
||||
- "*"
|
||||
exclude:
|
||||
labels:
|
||||
- duplicate
|
||||
- wontfix
|
||||
- question
|
||||
- invalid
|
||||
40
.github/workflows/add-content-to-project.yml
vendored
Normal file
40
.github/workflows/add-content-to-project.yml
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Based on https://github.com/leonsteinhaeuser/project-beta-automations
|
||||
|
||||
name: "Add Issues/PRs to TF Provider DevEx team board"
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
pull_request_target:
|
||||
# NOTE: The way content is added to project board is equivalent to an "upsert".
|
||||
# Calling it multiple times will be idempotent.
|
||||
#
|
||||
# See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
|
||||
# to see the reasoning behind using `pull_request_target` instead of `pull_request`
|
||||
types: [opened, reopened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
add-content-to-project:
|
||||
name: "Add Content to project"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Set Issue to 'Priority = Triage Next'"
|
||||
uses: leonsteinhaeuser/project-beta-automations@v2.0.1
|
||||
if: github.event_name == 'issues'
|
||||
with:
|
||||
gh_token: ${{ secrets.TF_DEVEX_PROJECT_GITHUB_TOKEN }}
|
||||
organization: "hashicorp"
|
||||
project_id: 99 #< https://github.com/orgs/hashicorp/projects/99
|
||||
resource_node_id: ${{ github.event.issue.node_id }}
|
||||
operation_mode: custom_field
|
||||
custom_field_values: '[{\"name\":\"Priority\",\"type\":\"single_select\",\"value\":\"Triage Next\"}]'
|
||||
- name: "Set Pull Request to 'Priority = Triage Next'"
|
||||
uses: leonsteinhaeuser/project-beta-automations@v2.0.1
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
gh_token: ${{ secrets.TF_DEVEX_PROJECT_GITHUB_TOKEN }}
|
||||
organization: "hashicorp"
|
||||
project_id: 99 #< https://github.com/orgs/hashicorp/projects/99
|
||||
resource_node_id: ${{ github.event.pull_request.node_id }}
|
||||
operation_mode: custom_field
|
||||
custom_field_values: '[{\"name\":\"Priority\",\"type\":\"single_select\",\"value\":\"Triage Next\"}]'
|
||||
23
.github/workflows/ci-changie.yml
vendored
23
.github/workflows/ci-changie.yml
vendored
|
|
@ -1,23 +0,0 @@
|
|||
# Continuous integration handling for changie
|
||||
name: ci-changie
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .changes/unreleased/*.yaml
|
||||
- .changie.yaml
|
||||
- .github/workflows/ci-changie.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: miniscruff/changie-action@5036dffa79ffc007110dc7f75eca7ef72780e147 # v2.1.0
|
||||
with:
|
||||
version: latest
|
||||
args: batch patch --dry-run
|
||||
|
||||
17
.github/workflows/compliance.yml
vendored
17
.github/workflows/compliance.yml
vendored
|
|
@ -1,17 +0,0 @@
|
|||
name: compliance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# Reference: ENGSRV-059
|
||||
copywrite:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: hashicorp/setup-copywrite@32638da2d4e81d56a0764aa1547882fc4d209636 # v1.1.3
|
||||
- run: copywrite headers --plan
|
||||
- run: copywrite license --plan
|
||||
36
.github/workflows/continuous-integration.yml
vendored
36
.github/workflows/continuous-integration.yml
vendored
|
|
@ -7,16 +7,30 @@ on:
|
|||
pull_request:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
name: Check dist/ directory
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@95d9656793415e47f574f7967f3850ea3bf5a7ed
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-caching: npm
|
||||
|
||||
test:
|
||||
name: Test
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@95d9656793415e47f574f7967f3850ea3bf5a7ed
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-caching: npm
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
- name: Install
|
||||
run: npm clean-install
|
||||
|
||||
- name: Verify
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
npm run build
|
||||
# Fail if "npm run build" generated new changes in dist
|
||||
git update-index --refresh dist/* && git diff-index --quiet HEAD dist
|
||||
|
||||
- name: Test
|
||||
run: npm test
|
||||
|
|
|
|||
11
.github/workflows/data/delay/main.tf
vendored
11
.github/workflows/data/delay/main.tf
vendored
|
|
@ -1,11 +0,0 @@
|
|||
resource "null_resource" "previous" {}
|
||||
|
||||
resource "time_sleep" "wait_30_seconds" {
|
||||
depends_on = [null_resource.previous]
|
||||
|
||||
create_duration = "30s"
|
||||
}
|
||||
|
||||
resource "null_resource" "next" {
|
||||
depends_on = [time_sleep.wait_30_seconds]
|
||||
}
|
||||
8
.github/workflows/data/local/main.tf
vendored
8
.github/workflows/data/local/main.tf
vendored
|
|
@ -1,5 +1,5 @@
|
|||
resource "random_pet" "pet" {}
|
||||
|
||||
output "pet" {
|
||||
value = random_pet.pet.id
|
||||
resource "null_resource" "null" {
|
||||
triggers = {
|
||||
value = timestamp()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
21
.github/workflows/issue-comment-triage.yml
vendored
21
.github/workflows/issue-comment-triage.yml
vendored
|
|
@ -1,21 +0,0 @@
|
|||
# DO NOT EDIT - This GitHub Workflow is managed by automation
|
||||
# https://github.com/hashicorp/terraform-devex-repos
|
||||
name: Issue Comment Triage
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
issue_comment_triage:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
# issue_comment events are triggered by comments on issues and pull requests. Checking the
|
||||
# value of github.event.issue.pull_request tells us whether the issue is an issue or is
|
||||
# actually a pull request, allowing us to dynamically set the gh subcommand:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment-on-issues-only-or-pull-requests-only
|
||||
COMMAND: ${{ github.event.issue.pull_request && 'pr' || 'issue' }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
steps:
|
||||
- name: 'Remove waiting-response on comment'
|
||||
run: gh ${{ env.COMMAND }} edit ${{ github.event.issue.html_url }} --remove-label waiting-response
|
||||
22
.github/workflows/lock.yml
vendored
22
.github/workflows/lock.yml
vendored
|
|
@ -1,22 +0,0 @@
|
|||
# DO NOT EDIT - This GitHub Workflow is managed by automation
|
||||
# https://github.com/hashicorp/terraform-devex-repos
|
||||
name: 'Lock Threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# NOTE: When TSCCR updates the GitHub action version, update the template workflow file to avoid drift:
|
||||
# https://github.com/hashicorp/terraform-devex-repos/blob/main/modules/repo/workflows/lock.tftpl
|
||||
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0
|
||||
with:
|
||||
process-only: 'issues, prs'
|
||||
github-token: ${{ github.token }}
|
||||
issue-inactive-days: '30'
|
||||
issue-lock-reason: resolved
|
||||
pr-inactive-days: '30'
|
||||
pr-lock-reason: resolved
|
||||
136
.github/workflows/release.yml
vendored
136
.github/workflows/release.yml
vendored
|
|
@ -1,134 +1,20 @@
|
|||
name: release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
versionNumber:
|
||||
description: 'Release version number (v#.#.#)'
|
||||
type: string
|
||||
required: true
|
||||
name: Publish GitHub Release
|
||||
|
||||
permissions:
|
||||
contents: read # Changelog commit operations use service account PAT
|
||||
contents: write # for creating a release and uploading release artifacts
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
jobs:
|
||||
major-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.major-version.outputs.version }}
|
||||
steps:
|
||||
- id: major-version
|
||||
run: echo "version=$(echo "${{ inputs.versionNumber }}" | cut -d. -f1)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
changelog-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.changelog-version.outputs.version }}
|
||||
steps:
|
||||
- id: changelog-version
|
||||
run: echo "version=$(echo "${{ inputs.versionNumber }}" | cut -c 2-)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
changelog:
|
||||
needs: changelog-version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations
|
||||
# More details: https://github.com/actions/checkout/blob/b4626ce19ce1106186ddf9bb20e706842f11a7c3/adrs/0153-checkout-v2.md#persist-credentials
|
||||
persist-credentials: false
|
||||
- name: Batch changes
|
||||
uses: miniscruff/changie-action@5036dffa79ffc007110dc7f75eca7ef72780e147 # v2.1.0
|
||||
with:
|
||||
version: latest
|
||||
args: batch ${{ needs.changelog-version.outputs.version }}
|
||||
- name: Merge changes
|
||||
uses: miniscruff/changie-action@5036dffa79ffc007110dc7f75eca7ef72780e147 # v2.1.0
|
||||
with:
|
||||
version: latest
|
||||
args: merge
|
||||
- name: Git push changelog
|
||||
run: |
|
||||
git config --global user.name "${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}"
|
||||
git config --global user.email "${{ vars.TF_DEVEX_CI_COMMIT_EMAIL }}"
|
||||
git add .
|
||||
git commit -a -m "Update changelog"
|
||||
git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
|
||||
|
||||
update-package-version:
|
||||
needs: changelog
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# Default input is the SHA that initially triggered the workflow. As we created a new commit in the previous job,
|
||||
# to ensure we get the latest commit we use the ref for checkout: 'refs/heads/<branch_name>'
|
||||
ref: ${{ github.ref }}
|
||||
# Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations
|
||||
# More details: https://github.com/actions/checkout/blob/b4626ce19ce1106186ddf9bb20e706842f11a7c3/adrs/0153-checkout-v2.md#persist-credentials
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Update package version
|
||||
run: npm version "${{ inputs.versionNumber }}" --git-tag-version false
|
||||
- name: Git push
|
||||
run: |
|
||||
git config --global user.name "${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}"
|
||||
git config --global user.email "${{ vars.TF_DEVEX_CI_COMMIT_EMAIL }}"
|
||||
git add .
|
||||
git commit -a -m "Update package version"
|
||||
git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
|
||||
|
||||
release-tag:
|
||||
needs: [ update-package-version, major-version ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
# Default input is the SHA that initially triggered the workflow. As we created a new commit in the previous job,
|
||||
# to ensure we get the latest commit we use the ref for checkout: 'refs/heads/<branch_name>'
|
||||
ref: ${{ github.ref }}
|
||||
# Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations
|
||||
# More details: https://github.com/actions/checkout/blob/b4626ce19ce1106186ddf9bb20e706842f11a7c3/adrs/0153-checkout-v2.md#persist-credentials
|
||||
persist-credentials: false
|
||||
|
||||
- name: Git push release tag
|
||||
run: |
|
||||
git config --global user.name "${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}"
|
||||
git config --global user.email "${{ vars.TF_DEVEX_CI_COMMIT_EMAIL }}"
|
||||
|
||||
git tag "${{ inputs.versionNumber }}"
|
||||
git tag -f "${{ needs.major-version.outputs.version }}"
|
||||
git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" "${{ inputs.versionNumber }}"
|
||||
git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" -f "${{ needs.major-version.outputs.version }}"
|
||||
|
||||
release:
|
||||
needs: [ changelog-version, release-tag ]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # Needed to create GitHub release
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
ref: ${{ inputs.versionNumber }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Generate Release Notes
|
||||
run: |
|
||||
cd .changes
|
||||
sed -e "1{/# /d;}" -e "2{/^$/d;}" ${{ needs.changelog-version.outputs.version }}.md > /tmp/release-notes.txt
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: GH Release
|
||||
run: |
|
||||
gh release create "${{ inputs.versionNumber }}" --notes-file /tmp/release-notes.txt --title "${{ inputs.versionNumber }}"
|
||||
gh release create "${GITHUB_REF#refs/tags/}" --generate-notes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
|
|
|
|||
131
.github/workflows/setup-terraform.yml
vendored
131
.github/workflows/setup-terraform.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: 'setup-terraform tests'
|
||||
name: 'Setup Terraform'
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
terraform-versions: [0.11.14, latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform - ${{ matrix['terraform-versions'] }}
|
||||
uses: ./
|
||||
|
|
@ -44,7 +44,7 @@ jobs:
|
|||
terraform-versions: [0.11.14, latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform (no wrapper) - ${{ matrix['terraform-versions'] }}
|
||||
uses: ./
|
||||
|
|
@ -69,7 +69,7 @@ jobs:
|
|||
terraform-versions: [~0.12, 0.12.x, <0.13.0]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform - ${{ matrix['terraform-versions'] }}
|
||||
uses: ./
|
||||
|
|
@ -88,7 +88,7 @@ jobs:
|
|||
terraform-versions: [~0.12, 0.12.x, <0.13.0]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform (no wrapper) - ${{ matrix['terraform-versions'] }}
|
||||
uses: ./
|
||||
|
|
@ -100,7 +100,7 @@ jobs:
|
|||
run: terraform version | grep 'Terraform v0\.12'
|
||||
|
||||
terraform-credentials-cloud:
|
||||
name: 'HCP Terraform Credentials'
|
||||
name: 'Terraform Cloud Credentials'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
@ -109,7 +109,7 @@ jobs:
|
|||
TF_CLOUD_API_TOKEN: 'XXXXXXXXXXXXXX.atlasv1.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -138,7 +138,7 @@ jobs:
|
|||
TF_CLOUD_API_TOKEN: 'XXXXXXXXXXXXXX.atlasv1.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -166,7 +166,7 @@ jobs:
|
|||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -189,7 +189,7 @@ jobs:
|
|||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -220,7 +220,7 @@ jobs:
|
|||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -253,26 +253,29 @@ jobs:
|
|||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: ./.github/workflows/data/local
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
||||
- name: Terraform Init
|
||||
shell: bash
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Format
|
||||
shell: bash
|
||||
run: terraform fmt -check
|
||||
|
||||
- name: Terraform Plan
|
||||
id: plan
|
||||
shell: bash
|
||||
run: terraform plan
|
||||
|
||||
- name: Print Terraform Plan
|
||||
shell: bash
|
||||
run: echo "${{ steps.plan.outputs.stdout }}"
|
||||
|
||||
terraform-run-local-no-wrapper:
|
||||
|
|
@ -283,11 +286,10 @@ jobs:
|
|||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: ./.github/workflows/data/local
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
|
|
@ -295,107 +297,14 @@ jobs:
|
|||
terraform_wrapper: false
|
||||
|
||||
- name: Terraform Init
|
||||
shell: bash
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Format
|
||||
shell: bash
|
||||
run: terraform fmt -check
|
||||
|
||||
- name: Terraform Plan
|
||||
id: plan
|
||||
shell: bash
|
||||
run: terraform plan
|
||||
|
||||
terraform-stdout-wrapper:
|
||||
name: 'Terraform STDOUT'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: ./.github/workflows/data/local
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
with:
|
||||
terraform_wrapper: true
|
||||
|
||||
- name: Terraform Init
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Format
|
||||
run: terraform fmt -check
|
||||
|
||||
- name: Terraform Apply
|
||||
id: apply
|
||||
run: terraform apply -auto-approve
|
||||
|
||||
- name: Terraform Output to JQ
|
||||
id: output
|
||||
run: terraform output -json | jq '.pet.value'
|
||||
|
||||
terraform-stdout-no-wrapper:
|
||||
name: 'Terraform STDOUT No Wrapper'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: ./.github/workflows/data/local
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
|
||||
- name: Terraform Init
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Format
|
||||
run: terraform fmt -check
|
||||
|
||||
- name: Terraform Apply
|
||||
id: apply
|
||||
run: terraform apply -auto-approve
|
||||
|
||||
- name: Terraform Output to JQ
|
||||
id: output
|
||||
run: terraform output -json | jq '.pet.value'
|
||||
|
||||
# This test has an artificial delay for testing the streaming of STDOUT
|
||||
terraform-wrapper-delayed-apply:
|
||||
name: 'Terraform Delayed Apply'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: ./.github/workflows/data/delay
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Setup Terraform
|
||||
uses: ./
|
||||
with:
|
||||
terraform_wrapper: true
|
||||
|
||||
- name: Terraform Init
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Format
|
||||
run: terraform fmt -check
|
||||
|
||||
- name: Terraform Apply
|
||||
id: apply
|
||||
run: terraform apply -auto-approve
|
||||
|
|
|
|||
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
_
|
||||
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run build && git add dist/
|
||||
92
CHANGELOG.md
92
CHANGELOG.md
|
|
@ -1,91 +1,3 @@
|
|||
## 3.1.2 (2024-08-19)
|
||||
|
||||
NOTES:
|
||||
|
||||
* This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#430](https://github.com/hashicorp/setup-terraform/issues/430))
|
||||
|
||||
## 3.1.1 (2024-05-07)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* wrapper: Fix wrapper to output to stdout and stderr immediately when data is received ([#395](https://github.com/hashicorp/setup-terraform/issues/395))
|
||||
|
||||
## 3.1.0 (2024-04-23)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* Automatically fallback to darwin/amd64 for Terraform versions before 1.0.2 as releases for darwin/arm64 are not available ([#409](https://github.com/hashicorp/setup-terraform/issues/409))
|
||||
|
||||
## 3.0.0 (2023-10-30)
|
||||
|
||||
NOTES:
|
||||
|
||||
* Updated default runtime to node20 ([#346](https://github.com/hashicorp/setup-terraform/issues/346))
|
||||
* The wrapper around the installed Terraform binary has been fixed to return the exact STDOUT and STDERR from Terraform when executing commands. Previous versions of setup-terraform may have required workarounds to process the STDOUT in bash, such as filtering out the first line or selectively parsing STDOUT with jq. These workarounds may need to be adjusted with `v3.0.0`, which will now return just the STDOUT/STDERR from Terraform with no errant characters/statements. ([#367](https://github.com/hashicorp/setup-terraform/issues/367))
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fixed malformed stdout when wrapper is enabled ([#367](https://github.com/hashicorp/setup-terraform/issues/367))
|
||||
|
||||
# [2.0.3] (2022-11-01)
|
||||
|
||||
### NOTES
|
||||
|
||||
* Reduced occurrences of GitHub Actions warnings for setting output [#247](https://github.com/hashicorp/setup-terraform/pull/247)
|
||||
|
||||
# [2.0.2] (2022-10-12)
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
* Update 2.0.1 release metadata by @jpogran in https://github.com/hashicorp/setup-terraform/pull/253
|
||||
* `README.md` updates - direct links to license and code of conduct, updated GitHub documents link by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/244
|
||||
|
||||
### INTERNAL
|
||||
|
||||
* Bump jest from 29.0.3 to 29.1.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/248
|
||||
|
||||
# [2.0.1] (2022-10-12)
|
||||
|
||||
### ENHANCEMENTS
|
||||
|
||||
* Do not fail when theres an exit-code 2 by @dannyibishev in https://github.com/hashicorp/setup-terraform/pull/125
|
||||
* Updated README to reflect GitHub limitations by @rnsc in https://github.com/hashicorp/setup-terraform/pull/205
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
* Fix terraform extract by @cpc-camarj in https://github.com/hashicorp/setup-terraform/pull/187
|
||||
* Add new-style readme build badges, bump `actions/checkout` in `README.md` examples by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/188
|
||||
* Fixed `master` to `main` workflow branch triggers by @magnetikonline in https://github.com/hashicorp/setup-terraform/pull/216
|
||||
* Fix the example of how to comment on pull request. by @acarmel in https://github.com/hashicorp/setup-terraform/pull/220
|
||||
|
||||
### INTERNAL
|
||||
|
||||
* Bump @actions/core from 1.6.0 to 1.7.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/185
|
||||
* Bump @vercel/ncc from 0.33.3 to 0.33.4 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/182
|
||||
* Bump jest from 27.5.1 to 28.0.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/184
|
||||
* Bump jest from 28.0.0 to 28.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/190
|
||||
* Bump husky from 7.0.4 to 8.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/193
|
||||
* Bump jest from 28.0.3 to 28.1.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/194
|
||||
* Bump @actions/github from 5.0.1 to 5.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/201
|
||||
* Bump @actions/core from 1.7.0 to 1.8.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/200
|
||||
* Bump @actions/tool-cache from 1.7.2 to 2.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/199
|
||||
* TF DevEx: repo adoption by @detro in https://github.com/hashicorp/setup-terraform/pull/204
|
||||
* Bump nock from 13.2.4 to 13.2.6 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/212
|
||||
* Bump @vercel/ncc from 0.33.4 to 0.34.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/210
|
||||
* Bump jest from 28.1.0 to 28.1.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/215
|
||||
* Bump nock from 13.2.6 to 13.2.7 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/217
|
||||
* Bump jest from 28.1.1 to 28.1.2 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/221
|
||||
* Bump jest from 28.1.2 to 28.1.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/224
|
||||
* Bump nock from 13.2.7 to 13.2.9 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/225
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 1.2.1 to 1.3.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/233
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 1.3.0 to 2.0.0 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/243
|
||||
* Bump jest from 28.1.3 to 29.0.3 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/242
|
||||
* Bump @hashicorp/js-releases from 1.5.1 to 1.6.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/226
|
||||
* Bump @actions/core from 1.8.2 to 1.9.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/235
|
||||
* Bump @actions/core from 1.6.0 to 1.9.1 in /wrapper by @dependabot in https://github.com/hashicorp/setup-terraform/pull/236
|
||||
* Bump @actions/github from 5.0.3 to 5.1.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/249
|
||||
* Bump leonsteinhaeuser/project-beta-automations from 2.0.0 to 2.0.1 by @dependabot in https://github.com/hashicorp/setup-terraform/pull/250
|
||||
|
||||
# [2.0.0] (2022-04-18)
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
|
@ -184,9 +96,7 @@ INTERNAL:
|
|||
- Initial release.
|
||||
|
||||
<!-- Links to tag comparisons -->
|
||||
[Unreleased]: https://github.com/hashicorp/setup-terraform/compare/v2.0.2...main
|
||||
[2.0.2]: https://github.com/hashicorp/setup-terraform/compare/v2.0.1...v2.0.2
|
||||
[2.0.1]: https://github.com/hashicorp/setup-terraform/compare/v2.0.0...v2.0.1
|
||||
[Unreleased]: https://github.com/hashicorp/setup-terraform/compare/v2.0.0...main
|
||||
[2.0.0]: https://github.com/hashicorp/setup-terraform/compare/v1.4.0...v2.0.0
|
||||
[1.4.0]: https://github.com/hashicorp/setup-terraform/compare/v1.3.2...v1.4.0
|
||||
[1.3.2]: https://github.com/hashicorp/setup-terraform/compare/v1.3.1...v1.3.2
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,5 +1,3 @@
|
|||
Copyright (c) 2020 HashiCorp, Inc.
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
schema: 1.1
|
||||
|
||||
partition: tf-ecosystem
|
||||
category: github-action
|
||||
|
||||
summary:
|
||||
owner: team-tf-core-plugins
|
||||
description: |
|
||||
Sets up Terraform CLI in your GitHub Actions workflow.
|
||||
visibility: public
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
data_summary:
|
||||
gdpr:
|
||||
exempt: true
|
||||
28
NOTICE
Normal file
28
NOTICE
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Notice
|
||||
|
||||
This project includes code under the following license(s):
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 GitHub, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
62
README.md
62
README.md
|
|
@ -6,36 +6,36 @@
|
|||
The `hashicorp/setup-terraform` action is a JavaScript action that sets up Terraform CLI in your GitHub Actions workflow by:
|
||||
|
||||
- Downloading a specific version of Terraform CLI and adding it to the `PATH`.
|
||||
- Configuring the [Terraform CLI configuration file](https://www.terraform.io/docs/commands/cli-config.html) with a HCP Terraform/Terraform Enterprise hostname and API token.
|
||||
- Configuring the [Terraform CLI configuration file](https://www.terraform.io/docs/commands/cli-config.html) with a Terraform Cloud/Enterprise hostname and API token.
|
||||
- Installing a wrapper script to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. (This can be optionally skipped if subsequent steps in the same job do not need to access the results of Terraform commands.)
|
||||
|
||||
After you've used the action, subsequent steps in the same job can run arbitrary Terraform commands using [the GitHub Actions `run` syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun). This allows most Terraform commands to work exactly like they do on your local command line.
|
||||
After you've used the action, subsequent steps in the same job can run arbitrary Terraform commands using [the GitHub Actions `run` syntax](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsrun). This allows most Terraform commands to work exactly like they do on your local command line.
|
||||
|
||||
## Usage
|
||||
|
||||
This action can be run on `ubuntu-latest`, `windows-latest`, and `macos-latest` GitHub Actions runners. When running on `windows-latest` the shell should be set to Bash. When running on self-hosted GitHub Actions runners, NodeJS must be previously installed with the version specified in the [`action.yml`](https://github.com/hashicorp/setup-terraform/blob/main/action.yml).
|
||||
This action can be run on `ubuntu-latest`, `windows-latest`, and `macos-latest` GitHub Actions runners. When running on `windows-latest` the shell should be set to Bash.
|
||||
|
||||
The default configuration installs the latest version of Terraform CLI and installs the wrapper script to wrap subsequent calls to the `terraform` binary:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
```
|
||||
|
||||
A specific version of Terraform CLI can be installed:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
with:
|
||||
terraform_version: "1.1.7"
|
||||
terraform_version: 1.1.7
|
||||
```
|
||||
|
||||
Credentials for HCP Terraform ([app.terraform.io](https://app.terraform.io/)) can be configured:
|
||||
Credentials for Terraform Cloud ([app.terraform.io](https://app.terraform.io/)) can be configured:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
with:
|
||||
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
|
||||
```
|
||||
|
|
@ -44,7 +44,7 @@ Credentials for Terraform Enterprise (TFE) can be configured:
|
|||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
with:
|
||||
cli_config_credentials_hostname: 'terraform.example.com'
|
||||
cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
|
||||
|
|
@ -54,7 +54,7 @@ The wrapper script installation can be skipped by setting the `terraform_wrapper
|
|||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
with:
|
||||
terraform_wrapper: false
|
||||
```
|
||||
|
|
@ -63,7 +63,7 @@ Subsequent steps can access outputs when the wrapper script is installed:
|
|||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
|
||||
- run: terraform init
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ Outputs can be used in subsequent steps to comment on the pull request:
|
|||
>
|
||||
> Due to that limitation, you might end up with a failed workflow run even if the plan succeeded.
|
||||
>
|
||||
> Another approach is to append your plan into the $GITHUB_STEP_SUMMARY environment variable which supports markdown.
|
||||
> Another approach is to append your plan into the $GITHUB_JOB_SUMMARY environment variable which supports markdown.
|
||||
|
||||
```yaml
|
||||
defaults:
|
||||
|
|
@ -90,8 +90,8 @@ defaults:
|
|||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
|
||||
- name: Terraform fmt
|
||||
id: fmt
|
||||
|
|
@ -100,7 +100,7 @@ steps:
|
|||
|
||||
- name: Terraform Init
|
||||
id: init
|
||||
run: terraform init -input=false
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Validate
|
||||
id: validate
|
||||
|
|
@ -108,10 +108,10 @@ steps:
|
|||
|
||||
- name: Terraform Plan
|
||||
id: plan
|
||||
run: terraform plan -no-color -input=false
|
||||
run: terraform plan -no-color
|
||||
continue-on-error: true
|
||||
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@v6
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
|
||||
|
|
@ -158,8 +158,8 @@ defaults:
|
|||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
- uses: actions/checkout@v3
|
||||
- uses: hashicorp/setup-terraform@v2
|
||||
|
||||
- name: Terraform fmt
|
||||
id: fmt
|
||||
|
|
@ -168,7 +168,7 @@ steps:
|
|||
|
||||
- name: Terraform Init
|
||||
id: init
|
||||
run: terraform init -input=false
|
||||
run: terraform init
|
||||
|
||||
- name: Terraform Validate
|
||||
id: validate
|
||||
|
|
@ -176,10 +176,10 @@ steps:
|
|||
|
||||
- name: Terraform Plan
|
||||
id: plan
|
||||
run: terraform plan -no-color -input=false
|
||||
run: terraform plan -no-color
|
||||
continue-on-error: true
|
||||
|
||||
- uses: actions/github-script@v7
|
||||
- uses: actions/github-script@v6
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
|
||||
|
|
@ -242,13 +242,13 @@ steps:
|
|||
|
||||
The action supports the following inputs:
|
||||
|
||||
- `cli_config_credentials_hostname` - (optional) The hostname of a HCP Terraform/Terraform Enterprise instance to
|
||||
- `cli_config_credentials_hostname` - (optional) The hostname of a Terraform Cloud/Enterprise instance to
|
||||
place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.
|
||||
- `cli_config_credentials_token` - (optional) The API token for a HCP Terraform/Terraform Enterprise instance to
|
||||
- `cli_config_credentials_token` - (optional) The API token for a Terraform Cloud/Enterprise instance to
|
||||
place within the credentials block of the Terraform CLI configuration file.
|
||||
- `terraform_version` - (optional) The version of Terraform CLI to install. Instead of a full version string,
|
||||
you can also specify a constraint string (see [Semver Ranges](https://www.npmjs.com/package/semver#ranges)
|
||||
for available range specifications). Examples are: `"<1.2.0"`, `"~1.1.0"`, `"1.1.7"` (all three installing
|
||||
for available range specifications). Examples are: `<1.2.0`, `~1.1.0`, `1.1.7` (all three installing
|
||||
the latest available `1.1` version). Prerelease versions can be specified and a range will stay within the
|
||||
given tag such as `beta` or `rc`. If no version is given, it will default to `latest`.
|
||||
- `terraform_wrapper` - (optional) Whether to install a wrapper to wrap subsequent calls of
|
||||
|
|
@ -266,20 +266,12 @@ to `true`, the following outputs are available for subsequent steps that call th
|
|||
|
||||
## License
|
||||
|
||||
[Mozilla Public License v2.0](LICENSE)
|
||||
[Mozilla Public License v2.0](https://github.com/hashicorp/setup-terraform/blob/master/LICENSE)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
[Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
[Code of Conduct](https://github.com/hashicorp/setup-terraform/blob/master/CODE_OF_CONDUCT.md)
|
||||
|
||||
## Experimental Status
|
||||
|
||||
By using the software in this repository (the "Software"), you acknowledge that: (1) the Software is still in development, may change, and has not been released as a commercial product by HashiCorp and is not currently supported in any way by HashiCorp; (2) the Software is provided on an "as-is" basis, and may include bugs, errors, or other issues; (3) the Software is NOT INTENDED FOR PRODUCTION USE, use of the Software may result in unexpected results, loss of data, or other unexpected results, and HashiCorp disclaims any and all liability resulting from use of the Software; and (4) HashiCorp reserves all rights to make all decisions about the features, functionality and commercial release (or non-release) of the Software, at any time and without any obligation or liability whatsoever.
|
||||
|
||||
## Contributing
|
||||
|
||||
### License Headers
|
||||
|
||||
All source code files (excluding autogenerated files like `package.json`, prose, and files excluded in [.copywrite.hcl](.copywrite.hcl)) must have a license header at the top.
|
||||
|
||||
This can be autogenerated by installing the HashiCorp [`copywrite`](https://github.com/hashicorp/copywrite#getting-started) tool and running `copywrite headers` in the root of the repository.
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ description: 'Sets up Terraform CLI in your GitHub Actions workflow.'
|
|||
author: 'HashiCorp, Inc.'
|
||||
inputs:
|
||||
cli_config_credentials_hostname:
|
||||
description: 'The hostname of a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.'
|
||||
description: 'The hostname of a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.'
|
||||
default: 'app.terraform.io'
|
||||
required: false
|
||||
cli_config_credentials_token:
|
||||
description: 'The API token for a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file.'
|
||||
description: 'The API token for a Terraform Cloud/Enterprise instance to place within the credentials block of the Terraform CLI configuration file.'
|
||||
required: false
|
||||
terraform_version:
|
||||
description: 'The version of Terraform CLI to install. Instead of full version string you can also specify constraint string starting with "<" (for example `<1.13.0`) to install the latest version satisfying the constraint. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.'
|
||||
|
|
@ -18,7 +18,7 @@ inputs:
|
|||
default: 'true'
|
||||
required: false
|
||||
runs:
|
||||
using: 'node20'
|
||||
using: 'node16'
|
||||
main: 'dist/index.js'
|
||||
branding:
|
||||
icon: 'terminal'
|
||||
|
|
|
|||
1000
dist/bridge.js
vendored
Normal file
1000
dist/bridge.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
977
dist/events.js
vendored
Normal file
977
dist/events.js
vendored
Normal file
|
|
@ -0,0 +1,977 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Modified by the vm2 team to make this a standalone module to be loaded into the sandbox.
|
||||
|
||||
'use strict';
|
||||
|
||||
const host = fromhost;
|
||||
|
||||
const {
|
||||
Boolean,
|
||||
Error,
|
||||
String,
|
||||
Symbol
|
||||
} = globalThis;
|
||||
|
||||
const ReflectApply = Reflect.apply;
|
||||
const ReflectOwnKeys = Reflect.ownKeys;
|
||||
|
||||
const ErrorCaptureStackTrace = Error.captureStackTrace;
|
||||
|
||||
const NumberIsNaN = Number.isNaN;
|
||||
|
||||
const ObjectCreate = Object.create;
|
||||
const ObjectDefineProperty = Object.defineProperty;
|
||||
const ObjectDefineProperties = Object.defineProperties;
|
||||
const ObjectGetPrototypeOf = Object.getPrototypeOf;
|
||||
|
||||
const SymbolFor = Symbol.for;
|
||||
|
||||
function uncurryThis(func) {
|
||||
return (thiz, ...args) => ReflectApply(func, thiz, args);
|
||||
}
|
||||
|
||||
const ArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
|
||||
const ArrayPrototypeJoin = uncurryThis(Array.prototype.join);
|
||||
const ArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
|
||||
const ArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
|
||||
const ArrayPrototypeUnshift = uncurryThis(Array.prototype.unshift);
|
||||
|
||||
const kRejection = SymbolFor('nodejs.rejection');
|
||||
|
||||
function inspect(obj) {
|
||||
return typeof obj === 'symbol' ? obj.toString() : `${obj}`;
|
||||
}
|
||||
|
||||
function spliceOne(list, index) {
|
||||
for (; index + 1 < list.length; index++)
|
||||
list[index] = list[index + 1];
|
||||
list.pop();
|
||||
}
|
||||
|
||||
function assert(what, message) {
|
||||
if (!what) throw new Error(message);
|
||||
}
|
||||
|
||||
function E(key, msg, Base) {
|
||||
return function NodeError(...args) {
|
||||
const error = new Base();
|
||||
const message = ReflectApply(msg, error, args);
|
||||
ObjectDefineProperties(error, {
|
||||
message: {
|
||||
value: message,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
},
|
||||
toString: {
|
||||
value() {
|
||||
return `${this.name} [${key}]: ${this.message}`;
|
||||
},
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
},
|
||||
});
|
||||
error.code = key;
|
||||
return error;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const ERR_INVALID_ARG_TYPE = E('ERR_INVALID_ARG_TYPE',
|
||||
(name, expected, actual) => {
|
||||
assert(typeof name === 'string', "'name' must be a string");
|
||||
if (!ArrayIsArray(expected)) {
|
||||
expected = [expected];
|
||||
}
|
||||
|
||||
let msg = 'The ';
|
||||
if (StringPrototypeEndsWith(name, ' argument')) {
|
||||
// For cases like 'first argument'
|
||||
msg += `${name} `;
|
||||
} else {
|
||||
const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
|
||||
msg += `"${name}" ${type} `;
|
||||
}
|
||||
msg += 'must be ';
|
||||
|
||||
const types = [];
|
||||
const instances = [];
|
||||
const other = [];
|
||||
|
||||
for (const value of expected) {
|
||||
assert(typeof value === 'string',
|
||||
'All expected entries have to be of type string');
|
||||
if (ArrayPrototypeIncludes(kTypes, value)) {
|
||||
ArrayPrototypePush(types, StringPrototypeToLowerCase(value));
|
||||
} else if (RegExpPrototypeTest(classRegExp, value)) {
|
||||
ArrayPrototypePush(instances, value);
|
||||
} else {
|
||||
assert(value !== 'object',
|
||||
'The value "object" should be written as "Object"');
|
||||
ArrayPrototypePush(other, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Special handle `object` in case other instances are allowed to outline
|
||||
// the differences between each other.
|
||||
if (instances.length > 0) {
|
||||
const pos = ArrayPrototypeIndexOf(types, 'object');
|
||||
if (pos !== -1) {
|
||||
ArrayPrototypeSplice(types, pos, 1);
|
||||
ArrayPrototypePush(instances, 'Object');
|
||||
}
|
||||
}
|
||||
|
||||
if (types.length > 0) {
|
||||
if (types.length > 2) {
|
||||
const last = ArrayPrototypePop(types);
|
||||
msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`;
|
||||
} else if (types.length === 2) {
|
||||
msg += `one of type ${types[0]} or ${types[1]}`;
|
||||
} else {
|
||||
msg += `of type ${types[0]}`;
|
||||
}
|
||||
if (instances.length > 0 || other.length > 0)
|
||||
msg += ' or ';
|
||||
}
|
||||
|
||||
if (instances.length > 0) {
|
||||
if (instances.length > 2) {
|
||||
const last = ArrayPrototypePop(instances);
|
||||
msg +=
|
||||
`an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`;
|
||||
} else {
|
||||
msg += `an instance of ${instances[0]}`;
|
||||
if (instances.length === 2) {
|
||||
msg += ` or ${instances[1]}`;
|
||||
}
|
||||
}
|
||||
if (other.length > 0)
|
||||
msg += ' or ';
|
||||
}
|
||||
|
||||
if (other.length > 0) {
|
||||
if (other.length > 2) {
|
||||
const last = ArrayPrototypePop(other);
|
||||
msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`;
|
||||
} else if (other.length === 2) {
|
||||
msg += `one of ${other[0]} or ${other[1]}`;
|
||||
} else {
|
||||
if (StringPrototypeToLowerCase(other[0]) !== other[0])
|
||||
msg += 'an ';
|
||||
msg += `${other[0]}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (actual == null) {
|
||||
msg += `. Received ${actual}`;
|
||||
} else if (typeof actual === 'function' && actual.name) {
|
||||
msg += `. Received function ${actual.name}`;
|
||||
} else if (typeof actual === 'object') {
|
||||
if (actual.constructor && actual.constructor.name) {
|
||||
msg += `. Received an instance of ${actual.constructor.name}`;
|
||||
} else {
|
||||
const inspected = inspect(actual, { depth: -1 });
|
||||
msg += `. Received ${inspected}`;
|
||||
}
|
||||
} else {
|
||||
let inspected = inspect(actual, { colors: false });
|
||||
if (inspected.length > 25)
|
||||
inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`;
|
||||
msg += `. Received type ${typeof actual} (${inspected})`;
|
||||
}
|
||||
return msg;
|
||||
}, TypeError);
|
||||
|
||||
const ERR_INVALID_THIS = E('ERR_INVALID_THIS', s => `Value of "this" must be of type ${s}`, TypeError);
|
||||
|
||||
const ERR_OUT_OF_RANGE = E('ERR_OUT_OF_RANGE',
|
||||
(str, range, input, replaceDefaultBoolean = false) => {
|
||||
assert(range, 'Missing "range" argument');
|
||||
let msg = replaceDefaultBoolean ? str :
|
||||
`The value of "${str}" is out of range.`;
|
||||
const received = inspect(input);
|
||||
msg += ` It must be ${range}. Received ${received}`;
|
||||
return msg;
|
||||
}, RangeError);
|
||||
|
||||
const ERR_UNHANDLED_ERROR = E('ERR_UNHANDLED_ERROR',
|
||||
err => {
|
||||
const msg = 'Unhandled error.';
|
||||
if (err === undefined) return msg;
|
||||
return `${msg} (${err})`;
|
||||
}, Error);
|
||||
|
||||
function validateBoolean(value, name) {
|
||||
if (typeof value !== 'boolean')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
|
||||
}
|
||||
|
||||
function validateFunction(value, name) {
|
||||
if (typeof value !== 'function')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
|
||||
}
|
||||
|
||||
function validateString(value, name) {
|
||||
if (typeof value !== 'string')
|
||||
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
|
||||
}
|
||||
|
||||
function nc(cond, e) {
|
||||
return cond === undefined || cond === null ? e : cond;
|
||||
}
|
||||
|
||||
function oc(base, key) {
|
||||
return base === undefined || base === null ? undefined : base[key];
|
||||
}
|
||||
|
||||
const kCapture = Symbol('kCapture');
|
||||
const kErrorMonitor = host.kErrorMonitor || Symbol('events.errorMonitor');
|
||||
const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
|
||||
const kMaxEventTargetListenersWarned =
|
||||
Symbol('events.maxEventTargetListenersWarned');
|
||||
|
||||
const kIsEventTarget = SymbolFor('nodejs.event_target');
|
||||
|
||||
function isEventTarget(obj) {
|
||||
return oc(oc(obj, 'constructor'), kIsEventTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `EventEmitter` instance.
|
||||
* @param {{ captureRejections?: boolean; }} [opts]
|
||||
* @constructs {EventEmitter}
|
||||
*/
|
||||
function EventEmitter(opts) {
|
||||
EventEmitter.init.call(this, opts);
|
||||
}
|
||||
module.exports = EventEmitter;
|
||||
if (host.once) module.exports.once = host.once;
|
||||
if (host.on) module.exports.on = host.on;
|
||||
if (host.getEventListeners) module.exports.getEventListeners = host.getEventListeners;
|
||||
// Backwards-compat with node 0.10.x
|
||||
EventEmitter.EventEmitter = EventEmitter;
|
||||
|
||||
EventEmitter.usingDomains = false;
|
||||
|
||||
EventEmitter.captureRejectionSymbol = kRejection;
|
||||
ObjectDefineProperty(EventEmitter, 'captureRejections', {
|
||||
get() {
|
||||
return EventEmitter.prototype[kCapture];
|
||||
},
|
||||
set(value) {
|
||||
validateBoolean(value, 'EventEmitter.captureRejections');
|
||||
|
||||
EventEmitter.prototype[kCapture] = value;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
if (host.EventEmitterReferencingAsyncResource) {
|
||||
const kAsyncResource = Symbol('kAsyncResource');
|
||||
const EventEmitterReferencingAsyncResource = host.EventEmitterReferencingAsyncResource;
|
||||
|
||||
class EventEmitterAsyncResource extends EventEmitter {
|
||||
/**
|
||||
* @param {{
|
||||
* name?: string,
|
||||
* triggerAsyncId?: number,
|
||||
* requireManualDestroy?: boolean,
|
||||
* }} [options]
|
||||
*/
|
||||
constructor(options = undefined) {
|
||||
let name;
|
||||
if (typeof options === 'string') {
|
||||
name = options;
|
||||
options = undefined;
|
||||
} else {
|
||||
if (new.target === EventEmitterAsyncResource) {
|
||||
validateString(oc(options, 'name'), 'options.name');
|
||||
}
|
||||
name = oc(options, 'name') || new.target.name;
|
||||
}
|
||||
super(options);
|
||||
|
||||
this[kAsyncResource] =
|
||||
new EventEmitterReferencingAsyncResource(this, name, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {symbol,string} event
|
||||
* @param {...any} args
|
||||
* @returns {boolean}
|
||||
*/
|
||||
emit(event, ...args) {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
const { asyncResource } = this;
|
||||
ArrayPrototypeUnshift(args, super.emit, this, event);
|
||||
return ReflectApply(asyncResource.runInAsyncScope, asyncResource,
|
||||
args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
emitDestroy() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
this.asyncResource.emitDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get asyncId() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this.asyncResource.asyncId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
get triggerAsyncId() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this.asyncResource.triggerAsyncId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {EventEmitterReferencingAsyncResource}
|
||||
*/
|
||||
get asyncResource() {
|
||||
if (this[kAsyncResource] === undefined)
|
||||
throw new ERR_INVALID_THIS('EventEmitterAsyncResource');
|
||||
return this[kAsyncResource];
|
||||
}
|
||||
}
|
||||
EventEmitter.EventEmitterAsyncResource = EventEmitterAsyncResource;
|
||||
}
|
||||
|
||||
EventEmitter.errorMonitor = kErrorMonitor;
|
||||
|
||||
// The default for captureRejections is false
|
||||
ObjectDefineProperty(EventEmitter.prototype, kCapture, {
|
||||
value: false,
|
||||
writable: true,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
EventEmitter.prototype._events = undefined;
|
||||
EventEmitter.prototype._eventsCount = 0;
|
||||
EventEmitter.prototype._maxListeners = undefined;
|
||||
|
||||
// By default EventEmitters will print a warning if more than 10 listeners are
|
||||
// added to it. This is a useful default which helps finding memory leaks.
|
||||
let defaultMaxListeners = 10;
|
||||
|
||||
function checkListener(listener) {
|
||||
validateFunction(listener, 'listener');
|
||||
}
|
||||
|
||||
ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return defaultMaxListeners;
|
||||
},
|
||||
set: function(arg) {
|
||||
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
|
||||
throw new ERR_OUT_OF_RANGE('defaultMaxListeners',
|
||||
'a non-negative number',
|
||||
arg);
|
||||
}
|
||||
defaultMaxListeners = arg;
|
||||
}
|
||||
});
|
||||
|
||||
ObjectDefineProperties(EventEmitter, {
|
||||
kMaxEventTargetListeners: {
|
||||
value: kMaxEventTargetListeners,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
},
|
||||
kMaxEventTargetListenersWarned: {
|
||||
value: kMaxEventTargetListenersWarned,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets the max listeners.
|
||||
* @param {number} n
|
||||
* @param {EventTarget[] | EventEmitter[]} [eventTargets]
|
||||
* @returns {void}
|
||||
*/
|
||||
EventEmitter.setMaxListeners =
|
||||
function(n = defaultMaxListeners, ...eventTargets) {
|
||||
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n))
|
||||
throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
|
||||
if (eventTargets.length === 0) {
|
||||
defaultMaxListeners = n;
|
||||
} else {
|
||||
for (let i = 0; i < eventTargets.length; i++) {
|
||||
const target = eventTargets[i];
|
||||
if (isEventTarget(target)) {
|
||||
target[kMaxEventTargetListeners] = n;
|
||||
target[kMaxEventTargetListenersWarned] = false;
|
||||
} else if (typeof target.setMaxListeners === 'function') {
|
||||
target.setMaxListeners(n);
|
||||
} else {
|
||||
throw new ERR_INVALID_ARG_TYPE(
|
||||
'eventTargets',
|
||||
['EventEmitter', 'EventTarget'],
|
||||
target);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If you're updating this function definition, please also update any
|
||||
// re-definitions, such as the one in the Domain module (lib/domain.js).
|
||||
EventEmitter.init = function(opts) {
|
||||
|
||||
if (this._events === undefined ||
|
||||
this._events === ObjectGetPrototypeOf(this)._events) {
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
this._maxListeners = this._maxListeners || undefined;
|
||||
|
||||
|
||||
if (oc(opts, 'captureRejections')) {
|
||||
validateBoolean(opts.captureRejections, 'options.captureRejections');
|
||||
this[kCapture] = Boolean(opts.captureRejections);
|
||||
} else {
|
||||
// Assigning the kCapture property directly saves an expensive
|
||||
// prototype lookup in a very sensitive hot path.
|
||||
this[kCapture] = EventEmitter.prototype[kCapture];
|
||||
}
|
||||
};
|
||||
|
||||
function addCatch(that, promise, type, args) {
|
||||
if (!that[kCapture]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Promises/A+ spec, then could be a getter
|
||||
// that throws on second use.
|
||||
try {
|
||||
const then = promise.then;
|
||||
|
||||
if (typeof then === 'function') {
|
||||
then.call(promise, undefined, function(err) {
|
||||
// The callback is called with nextTick to avoid a follow-up
|
||||
// rejection from this promise.
|
||||
process.nextTick(emitUnhandledRejectionOrErr, that, err, type, args);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
that.emit('error', err);
|
||||
}
|
||||
}
|
||||
|
||||
function emitUnhandledRejectionOrErr(ee, err, type, args) {
|
||||
if (typeof ee[kRejection] === 'function') {
|
||||
ee[kRejection](err, type, ...args);
|
||||
} else {
|
||||
// We have to disable the capture rejections mechanism, otherwise
|
||||
// we might end up in an infinite loop.
|
||||
const prev = ee[kCapture];
|
||||
|
||||
// If the error handler throws, it is not catchable and it
|
||||
// will end up in 'uncaughtException'. We restore the previous
|
||||
// value of kCapture in case the uncaughtException is present
|
||||
// and the exception is handled.
|
||||
try {
|
||||
ee[kCapture] = false;
|
||||
ee.emit('error', err);
|
||||
} finally {
|
||||
ee[kCapture] = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the max listeners of the event emitter.
|
||||
* @param {number} n
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
||||
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
|
||||
throw new ERR_OUT_OF_RANGE('n', 'a non-negative number', n);
|
||||
}
|
||||
this._maxListeners = n;
|
||||
return this;
|
||||
};
|
||||
|
||||
function _getMaxListeners(that) {
|
||||
if (that._maxListeners === undefined)
|
||||
return EventEmitter.defaultMaxListeners;
|
||||
return that._maxListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current max listener value for the event emitter.
|
||||
* @returns {number}
|
||||
*/
|
||||
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
||||
return _getMaxListeners(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Synchronously calls each of the listeners registered
|
||||
* for the event.
|
||||
* @param {string | symbol} type
|
||||
* @param {...any} [args]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
EventEmitter.prototype.emit = function emit(type, ...args) {
|
||||
let doError = (type === 'error');
|
||||
|
||||
const events = this._events;
|
||||
if (events !== undefined) {
|
||||
if (doError && events[kErrorMonitor] !== undefined)
|
||||
this.emit(kErrorMonitor, ...args);
|
||||
doError = (doError && events.error === undefined);
|
||||
} else if (!doError)
|
||||
return false;
|
||||
|
||||
// If there is no 'error' event listener then throw.
|
||||
if (doError) {
|
||||
let er;
|
||||
if (args.length > 0)
|
||||
er = args[0];
|
||||
if (er instanceof Error) {
|
||||
try {
|
||||
const capture = {};
|
||||
ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
|
||||
} catch (e) {}
|
||||
|
||||
// Note: The comments on the `throw` lines are intentional, they show
|
||||
// up in Node's output if this results in an unhandled exception.
|
||||
throw er; // Unhandled 'error' event
|
||||
}
|
||||
|
||||
let stringifiedEr;
|
||||
try {
|
||||
stringifiedEr = inspect(er);
|
||||
} catch (e) {
|
||||
stringifiedEr = er;
|
||||
}
|
||||
|
||||
// At least give some kind of context to the user
|
||||
const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
|
||||
err.context = er;
|
||||
throw err; // Unhandled 'error' event
|
||||
}
|
||||
|
||||
const handler = events[type];
|
||||
|
||||
if (handler === undefined)
|
||||
return false;
|
||||
|
||||
if (typeof handler === 'function') {
|
||||
const result = handler.apply(this, args);
|
||||
|
||||
// We check if result is undefined first because that
|
||||
// is the most common case so we do not pay any perf
|
||||
// penalty
|
||||
if (result !== undefined && result !== null) {
|
||||
addCatch(this, result, type, args);
|
||||
}
|
||||
} else {
|
||||
const len = handler.length;
|
||||
const listeners = arrayClone(handler);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const result = listeners[i].apply(this, args);
|
||||
|
||||
// We check if result is undefined first because that
|
||||
// is the most common case so we do not pay any perf
|
||||
// penalty.
|
||||
// This code is duplicated because extracting it away
|
||||
// would make it non-inlineable.
|
||||
if (result !== undefined && result !== null) {
|
||||
addCatch(this, result, type, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
function _addListener(target, type, listener, prepend) {
|
||||
let m;
|
||||
let events;
|
||||
let existing;
|
||||
|
||||
checkListener(listener);
|
||||
|
||||
events = target._events;
|
||||
if (events === undefined) {
|
||||
events = target._events = ObjectCreate(null);
|
||||
target._eventsCount = 0;
|
||||
} else {
|
||||
// To avoid recursion in the case that type === "newListener"! Before
|
||||
// adding it to the listeners, first emit "newListener".
|
||||
if (events.newListener !== undefined) {
|
||||
target.emit('newListener', type,
|
||||
nc(listener.listener, listener));
|
||||
|
||||
// Re-assign `events` because a newListener handler could have caused the
|
||||
// this._events to be assigned to a new object
|
||||
events = target._events;
|
||||
}
|
||||
existing = events[type];
|
||||
}
|
||||
|
||||
if (existing === undefined) {
|
||||
// Optimize the case of one listener. Don't need the extra array object.
|
||||
events[type] = listener;
|
||||
++target._eventsCount;
|
||||
} else {
|
||||
if (typeof existing === 'function') {
|
||||
// Adding the second element, need to change to array.
|
||||
existing = events[type] =
|
||||
prepend ? [listener, existing] : [existing, listener];
|
||||
// If we've already got an array, just append.
|
||||
} else if (prepend) {
|
||||
existing.unshift(listener);
|
||||
} else {
|
||||
existing.push(listener);
|
||||
}
|
||||
|
||||
// Check for listener leak
|
||||
m = _getMaxListeners(target);
|
||||
if (m > 0 && existing.length > m && !existing.warned) {
|
||||
existing.warned = true;
|
||||
// No error code for this since it is a Warning
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const w = new Error('Possible EventEmitter memory leak detected. ' +
|
||||
`${existing.length} ${String(type)} listeners ` +
|
||||
`added to ${inspect(target, { depth: -1 })}. Use ` +
|
||||
'emitter.setMaxListeners() to increase limit');
|
||||
w.name = 'MaxListenersExceededWarning';
|
||||
w.emitter = target;
|
||||
w.type = type;
|
||||
w.count = existing.length;
|
||||
process.emitWarning(w);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to the event emitter.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.addListener = function addListener(type, listener) {
|
||||
return _addListener(this, type, listener, false);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
||||
|
||||
/**
|
||||
* Adds the `listener` function to the beginning of
|
||||
* the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.prependListener =
|
||||
function prependListener(type, listener) {
|
||||
return _addListener(this, type, listener, true);
|
||||
};
|
||||
|
||||
function onceWrapper() {
|
||||
if (!this.fired) {
|
||||
this.target.removeListener(this.type, this.wrapFn);
|
||||
this.fired = true;
|
||||
if (arguments.length === 0)
|
||||
return this.listener.call(this.target);
|
||||
return this.listener.apply(this.target, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
function _onceWrap(target, type, listener) {
|
||||
const state = { fired: false, wrapFn: undefined, target, type, listener };
|
||||
const wrapped = onceWrapper.bind(state);
|
||||
wrapped.listener = listener;
|
||||
state.wrapFn = wrapped;
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a one-time `listener` function to the event emitter.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.once = function once(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
this.on(type, _onceWrap(this, type, listener));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a one-time `listener` function to the beginning of
|
||||
* the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.prependOnceListener =
|
||||
function prependOnceListener(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
this.prependListener(type, _onceWrap(this, type, listener));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes the specified `listener` from the listeners array.
|
||||
* @param {string | symbol} type
|
||||
* @param {Function} listener
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.removeListener =
|
||||
function removeListener(type, listener) {
|
||||
checkListener(listener);
|
||||
|
||||
const events = this._events;
|
||||
if (events === undefined)
|
||||
return this;
|
||||
|
||||
const list = events[type];
|
||||
if (list === undefined)
|
||||
return this;
|
||||
|
||||
if (list === listener || list.listener === listener) {
|
||||
if (--this._eventsCount === 0)
|
||||
this._events = ObjectCreate(null);
|
||||
else {
|
||||
delete events[type];
|
||||
if (events.removeListener)
|
||||
this.emit('removeListener', type, list.listener || listener);
|
||||
}
|
||||
} else if (typeof list !== 'function') {
|
||||
let position = -1;
|
||||
|
||||
for (let i = list.length - 1; i >= 0; i--) {
|
||||
if (list[i] === listener || list[i].listener === listener) {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (position < 0)
|
||||
return this;
|
||||
|
||||
if (position === 0)
|
||||
list.shift();
|
||||
else {
|
||||
spliceOne(list, position);
|
||||
}
|
||||
|
||||
if (list.length === 1)
|
||||
events[type] = list[0];
|
||||
|
||||
if (events.removeListener !== undefined)
|
||||
this.emit('removeListener', type, listener);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
|
||||
/**
|
||||
* Removes all listeners from the event emitter. (Only
|
||||
* removes listeners for a specific event name if specified
|
||||
* as `type`).
|
||||
* @param {string | symbol} [type]
|
||||
* @returns {EventEmitter}
|
||||
*/
|
||||
EventEmitter.prototype.removeAllListeners =
|
||||
function removeAllListeners(type) {
|
||||
const events = this._events;
|
||||
if (events === undefined)
|
||||
return this;
|
||||
|
||||
// Not listening for removeListener, no need to emit
|
||||
if (events.removeListener === undefined) {
|
||||
if (arguments.length === 0) {
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
} else if (events[type] !== undefined) {
|
||||
if (--this._eventsCount === 0)
|
||||
this._events = ObjectCreate(null);
|
||||
else
|
||||
delete events[type];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Emit removeListener for all listeners on all events
|
||||
if (arguments.length === 0) {
|
||||
for (const key of ReflectOwnKeys(events)) {
|
||||
if (key === 'removeListener') continue;
|
||||
this.removeAllListeners(key);
|
||||
}
|
||||
this.removeAllListeners('removeListener');
|
||||
this._events = ObjectCreate(null);
|
||||
this._eventsCount = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
const listeners = events[type];
|
||||
|
||||
if (typeof listeners === 'function') {
|
||||
this.removeListener(type, listeners);
|
||||
} else if (listeners !== undefined) {
|
||||
// LIFO order
|
||||
for (let i = listeners.length - 1; i >= 0; i--) {
|
||||
this.removeListener(type, listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
function _listeners(target, type, unwrap) {
|
||||
const events = target._events;
|
||||
|
||||
if (events === undefined)
|
||||
return [];
|
||||
|
||||
const evlistener = events[type];
|
||||
if (evlistener === undefined)
|
||||
return [];
|
||||
|
||||
if (typeof evlistener === 'function')
|
||||
return unwrap ? [evlistener.listener || evlistener] : [evlistener];
|
||||
|
||||
return unwrap ?
|
||||
unwrapListeners(evlistener) : arrayClone(evlistener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the array of listeners for the event name
|
||||
* specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {Function[]}
|
||||
*/
|
||||
EventEmitter.prototype.listeners = function listeners(type) {
|
||||
return _listeners(this, type, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a copy of the array of listeners and wrappers for
|
||||
* the event name specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {Function[]}
|
||||
*/
|
||||
EventEmitter.prototype.rawListeners = function rawListeners(type) {
|
||||
return _listeners(this, type, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of listeners listening to the event name
|
||||
* specified as `type`.
|
||||
* @deprecated since v3.2.0
|
||||
* @param {EventEmitter} emitter
|
||||
* @param {string | symbol} type
|
||||
* @returns {number}
|
||||
*/
|
||||
EventEmitter.listenerCount = function(emitter, type) {
|
||||
if (typeof emitter.listenerCount === 'function') {
|
||||
return emitter.listenerCount(type);
|
||||
}
|
||||
return emitter.listenerCount(type);
|
||||
};
|
||||
|
||||
EventEmitter.prototype.listenerCount = listenerCount;
|
||||
|
||||
/**
|
||||
* Returns the number of listeners listening to event name
|
||||
* specified as `type`.
|
||||
* @param {string | symbol} type
|
||||
* @returns {number}
|
||||
*/
|
||||
function listenerCount(type) {
|
||||
const events = this._events;
|
||||
|
||||
if (events !== undefined) {
|
||||
const evlistener = events[type];
|
||||
|
||||
if (typeof evlistener === 'function') {
|
||||
return 1;
|
||||
} else if (evlistener !== undefined) {
|
||||
return evlistener.length;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array listing the events for which
|
||||
* the emitter has registered listeners.
|
||||
* @returns {any[]}
|
||||
*/
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
|
||||
};
|
||||
|
||||
function arrayClone(arr) {
|
||||
// At least since V8 8.3, this implementation is faster than the previous
|
||||
// which always used a simple for-loop
|
||||
switch (arr.length) {
|
||||
case 2: return [arr[0], arr[1]];
|
||||
case 3: return [arr[0], arr[1], arr[2]];
|
||||
case 4: return [arr[0], arr[1], arr[2], arr[3]];
|
||||
case 5: return [arr[0], arr[1], arr[2], arr[3], arr[4]];
|
||||
case 6: return [arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]];
|
||||
}
|
||||
return ArrayPrototypeSlice(arr);
|
||||
}
|
||||
|
||||
function unwrapListeners(arr) {
|
||||
const ret = arrayClone(arr);
|
||||
for (let i = 0; i < ret.length; ++i) {
|
||||
const orig = ret[i].listener;
|
||||
if (typeof orig === 'function')
|
||||
ret[i] = orig;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
44918
dist/index.js
vendored
44918
dist/index.js
vendored
File diff suppressed because one or more lines are too long
25405
dist/index1.js
vendored
25405
dist/index1.js
vendored
File diff suppressed because one or more lines are too long
464
dist/setup-node-sandbox.js
vendored
Normal file
464
dist/setup-node-sandbox.js
vendored
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
/* global host, data, VMError */
|
||||
|
||||
'use strict';
|
||||
|
||||
const LocalError = Error;
|
||||
const LocalTypeError = TypeError;
|
||||
const LocalWeakMap = WeakMap;
|
||||
|
||||
const {
|
||||
apply: localReflectApply,
|
||||
defineProperty: localReflectDefineProperty
|
||||
} = Reflect;
|
||||
|
||||
const {
|
||||
set: localWeakMapSet,
|
||||
get: localWeakMapGet
|
||||
} = LocalWeakMap.prototype;
|
||||
|
||||
const {
|
||||
isArray: localArrayIsArray
|
||||
} = Array;
|
||||
|
||||
function uncurryThis(func) {
|
||||
return (thiz, ...args) => localReflectApply(func, thiz, args);
|
||||
}
|
||||
|
||||
const localArrayPrototypeSlice = uncurryThis(Array.prototype.slice);
|
||||
const localArrayPrototypeIncludes = uncurryThis(Array.prototype.includes);
|
||||
const localArrayPrototypePush = uncurryThis(Array.prototype.push);
|
||||
const localArrayPrototypeIndexOf = uncurryThis(Array.prototype.indexOf);
|
||||
const localArrayPrototypeSplice = uncurryThis(Array.prototype.splice);
|
||||
const localStringPrototypeStartsWith = uncurryThis(String.prototype.startsWith);
|
||||
const localStringPrototypeSlice = uncurryThis(String.prototype.slice);
|
||||
const localStringPrototypeIndexOf = uncurryThis(String.prototype.indexOf);
|
||||
|
||||
const {
|
||||
argv: optionArgv,
|
||||
env: optionEnv,
|
||||
console: optionConsole,
|
||||
vm,
|
||||
resolver,
|
||||
extensions
|
||||
} = data;
|
||||
|
||||
function ensureSandboxArray(a) {
|
||||
return localArrayPrototypeSlice(a);
|
||||
}
|
||||
|
||||
const globalPaths = ensureSandboxArray(resolver.globalPaths);
|
||||
|
||||
class Module {
|
||||
|
||||
constructor(id, path, parent) {
|
||||
this.id = id;
|
||||
this.filename = id;
|
||||
this.path = path;
|
||||
this.parent = parent;
|
||||
this.loaded = false;
|
||||
this.paths = path ? ensureSandboxArray(resolver.genLookupPaths(path)) : [];
|
||||
this.children = [];
|
||||
this.exports = {};
|
||||
}
|
||||
|
||||
_updateChildren(child, isNew) {
|
||||
const children = this.children;
|
||||
if (children && (isNew || !localArrayPrototypeIncludes(children, child))) {
|
||||
localArrayPrototypePush(children, child);
|
||||
}
|
||||
}
|
||||
|
||||
require(id) {
|
||||
return requireImpl(this, id, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const originalRequire = Module.prototype.require;
|
||||
const cacheBuiltins = {__proto__: null};
|
||||
|
||||
function requireImpl(mod, id, direct) {
|
||||
if (direct && mod.require !== originalRequire) {
|
||||
return mod.require(id);
|
||||
}
|
||||
const filename = resolver.resolve(mod, id, undefined, Module._extensions, direct);
|
||||
if (localStringPrototypeStartsWith(filename, 'node:')) {
|
||||
id = localStringPrototypeSlice(filename, 5);
|
||||
let nmod = cacheBuiltins[id];
|
||||
if (!nmod) {
|
||||
nmod = resolver.loadBuiltinModule(vm, id);
|
||||
if (!nmod) throw new VMError(`Cannot find module '${filename}'`, 'ENOTFOUND');
|
||||
cacheBuiltins[id] = nmod;
|
||||
}
|
||||
return nmod;
|
||||
}
|
||||
|
||||
const cachedModule = Module._cache[filename];
|
||||
if (cachedModule !== undefined) {
|
||||
mod._updateChildren(cachedModule, false);
|
||||
return cachedModule.exports;
|
||||
}
|
||||
|
||||
let nmod = cacheBuiltins[id];
|
||||
if (nmod) return nmod;
|
||||
nmod = resolver.loadBuiltinModule(vm, id);
|
||||
if (nmod) {
|
||||
cacheBuiltins[id] = nmod;
|
||||
return nmod;
|
||||
}
|
||||
|
||||
const path = resolver.pathDirname(filename);
|
||||
const module = new Module(filename, path, mod);
|
||||
resolver.registerModule(module, filename, path, mod, direct);
|
||||
mod._updateChildren(module, true);
|
||||
try {
|
||||
Module._cache[filename] = module;
|
||||
const handler = findBestExtensionHandler(filename);
|
||||
handler(module, filename);
|
||||
module.loaded = true;
|
||||
} catch (e) {
|
||||
delete Module._cache[filename];
|
||||
const children = mod.children;
|
||||
if (localArrayIsArray(children)) {
|
||||
const index = localArrayPrototypeIndexOf(children, module);
|
||||
if (index !== -1) {
|
||||
localArrayPrototypeSplice(children, index, 1);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
return module.exports;
|
||||
}
|
||||
|
||||
Module.builtinModules = ensureSandboxArray(resolver.getBuiltinModulesList());
|
||||
Module.globalPaths = globalPaths;
|
||||
Module._extensions = {__proto__: null};
|
||||
Module._cache = {__proto__: null};
|
||||
|
||||
{
|
||||
const keys = Object.getOwnPropertyNames(extensions);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
const handler = extensions[key];
|
||||
Module._extensions[key] = (mod, filename) => handler(mod, filename);
|
||||
}
|
||||
}
|
||||
|
||||
function findBestExtensionHandler(filename) {
|
||||
const name = resolver.pathBasename(filename);
|
||||
for (let i = 0; (i = localStringPrototypeIndexOf(name, '.', i + 1)) !== -1;) {
|
||||
const ext = localStringPrototypeSlice(name, i);
|
||||
const handler = Module._extensions[ext];
|
||||
if (handler) return handler;
|
||||
}
|
||||
const js = Module._extensions['.js'];
|
||||
if (js) return js;
|
||||
const keys = Object.getOwnPropertyNames(Module._extensions);
|
||||
if (keys.length === 0) throw new VMError(`Failed to load '${filename}': Unknown type.`, 'ELOADFAIL');
|
||||
return Module._extensions[keys[0]];
|
||||
}
|
||||
|
||||
function createRequireForModule(mod) {
|
||||
// eslint-disable-next-line no-shadow
|
||||
function require(id) {
|
||||
return requireImpl(mod, id, true);
|
||||
}
|
||||
function resolve(id, options) {
|
||||
return resolver.resolve(mod, id, options, Module._extensions, true);
|
||||
}
|
||||
require.resolve = resolve;
|
||||
function paths(id) {
|
||||
return ensureSandboxArray(resolver.lookupPaths(mod, id));
|
||||
}
|
||||
resolve.paths = paths;
|
||||
|
||||
require.extensions = Module._extensions;
|
||||
|
||||
require.cache = Module._cache;
|
||||
|
||||
return require;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare sandbox.
|
||||
*/
|
||||
|
||||
const TIMERS = new LocalWeakMap();
|
||||
|
||||
class Timeout {
|
||||
}
|
||||
|
||||
class Interval {
|
||||
}
|
||||
|
||||
class Immediate {
|
||||
}
|
||||
|
||||
function clearTimer(timer) {
|
||||
const obj = localReflectApply(localWeakMapGet, TIMERS, [timer]);
|
||||
if (obj) {
|
||||
obj.clear(obj.value);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a function and not an arrow function, since the original is also a function
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setTimeout = function setTimeout(callback, delay, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Timeout(callback, args);
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setTimeout(cb, delay);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearTimeout,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setInterval = function setInterval(callback, interval, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Interval();
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setInterval(cb, interval);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearInterval,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.setImmediate = function setImmediate(callback, ...args) {
|
||||
if (typeof callback !== 'function') throw new LocalTypeError('"callback" argument must be a function');
|
||||
const obj = new Immediate();
|
||||
const cb = () => {
|
||||
localReflectApply(callback, null, args);
|
||||
};
|
||||
const tmr = host.setImmediate(cb);
|
||||
|
||||
const ref = {
|
||||
__proto__: null,
|
||||
clear: host.clearImmediate,
|
||||
value: tmr
|
||||
};
|
||||
|
||||
localReflectApply(localWeakMapSet, TIMERS, [obj, ref]);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearTimeout = function clearTimeout(timeout) {
|
||||
clearTimer(timeout);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearInterval = function clearInterval(interval) {
|
||||
clearTimer(interval);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
global.clearImmediate = function clearImmediate(immediate) {
|
||||
clearTimer(immediate);
|
||||
};
|
||||
|
||||
const localProcess = host.process;
|
||||
|
||||
function vmEmitArgs(event, args) {
|
||||
const allargs = [event];
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (!localReflectDefineProperty(allargs, i + 1, {
|
||||
__proto__: null,
|
||||
value: args[i],
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
})) throw new LocalError('Unexpected');
|
||||
}
|
||||
return localReflectApply(vm.emit, vm, allargs);
|
||||
}
|
||||
|
||||
const LISTENERS = new LocalWeakMap();
|
||||
const LISTENER_HANDLER = new LocalWeakMap();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} name
|
||||
* @param {*} handler
|
||||
* @this process
|
||||
* @return {this}
|
||||
*/
|
||||
function addListener(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new LocalError(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
let cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
|
||||
if (!cb) {
|
||||
cb = () => {
|
||||
handler();
|
||||
};
|
||||
localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);
|
||||
localReflectApply(localWeakMapSet, LISTENERS, [handler, cb]);
|
||||
}
|
||||
|
||||
localProcess.on(name, cb);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @this process
|
||||
* @return {this}
|
||||
*/
|
||||
// eslint-disable-next-line no-shadow
|
||||
function process() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// FIXME wrong class structure
|
||||
global.process = {
|
||||
__proto__: process.prototype,
|
||||
argv: optionArgv !== undefined ? optionArgv : [],
|
||||
title: localProcess.title,
|
||||
version: localProcess.version,
|
||||
versions: localProcess.versions,
|
||||
arch: localProcess.arch,
|
||||
platform: localProcess.platform,
|
||||
env: optionEnv !== undefined ? optionEnv : {},
|
||||
pid: localProcess.pid,
|
||||
features: localProcess.features,
|
||||
nextTick: function nextTick(callback, ...args) {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new LocalError('Callback must be a function.');
|
||||
}
|
||||
|
||||
localProcess.nextTick(()=>{
|
||||
localReflectApply(callback, null, args);
|
||||
});
|
||||
},
|
||||
hrtime: function hrtime(time) {
|
||||
return localProcess.hrtime(time);
|
||||
},
|
||||
cwd: function cwd() {
|
||||
return localProcess.cwd();
|
||||
},
|
||||
addListener,
|
||||
on: addListener,
|
||||
|
||||
once: function once(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
throw new LocalError(`Access denied to listen for '${name}' event.`);
|
||||
}
|
||||
|
||||
let triggered = false;
|
||||
const cb = () => {
|
||||
if (triggered) return;
|
||||
triggered = true;
|
||||
localProcess.removeListener(name, cb);
|
||||
handler();
|
||||
};
|
||||
localReflectApply(localWeakMapSet, LISTENER_HANDLER, [cb, handler]);
|
||||
|
||||
localProcess.on(name, cb);
|
||||
|
||||
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
|
||||
const all = localProcess.listeners(name);
|
||||
const filtered = [];
|
||||
let j = 0;
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
const h = localReflectApply(localWeakMapGet, LISTENER_HANDLER, [all[i]]);
|
||||
if (h) {
|
||||
if (!localReflectDefineProperty(filtered, j, {
|
||||
__proto__: null,
|
||||
value: h,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
})) throw new LocalError('Unexpected');
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
},
|
||||
|
||||
removeListener: function removeListener(name, handler) {
|
||||
if (name !== 'beforeExit' && name !== 'exit') {
|
||||
return this;
|
||||
}
|
||||
|
||||
const cb = localReflectApply(localWeakMapGet, LISTENERS, [handler]);
|
||||
if (cb) localProcess.removeListener(name, cb);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
umask: function umask() {
|
||||
if (arguments.length) {
|
||||
throw new LocalError('Access denied to set umask.');
|
||||
}
|
||||
|
||||
return localProcess.umask();
|
||||
}
|
||||
};
|
||||
|
||||
if (optionConsole === 'inherit') {
|
||||
global.console = host.console;
|
||||
} else if (optionConsole === 'redirect') {
|
||||
global.console = {
|
||||
debug(...args) {
|
||||
vmEmitArgs('console.debug', args);
|
||||
},
|
||||
log(...args) {
|
||||
vmEmitArgs('console.log', args);
|
||||
},
|
||||
info(...args) {
|
||||
vmEmitArgs('console.info', args);
|
||||
},
|
||||
warn(...args) {
|
||||
vmEmitArgs('console.warn', args);
|
||||
},
|
||||
error(...args) {
|
||||
vmEmitArgs('console.error', args);
|
||||
},
|
||||
dir(...args) {
|
||||
vmEmitArgs('console.dir', args);
|
||||
},
|
||||
time() {},
|
||||
timeEnd() {},
|
||||
trace(...args) {
|
||||
vmEmitArgs('console.trace', args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
__proto__: null,
|
||||
Module,
|
||||
jsonParse: JSON.parse,
|
||||
createRequireForModule,
|
||||
requireImpl
|
||||
};
|
||||
453
dist/setup-sandbox.js
vendored
Normal file
453
dist/setup-sandbox.js
vendored
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/* global host, bridge, data, context */
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
Object: localObject,
|
||||
Array: localArray,
|
||||
Error: LocalError,
|
||||
Reflect: localReflect,
|
||||
Proxy: LocalProxy,
|
||||
WeakMap: LocalWeakMap,
|
||||
Function: localFunction,
|
||||
Promise: localPromise,
|
||||
eval: localEval
|
||||
} = global;
|
||||
|
||||
const {
|
||||
freeze: localObjectFreeze
|
||||
} = localObject;
|
||||
|
||||
const {
|
||||
getPrototypeOf: localReflectGetPrototypeOf,
|
||||
apply: localReflectApply,
|
||||
deleteProperty: localReflectDeleteProperty,
|
||||
has: localReflectHas,
|
||||
defineProperty: localReflectDefineProperty,
|
||||
setPrototypeOf: localReflectSetPrototypeOf,
|
||||
getOwnPropertyDescriptor: localReflectGetOwnPropertyDescriptor
|
||||
} = localReflect;
|
||||
|
||||
const {
|
||||
isArray: localArrayIsArray
|
||||
} = localArray;
|
||||
|
||||
const {
|
||||
ensureThis,
|
||||
ReadOnlyHandler,
|
||||
from,
|
||||
fromWithFactory,
|
||||
readonlyFactory,
|
||||
connect,
|
||||
addProtoMapping,
|
||||
VMError,
|
||||
ReadOnlyMockHandler
|
||||
} = bridge;
|
||||
|
||||
const {
|
||||
allowAsync,
|
||||
GeneratorFunction,
|
||||
AsyncFunction,
|
||||
AsyncGeneratorFunction
|
||||
} = data;
|
||||
|
||||
const localWeakMapGet = LocalWeakMap.prototype.get;
|
||||
|
||||
function localUnexpected() {
|
||||
return new VMError('Should not happen');
|
||||
}
|
||||
|
||||
// global is originally prototype of host.Object so it can be used to climb up from the sandbox.
|
||||
if (!localReflectSetPrototypeOf(context, localObject.prototype)) throw localUnexpected();
|
||||
|
||||
Object.defineProperties(global, {
|
||||
global: {value: global, writable: true, configurable: true, enumerable: true},
|
||||
globalThis: {value: global, writable: true, configurable: true},
|
||||
GLOBAL: {value: global, writable: true, configurable: true},
|
||||
root: {value: global, writable: true, configurable: true}
|
||||
});
|
||||
|
||||
if (!localReflectDefineProperty(global, 'VMError', {
|
||||
__proto__: null,
|
||||
value: VMError,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
})) throw localUnexpected();
|
||||
|
||||
// Fixes buffer unsafe allocation
|
||||
/* eslint-disable no-use-before-define */
|
||||
class BufferHandler extends ReadOnlyHandler {
|
||||
|
||||
apply(target, thiz, args) {
|
||||
if (args.length > 0 && typeof args[0] === 'number') {
|
||||
return LocalBuffer.alloc(args[0]);
|
||||
}
|
||||
return localReflectApply(LocalBuffer.from, LocalBuffer, args);
|
||||
}
|
||||
|
||||
construct(target, args, newTarget) {
|
||||
if (args.length > 0 && typeof args[0] === 'number') {
|
||||
return LocalBuffer.alloc(args[0]);
|
||||
}
|
||||
return localReflectApply(LocalBuffer.from, LocalBuffer, args);
|
||||
}
|
||||
|
||||
}
|
||||
/* eslint-enable no-use-before-define */
|
||||
|
||||
const LocalBuffer = fromWithFactory(obj => new BufferHandler(obj), host.Buffer);
|
||||
|
||||
|
||||
if (!localReflectDefineProperty(global, 'Buffer', {
|
||||
__proto__: null,
|
||||
value: LocalBuffer,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
})) throw localUnexpected();
|
||||
|
||||
addProtoMapping(LocalBuffer.prototype, host.Buffer.prototype, 'Uint8Array');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} size Size of new buffer
|
||||
* @this LocalBuffer
|
||||
* @return {LocalBuffer}
|
||||
*/
|
||||
function allocUnsafe(size) {
|
||||
return LocalBuffer.alloc(size);
|
||||
}
|
||||
|
||||
connect(allocUnsafe, host.Buffer.allocUnsafe);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} size Size of new buffer
|
||||
* @this LocalBuffer
|
||||
* @return {LocalBuffer}
|
||||
*/
|
||||
function allocUnsafeSlow(size) {
|
||||
return LocalBuffer.alloc(size);
|
||||
}
|
||||
|
||||
connect(allocUnsafeSlow, host.Buffer.allocUnsafeSlow);
|
||||
|
||||
/**
|
||||
* Replacement for Buffer inspect
|
||||
*
|
||||
* @param {*} recurseTimes
|
||||
* @param {*} ctx
|
||||
* @this LocalBuffer
|
||||
* @return {string}
|
||||
*/
|
||||
function inspect(recurseTimes, ctx) {
|
||||
// Mimic old behavior, could throw but didn't pass a test.
|
||||
const max = host.INSPECT_MAX_BYTES;
|
||||
const actualMax = Math.min(max, this.length);
|
||||
const remaining = this.length - max;
|
||||
let str = this.hexSlice(0, actualMax).replace(/(.{2})/g, '$1 ').trim();
|
||||
if (remaining > 0) str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`;
|
||||
return `<${this.constructor.name} ${str}>`;
|
||||
}
|
||||
|
||||
connect(inspect, host.Buffer.prototype.inspect);
|
||||
|
||||
connect(localFunction.prototype.bind, host.Function.prototype.bind);
|
||||
|
||||
connect(localObject.prototype.__defineGetter__, host.Object.prototype.__defineGetter__);
|
||||
connect(localObject.prototype.__defineSetter__, host.Object.prototype.__defineSetter__);
|
||||
connect(localObject.prototype.__lookupGetter__, host.Object.prototype.__lookupGetter__);
|
||||
connect(localObject.prototype.__lookupSetter__, host.Object.prototype.__lookupSetter__);
|
||||
|
||||
/*
|
||||
* PrepareStackTrace sanitization
|
||||
*/
|
||||
|
||||
const oldPrepareStackTraceDesc = localReflectGetOwnPropertyDescriptor(LocalError, 'prepareStackTrace');
|
||||
|
||||
let currentPrepareStackTrace = LocalError.prepareStackTrace;
|
||||
const wrappedPrepareStackTrace = new LocalWeakMap();
|
||||
if (typeof currentPrepareStackTrace === 'function') {
|
||||
wrappedPrepareStackTrace.set(currentPrepareStackTrace, currentPrepareStackTrace);
|
||||
}
|
||||
|
||||
let OriginalCallSite;
|
||||
LocalError.prepareStackTrace = (e, sst) => {
|
||||
OriginalCallSite = sst[0].constructor;
|
||||
};
|
||||
new LocalError().stack;
|
||||
if (typeof OriginalCallSite === 'function') {
|
||||
LocalError.prepareStackTrace = undefined;
|
||||
|
||||
function makeCallSiteGetters(list) {
|
||||
const callSiteGetters = [];
|
||||
for (let i=0; i<list.length; i++) {
|
||||
const name = list[i];
|
||||
const func = OriginalCallSite.prototype[name];
|
||||
callSiteGetters[i] = {__proto__: null,
|
||||
name,
|
||||
propName: '_' + name,
|
||||
func: (thiz) => {
|
||||
return localReflectApply(func, thiz, []);
|
||||
}
|
||||
};
|
||||
}
|
||||
return callSiteGetters;
|
||||
}
|
||||
|
||||
function applyCallSiteGetters(thiz, callSite, getters) {
|
||||
for (let i=0; i<getters.length; i++) {
|
||||
const getter = getters[i];
|
||||
localReflectDefineProperty(thiz, getter.propName, {
|
||||
__proto__: null,
|
||||
value: getter.func(callSite)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const callSiteGetters = makeCallSiteGetters([
|
||||
'getTypeName',
|
||||
'getFunctionName',
|
||||
'getMethodName',
|
||||
'getFileName',
|
||||
'getLineNumber',
|
||||
'getColumnNumber',
|
||||
'getEvalOrigin',
|
||||
'isToplevel',
|
||||
'isEval',
|
||||
'isNative',
|
||||
'isConstructor',
|
||||
'isAsync',
|
||||
'isPromiseAll',
|
||||
'getPromiseIndex'
|
||||
]);
|
||||
|
||||
class CallSite {
|
||||
constructor(callSite) {
|
||||
applyCallSiteGetters(this, callSite, callSiteGetters);
|
||||
}
|
||||
getThis() {
|
||||
return undefined;
|
||||
}
|
||||
getFunction() {
|
||||
return undefined;
|
||||
}
|
||||
toString() {
|
||||
return 'CallSite {}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (let i=0; i<callSiteGetters.length; i++) {
|
||||
const name = callSiteGetters[i].name;
|
||||
const funcProp = localReflectGetOwnPropertyDescriptor(OriginalCallSite.prototype, name);
|
||||
if (!funcProp) continue;
|
||||
const propertyName = callSiteGetters[i].propName;
|
||||
const func = {func() {
|
||||
return this[propertyName];
|
||||
}}.func;
|
||||
const nameProp = localReflectGetOwnPropertyDescriptor(func, 'name');
|
||||
if (!nameProp) throw localUnexpected();
|
||||
nameProp.value = name;
|
||||
if (!localReflectDefineProperty(func, 'name', nameProp)) throw localUnexpected();
|
||||
funcProp.value = func;
|
||||
if (!localReflectDefineProperty(CallSite.prototype, name, funcProp)) throw localUnexpected();
|
||||
}
|
||||
|
||||
if (!localReflectDefineProperty(LocalError, 'prepareStackTrace', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
get() {
|
||||
return currentPrepareStackTrace;
|
||||
},
|
||||
set(value) {
|
||||
if (typeof(value) !== 'function') {
|
||||
currentPrepareStackTrace = value;
|
||||
return;
|
||||
}
|
||||
const wrapped = localReflectApply(localWeakMapGet, wrappedPrepareStackTrace, [value]);
|
||||
if (wrapped) {
|
||||
currentPrepareStackTrace = wrapped;
|
||||
return;
|
||||
}
|
||||
const newWrapped = (error, sst) => {
|
||||
if (localArrayIsArray(sst)) {
|
||||
for (let i=0; i < sst.length; i++) {
|
||||
const cs = sst[i];
|
||||
if (typeof cs === 'object' && localReflectGetPrototypeOf(cs) === OriginalCallSite.prototype) {
|
||||
sst[i] = new CallSite(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value(error, sst);
|
||||
};
|
||||
wrappedPrepareStackTrace.set(value, newWrapped);
|
||||
wrappedPrepareStackTrace.set(newWrapped, newWrapped);
|
||||
currentPrepareStackTrace = newWrapped;
|
||||
}
|
||||
})) throw localUnexpected();
|
||||
} else if (oldPrepareStackTraceDesc) {
|
||||
localReflectDefineProperty(LocalError, 'prepareStackTrace', oldPrepareStackTraceDesc);
|
||||
} else {
|
||||
localReflectDeleteProperty(LocalError, 'prepareStackTrace');
|
||||
}
|
||||
|
||||
/*
|
||||
* Exception sanitization
|
||||
*/
|
||||
|
||||
const withProxy = localObjectFreeze({
|
||||
__proto__: null,
|
||||
has(target, key) {
|
||||
if (key === host.INTERNAL_STATE_NAME) return false;
|
||||
return localReflectHas(target, key);
|
||||
}
|
||||
});
|
||||
|
||||
const interanState = localObjectFreeze({
|
||||
__proto__: null,
|
||||
wrapWith(x) {
|
||||
if (x === null || x === undefined) return x;
|
||||
return new LocalProxy(localObject(x), withProxy);
|
||||
},
|
||||
handleException: ensureThis,
|
||||
import(what) {
|
||||
throw new VMError('Dynamic Import not supported');
|
||||
}
|
||||
});
|
||||
|
||||
if (!localReflectDefineProperty(global, host.INTERNAL_STATE_NAME, {
|
||||
__proto__: null,
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
value: interanState
|
||||
})) throw localUnexpected();
|
||||
|
||||
/*
|
||||
* Eval sanitization
|
||||
*/
|
||||
|
||||
function throwAsync() {
|
||||
return new VMError('Async not available');
|
||||
}
|
||||
|
||||
function makeFunction(inputArgs, isAsync, isGenerator) {
|
||||
const lastArgs = inputArgs.length - 1;
|
||||
let code = lastArgs >= 0 ? `${inputArgs[lastArgs]}` : '';
|
||||
let args = lastArgs > 0 ? `${inputArgs[0]}` : '';
|
||||
for (let i = 1; i < lastArgs; i++) {
|
||||
args += `,${inputArgs[i]}`;
|
||||
}
|
||||
try {
|
||||
code = host.transformAndCheck(args, code, isAsync, isGenerator, allowAsync);
|
||||
} catch (e) {
|
||||
throw bridge.from(e);
|
||||
}
|
||||
return localEval(code);
|
||||
}
|
||||
|
||||
const FunctionHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
return makeFunction(args, this.isAsync, this.isGenerator);
|
||||
},
|
||||
construct(target, args, newTarget) {
|
||||
return makeFunction(args, this.isAsync, this.isGenerator);
|
||||
}
|
||||
};
|
||||
|
||||
const EvalHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
if (args.length === 0) return undefined;
|
||||
let code = `${args[0]}`;
|
||||
try {
|
||||
code = host.transformAndCheck(null, code, false, false, allowAsync);
|
||||
} catch (e) {
|
||||
throw bridge.from(e);
|
||||
}
|
||||
return localEval(code);
|
||||
}
|
||||
};
|
||||
|
||||
const AsyncErrorHandler = {
|
||||
__proto__: null,
|
||||
apply(target, thiz, args) {
|
||||
throw throwAsync();
|
||||
},
|
||||
construct(target, args, newTarget) {
|
||||
throw throwAsync();
|
||||
}
|
||||
};
|
||||
|
||||
function makeCheckFunction(isAsync, isGenerator) {
|
||||
if (isAsync && !allowAsync) return AsyncErrorHandler;
|
||||
return {
|
||||
__proto__: FunctionHandler,
|
||||
isAsync,
|
||||
isGenerator
|
||||
};
|
||||
}
|
||||
|
||||
function overrideWithProxy(obj, prop, value, handler) {
|
||||
const proxy = new LocalProxy(value, handler);
|
||||
if (!localReflectDefineProperty(obj, prop, {__proto__: null, value: proxy})) throw localUnexpected();
|
||||
return proxy;
|
||||
}
|
||||
|
||||
const proxiedFunction = overrideWithProxy(localFunction.prototype, 'constructor', localFunction, makeCheckFunction(false, false));
|
||||
if (GeneratorFunction) {
|
||||
if (!localReflectSetPrototypeOf(GeneratorFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(GeneratorFunction.prototype, 'constructor', GeneratorFunction, makeCheckFunction(false, true));
|
||||
}
|
||||
if (AsyncFunction) {
|
||||
if (!localReflectSetPrototypeOf(AsyncFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(AsyncFunction.prototype, 'constructor', AsyncFunction, makeCheckFunction(true, false));
|
||||
}
|
||||
if (AsyncGeneratorFunction) {
|
||||
if (!localReflectSetPrototypeOf(AsyncGeneratorFunction, proxiedFunction)) throw localUnexpected();
|
||||
overrideWithProxy(AsyncGeneratorFunction.prototype, 'constructor', AsyncGeneratorFunction, makeCheckFunction(true, true));
|
||||
}
|
||||
|
||||
global.Function = proxiedFunction;
|
||||
global.eval = new LocalProxy(localEval, EvalHandler);
|
||||
|
||||
/*
|
||||
* Promise sanitization
|
||||
*/
|
||||
|
||||
if (localPromise && !allowAsync) {
|
||||
|
||||
const PromisePrototype = localPromise.prototype;
|
||||
|
||||
overrideWithProxy(PromisePrototype, 'then', PromisePrototype.then, AsyncErrorHandler);
|
||||
// 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 (PromisePrototype.finally) {
|
||||
overrideWithProxy(PromisePrototype, 'finally', PromisePrototype.finally, AsyncErrorHandler);
|
||||
// Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
|
||||
}
|
||||
if (Promise.prototype.catch) {
|
||||
overrideWithProxy(PromisePrototype, 'catch', PromisePrototype.catch, AsyncErrorHandler);
|
||||
// Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function readonly(other, mock) {
|
||||
// Note: other@other(unsafe) mock@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
if (!mock) return fromWithFactory(readonlyFactory, other);
|
||||
const tmock = from(mock);
|
||||
return fromWithFactory(obj=>new ReadOnlyMockHandler(obj, tmock), other);
|
||||
}
|
||||
|
||||
return {
|
||||
__proto__: null,
|
||||
readonly,
|
||||
global
|
||||
};
|
||||
5
index.js
5
index.js
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
const core = require('@actions/core');
|
||||
|
||||
const setup = require('./lib/setup-terraform');
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
// Node.js core
|
||||
const fs = require('fs').promises;
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const semver = require('semver');
|
||||
|
||||
// External
|
||||
const core = require('@actions/core');
|
||||
|
|
@ -136,15 +130,7 @@ async function run () {
|
|||
core.debug(`Finding releases for Terraform version ${version}`);
|
||||
const release = await releases.getRelease('terraform', version, 'GitHub Action: Setup Terraform');
|
||||
const platform = mapOS(osPlatform);
|
||||
let arch = mapArch(osArch);
|
||||
|
||||
// Terraform was not available for darwin/arm64 until 1.0.2, however macOS
|
||||
// runners can emulate darwin/amd64.
|
||||
if (platform === 'darwin' && arch === 'arm64' && semver.valid(release.version) && semver.lt(release.version, '1.0.2')) {
|
||||
core.warning('Terraform is not available for darwin/arm64 until version 1.0.2. Falling back to darwin/amd64.');
|
||||
arch = 'amd64';
|
||||
}
|
||||
|
||||
const arch = mapArch(osArch);
|
||||
core.debug(`Getting build for Terraform version ${release.version}: ${platform} ${arch}`);
|
||||
const build = release.getBuild(platform, arch);
|
||||
if (!build) {
|
||||
|
|
|
|||
10353
package-lock.json
generated
10353
package-lock.json
generated
File diff suppressed because it is too large
Load diff
42
package.json
42
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "setup-terraform",
|
||||
"version": "3.1.2",
|
||||
"version": "2.0.0",
|
||||
"description": "Setup Terraform CLI for GitHub Actions",
|
||||
"license": "MPL-2.0",
|
||||
"publisher": "hashicorp",
|
||||
|
|
@ -10,31 +10,39 @@
|
|||
"url": "https://github.com/hashicorp/setup-terraform.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "semistandard --env jest && jest --coverage",
|
||||
"lint": "semistandard --env jest --fix",
|
||||
"build": "ncc build wrapper/terraform.js --out wrapper/dist && ncc build index.js --out dist",
|
||||
"format-check": "echo \"unimplemented for actions/reusable-workflows basic-validation\""
|
||||
"test": "cd wrapper && npm test && cd .. && semistandard --env jest && jest --coverage",
|
||||
"lint": "cd wrapper && npm run lint && cd .. && semistandard --env jest --fix",
|
||||
"build": "cd wrapper && npm run build && cd .. && ncc build index.js --out dist",
|
||||
"postinstall": "cd wrapper && npm install",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^6.0.1",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@actions/tool-cache": "^2.0.2",
|
||||
"@hashicorp/js-releases": "^1.7.5",
|
||||
"semver": "^7.7.3"
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@actions/io": "^1.1.2",
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"@hashicorp/js-releases": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.38.4",
|
||||
"jest": "^30.2.0",
|
||||
"nock": "^14.0.10",
|
||||
"semistandard": "^17.0.0"
|
||||
"@vercel/ncc": "0.34.0",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "^29.0.3",
|
||||
"nock": "^13.2.9",
|
||||
"semistandard": "^16.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"testPathIgnorePatterns": [
|
||||
"<rootDir>/dist/",
|
||||
"<rootDir>/node_modules/",
|
||||
"<rootDir>/wrapper/"
|
||||
]
|
||||
},
|
||||
"semistandard": {
|
||||
"ignore": [
|
||||
"**/dist/**"
|
||||
"dist/**",
|
||||
"wrapper/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
// Mock external modules by default
|
||||
jest.mock('@actions/core');
|
||||
jest.mock('@actions/tool-cache');
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Acts as a listener for @actions/exec, by capturing STDOUT and STDERR
|
||||
* streams, and exposing them via a contents attribute.
|
||||
|
|
@ -20,18 +15,13 @@
|
|||
* console.log(listener.contents);
|
||||
*/
|
||||
class OutputListener {
|
||||
constructor (streamWriter) {
|
||||
constructor () {
|
||||
this._buff = [];
|
||||
this._streamWriter = streamWriter;
|
||||
}
|
||||
|
||||
get listener () {
|
||||
const listen = function listen (data) {
|
||||
this._buff.push(data);
|
||||
|
||||
if (this._streamWriter) {
|
||||
this._streamWriter.write(data);
|
||||
}
|
||||
};
|
||||
return listen.bind(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
|
|
|
|||
10352
wrapper/package-lock.json
generated
Normal file
10352
wrapper/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
29
wrapper/package.json
Normal file
29
wrapper/package.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "terraform.js",
|
||||
"version": "0.0.1",
|
||||
"description": "JavaScript wrapper for terraform binary",
|
||||
"license": "MPL-2.0",
|
||||
"publisher": "hashicorp",
|
||||
"main": "terraform.js",
|
||||
"scripts": {
|
||||
"test": "semistandard --env jest && jest --coverage",
|
||||
"lint": "semistandard --env jest --fix",
|
||||
"build": "ncc build terraform.js --out dist"
|
||||
},
|
||||
"author": "",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/io": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "0.33.3",
|
||||
"jest": "^27.5.1",
|
||||
"semistandard": "^16.0.1"
|
||||
},
|
||||
"semistandard": {
|
||||
"ignore": [
|
||||
"dist/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,4 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
const io = require('@actions/io');
|
||||
const core = require('@actions/core');
|
||||
const { exec } = require('@actions/exec');
|
||||
|
|
@ -21,9 +16,9 @@ async function checkTerraform () {
|
|||
// This will fail if Terraform isn't found, which is what we want
|
||||
await checkTerraform();
|
||||
|
||||
// Create listeners to receive output (in memory)
|
||||
const stdout = new OutputListener(process.stdout);
|
||||
const stderr = new OutputListener(process.stderr);
|
||||
// Create listeners to receive output (in memory) as well
|
||||
const stdout = new OutputListener();
|
||||
const stderr = new OutputListener();
|
||||
const listeners = {
|
||||
stdout: stdout.listener,
|
||||
stderr: stderr.listener
|
||||
|
|
@ -33,10 +28,13 @@ async function checkTerraform () {
|
|||
const args = process.argv.slice(2);
|
||||
const options = {
|
||||
listeners,
|
||||
ignoreReturnCode: true,
|
||||
silent: true // avoid printing command in stdout: https://github.com/actions/toolkit/issues/649
|
||||
ignoreReturnCode: true
|
||||
};
|
||||
const exitCode = await exec(pathToCLI, args, options);
|
||||
core.debug(`Terraform exited with code ${exitCode}.`);
|
||||
core.debug(`stdout: ${stdout.contents}`);
|
||||
core.debug(`stderr: ${stderr.contents}`);
|
||||
core.debug(`exitcode: ${exitCode}`);
|
||||
|
||||
// Set outputs, result, exitcode, and stderr
|
||||
core.setOutput('stdout', stdout.contents);
|
||||
|
|
|
|||
|
|
@ -1,36 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
const OutputListener = require('../lib/output-listener');
|
||||
|
||||
describe('output-listener', () => {
|
||||
it('receives and buffers data to .contents', () => {
|
||||
it('receives and exposes data', () => {
|
||||
const listener = new OutputListener();
|
||||
const listen = listener.listener;
|
||||
|
||||
listen(Buffer.from('foo'));
|
||||
listen(Buffer.from('bar'));
|
||||
listen(Buffer.from('baz'));
|
||||
|
||||
expect(listener.contents).toEqual('foobarbaz');
|
||||
});
|
||||
|
||||
it('receives and writes data to stream immediately', () => {
|
||||
const mockWrite = jest.fn();
|
||||
const listener = new OutputListener({ write: mockWrite });
|
||||
const listen = listener.listener;
|
||||
|
||||
listen(Buffer.from('first write'));
|
||||
expect(mockWrite.mock.lastCall[0]).toStrictEqual(Buffer.from('first write'));
|
||||
|
||||
listen(Buffer.from('second write'));
|
||||
expect(mockWrite.mock.lastCall[0]).toStrictEqual(Buffer.from('second write'));
|
||||
|
||||
listen(Buffer.from('third write'));
|
||||
expect(mockWrite.mock.lastCall[0]).toStrictEqual(Buffer.from('third write'));
|
||||
|
||||
expect(mockWrite).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue