Compare commits
196 Commits
Author | SHA1 | Date |
---|---|---|
|
0d4c9c5ea7 | |
|
b29e14f6a9 | |
|
218a70c516 | |
|
b8200806cf | |
|
27530a9fbb | |
|
d072a60421 | |
|
7c627b5124 | |
|
787cfc6623 | |
|
8e66e916f8 | |
|
5ba5e97350 | |
|
db77945884 | |
|
bfd28af29d | |
|
70fccc794a | |
|
d5eb4a7b25 | |
|
d9ec9539b3 | |
|
406e1d7119 | |
|
834ded21d8 | |
|
c7cb6a492e | |
|
7840e6ddd4 | |
|
d910b14072 | |
|
7c17210d47 | |
|
117949aa8e | |
|
225e47902b | |
|
5f4866a30a | |
|
28283a6966 | |
|
e92390c5fb | |
|
1e752e2293 | |
|
51c60978b0 | |
|
8f079fbb6c | |
|
16fa7681c3 | |
|
46d1619226 | |
|
8c291c5677 | |
|
ec726f409d | |
|
5139682d94 | |
|
6d4e2ba5df | |
|
583cbb6dfd | |
|
566711b9b9 | |
|
f1ee1338e0 | |
|
83a00bc1ab | |
|
f405860ca0 | |
|
3d58c274f1 | |
|
a3484d8199 | |
|
1f401f745b | |
|
adb236cb13 | |
|
1220aa36aa | |
|
21a24919f5 | |
|
df0d2135ce | |
|
9ed9eb7c45 | |
|
e4302a2b09 | |
|
a174191dfd | |
|
b5b3868f21 | |
|
7137ecbd58 | |
|
6452b9a4db | |
|
495b903b08 | |
|
b96c2c0282 | |
|
3055c413af | |
|
b4bedf8053 | |
|
be2bd2e073 | |
|
b1ee45f5c7 | |
|
601e14e667 | |
|
194e6ce729 | |
|
ba38666a08 | |
|
eb1ca82ebd | |
|
343f7c4344 | |
|
aad0f974f2 | |
|
2e0cd39144 | |
|
203bc9c4ef | |
|
2199648fc8 | |
|
b489376173 | |
|
7c309e74e6 | |
|
0ccf222961 | |
|
56d703e106 | |
|
24d3b3519e | |
|
e7ebaec3b4 | |
|
357a886c44 | |
|
d76f68242b | |
|
98faccfdb6 | |
|
5a4d18a7d0 | |
|
0e7803459f | |
|
a64852414f | |
|
9b251271cc | |
|
94f6005b3f | |
|
3c2fe176ab | |
|
a5609cb39f | |
|
e67ee94f2c | |
|
98341b6c68 | |
|
69b57c9b4d | |
|
cf8514a651 | |
|
721f0dbb33 | |
|
4690724d0f | |
|
6938c21f0b | |
|
3fcfd2761a | |
|
553b6f090f | |
|
7d6435bfdc | |
|
6d5b470689 | |
|
ab756cbbaa | |
|
3e7d5660ba | |
|
f244684852 | |
|
413775f4e3 | |
|
6f98ce7512 | |
|
a979406458 | |
|
60b7f106cc | |
|
ba3ca1d0ac | |
|
039d2a5a8d | |
|
cccd53a808 | |
|
9338656050 | |
|
cc693296f2 | |
|
939ed8cac4 | |
|
0b2ed364aa | |
|
315bd6c458 | |
|
243b4ca640 | |
|
1c5e4f407b | |
|
7124cda302 | |
|
0a5a6d545f | |
|
e6f576c226 | |
|
465a07811f | |
|
360b4b5fef | |
|
c156700b23 | |
|
f605cf145e | |
|
2a93a3eddb | |
|
422e90f610 | |
|
bc8c4d08b4 | |
|
052c2c4268 | |
|
beabccd65a | |
|
b56ed1c88d | |
|
a13e198944 | |
|
1b469c82ee | |
|
83e260592e | |
|
6ba7f31490 | |
|
5447726540 | |
|
40891eba8c | |
|
dcd1f1fe0a | |
|
713d7298f6 | |
|
a7ae18608a | |
|
65b78e6e13 | |
|
219c305e1c | |
|
eb81c74b31 | |
|
eb7654ec33 | |
|
ec9cdf07d5 | |
|
d01f5a4fd6 | |
|
af023e8f62 | |
|
3da7dc6e2b | |
|
07119058a1 | |
|
bc135a1993 | |
|
f8374000f2 | |
|
9d3e51f876 | |
|
9ec69b27e2 | |
|
7f58925139 | |
|
980c90b31a | |
|
add9f8d32e | |
|
f75d088332 | |
|
b161681273 | |
|
f4ef78c080 | |
|
9ad4ce3929 | |
|
884eadd4f8 | |
|
a266232f5c | |
|
f97efcfbf9 | |
|
5ae789beac | |
|
71c23b5b34 | |
|
6401d70aab | |
|
67e8909cc6 | |
|
21f251affc | |
|
07cad18854 | |
|
be010b4293 | |
|
f719196635 | |
|
9607a71381 | |
|
d398f07826 | |
|
31aab9fb7e | |
|
49ed152c8e | |
|
b61a9ce7bd | |
|
3a136a8631 | |
|
b312880b69 | |
|
795794e081 | |
|
1edf6180e0 | |
|
8e66ad4089 | |
|
7c79b598ea | |
|
24a38e0d6d | |
|
70e1ff84cb | |
|
0828e0e718 | |
|
56f72fcef0 | |
|
f169e16aaa | |
|
fa178e4710 | |
|
a4bf4e934e | |
|
2bbd6e81e1 | |
|
f6d32ad023 | |
|
b4595c8bf9 | |
|
dd4fa0671b | |
|
4e3538592e | |
|
bb984efc56 | |
|
722888132b | |
|
17780b56b7 | |
|
39857b3b45 | |
|
5fcc728422 | |
|
9fb8721eb9 | |
|
4e3c9375bb | |
|
4b59a429db |
|
@ -1,2 +1,12 @@
|
|||
/coverage
|
||||
/node_modules
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
/dist/**
|
||||
/coverage/**
|
||||
/node_modules/**
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"jest",
|
||||
"prettier"
|
||||
]
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
/.yarn/releases/** binary
|
||||
/.yarn/plugins/** binary
|
||||
/dist/** linguist-generated=true
|
||||
/lib/** linguist-generated=true
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
* @crazy-max
|
|
@ -0,0 +1,3 @@
|
|||
# Code of conduct
|
||||
|
||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
|
@ -0,0 +1,101 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Bug Report
|
||||
description: Report a bug
|
||||
labels:
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report a bug!
|
||||
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Contributing guidelines
|
||||
description: >
|
||||
Make sure you've read the contributing guidelines before proceeding.
|
||||
options:
|
||||
- label: I've read the [contributing guidelines](https://github.com/docker/login-action/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "I've found a bug, and:"
|
||||
description: |
|
||||
Make sure that your request fulfills all of the following requirements.
|
||||
If one requirement cannot be satisfied, explain in detail why.
|
||||
options:
|
||||
- label: The documentation does not mention anything about my problem
|
||||
- label: There are no open or closed issues that are related to my problem
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: >
|
||||
Provide a brief description of the bug in 1-2 sentences.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: >
|
||||
Describe precisely what you'd expect to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual behaviour
|
||||
description: >
|
||||
Describe precisely what is actually happening.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Repository URL
|
||||
description: >
|
||||
Enter the URL of the repository where you are experiencing the
|
||||
issue. If your repository is private, provide a link to a minimal
|
||||
repository that reproduces the issue.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Workflow run URL
|
||||
description: >
|
||||
Enter the URL of the GitHub Action workflow run if public (e.g.
|
||||
`https://github.com/<user>/<repo>/actions/runs/<id>`)
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: YAML workflow
|
||||
description: |
|
||||
Provide the YAML of the workflow that's causing the issue.
|
||||
Make sure to remove any sensitive information.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Workflow logs
|
||||
description: >
|
||||
[Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files)
|
||||
the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||
and make sure to remove any sensitive information.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: BuildKit logs
|
||||
description: >
|
||||
If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs)
|
||||
render: text
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: |
|
||||
Provide any additional information that could be useful.
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
### Behaviour
|
||||
|
||||
#### Steps to reproduce this issue
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
#### Expected behaviour
|
||||
|
||||
> Tell us what should happen
|
||||
|
||||
#### Actual behaviour
|
||||
|
||||
> Tell us what happens instead
|
||||
|
||||
### Configuration
|
||||
|
||||
* Repository URL (if public):
|
||||
* Build URL (if public):
|
||||
|
||||
```yml
|
||||
# paste your YAML workflow file here and remove sensitive data
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
> Download the [log file of your build](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||
> and [attach it](https://docs.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.
|
|
@ -0,0 +1,9 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Questions and Discussions
|
||||
url: https://github.com/docker/login-action/discussions/new
|
||||
about: Use Github Discussions to ask questions and/or open discussion topics.
|
||||
- name: Documentation
|
||||
url: https://docs.docker.com/build/ci/github-actions/
|
||||
about: Read the documentation.
|
|
@ -0,0 +1,15 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Feature request
|
||||
description: Missing functionality? Come tell us about it!
|
||||
labels:
|
||||
- kind/enhancement
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What is the feature you want to see?
|
||||
validations:
|
||||
required: true
|
|
@ -0,0 +1,12 @@
|
|||
# Reporting security issues
|
||||
|
||||
The project maintainers take security seriously. If you discover a security
|
||||
issue, please bring it to their attention right away!
|
||||
|
||||
**Please _DO NOT_ file a public issue**, instead send your report privately to
|
||||
[security@docker.com](mailto:security@docker.com).
|
||||
|
||||
Security reports are greatly appreciated, and we will publicly thank you for it.
|
||||
We also like to send gifts—if you'd like Docker swag, make sure to let
|
||||
us know. We currently do not offer a paid security bounty program, but are not
|
||||
ruling it out in the future.
|
|
@ -1,29 +0,0 @@
|
|||
# Support [](https://isitmaintained.com/project/docker/login-action)
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Please do a search in [open issues](https://github.com/docker/login-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||
|
||||
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||
|
||||
:+1: - upvote
|
||||
|
||||
:-1: - downvote
|
||||
|
||||
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||
|
||||
## Writing good bug reports and feature requests
|
||||
|
||||
File a single issue per problem and feature request.
|
||||
|
||||
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||
|
||||
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||
|
||||
You are now ready to [create a new issue](https://github.com/docker/login-action/issues/new/choose)!
|
||||
|
||||
## Closure policy
|
||||
|
||||
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||
* Issues that go a week without a response from original poster are subject to closure at our discretion.
|
|
@ -11,6 +11,14 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: "increase"
|
||||
groups:
|
||||
aws-sdk-dependencies:
|
||||
patterns:
|
||||
- "*aws-sdk*"
|
||||
proxy-agent-dependencies:
|
||||
patterns:
|
||||
- "*-proxy-agent"
|
||||
allow:
|
||||
- dependency-type: "production"
|
||||
labels:
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
name: ci
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
|
@ -15,7 +19,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Stop docker
|
||||
run: |
|
||||
|
@ -39,7 +43,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to GitHub Container Registry
|
||||
uses: ./
|
||||
|
@ -56,7 +60,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to GitHub Container Registry
|
||||
uses: ./
|
||||
|
@ -81,7 +85,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to ACR
|
||||
uses: ./
|
||||
|
@ -101,7 +105,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: ./
|
||||
|
@ -120,7 +124,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to ECR
|
||||
uses: ./
|
||||
|
@ -140,10 +144,10 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
|
@ -165,9 +169,10 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to Public ECR
|
||||
continue-on-error: ${{ matrix.os == 'windows-latest' }}
|
||||
uses: ./
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
|
@ -187,16 +192,17 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
-
|
||||
name: Login to ECR
|
||||
name: Login to Public ECR
|
||||
continue-on-error: ${{ matrix.os == 'windows-latest' }}
|
||||
uses: ./
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
|
@ -212,7 +218,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to GitHub Container Registry
|
||||
uses: ./
|
||||
|
@ -232,7 +238,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to GitLab
|
||||
uses: ./
|
||||
|
@ -252,7 +258,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to Google Artifact Registry
|
||||
uses: ./
|
||||
|
@ -272,7 +278,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Login to Google Container Registry
|
||||
uses: ./
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
name: codeql
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
paths:
|
||||
- '.github/workflows/codeql.yml'
|
||||
- 'dist/**'
|
||||
- 'src/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/codeql.yml'
|
||||
- 'dist/**'
|
||||
- 'src/**'
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language:
|
||||
- javascript-typescript
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config: |
|
||||
paths:
|
||||
- src
|
||||
-
|
||||
name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
-
|
||||
name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
|
@ -1,14 +1,15 @@
|
|||
name: test
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
@ -16,19 +17,15 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v1
|
||||
with:
|
||||
targets: validate
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v1
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
targets: test
|
||||
-
|
||||
name: Upload coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
file: ./coverage/clover.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
name: validate
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
targets: ${{ steps.targets.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Targets matrix
|
||||
id: targets
|
||||
run: |
|
||||
echo "matrix=$(docker buildx bake validate --print | jq -cr '.group.validate.targets')" >> $GITHUB_OUTPUT
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v4
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
|
@ -1,12 +1,5 @@
|
|||
/.dev
|
||||
node_modules/
|
||||
lib
|
||||
# https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
|
||||
# Jetbrains
|
||||
/.idea
|
||||
/*.iml
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
@ -14,6 +7,7 @@ npm-debug.log*
|
|||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
@ -24,34 +18,14 @@ pids
|
|||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
|
@ -61,36 +35,19 @@ typings/
|
|||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.test
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,13 @@
|
|||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
- code: YN0019
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
212
README.md
212
README.md
|
@ -1,7 +1,7 @@
|
|||
[](https://github.com/docker/login-action/releases/latest)
|
||||
[](https://github.com/marketplace/actions/docker-login)
|
||||
[](https://github.com/docker/login-action/actions?workflow=ci)
|
||||
[](https://github.com/docker/login-action/actions?workflow=test)
|
||||
[](https://github.com/docker/login-action/actions?workflow=ci)
|
||||
[](https://github.com/docker/login-action/actions?workflow=test)
|
||||
[](https://codecov.io/gh/docker/login-action)
|
||||
|
||||
## About
|
||||
|
@ -23,16 +23,18 @@ ___
|
|||
* [AWS Public Elastic Container Registry (ECR)](#aws-public-elastic-container-registry-ecr)
|
||||
* [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir)
|
||||
* [Quay.io](#quayio)
|
||||
* [DigitalOcean](#digitalocean-container-registry)
|
||||
* [Customizing](#customizing)
|
||||
* [inputs](#inputs)
|
||||
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
|
||||
* [Contributing](#contributing)
|
||||
|
||||
## Usage
|
||||
|
||||
### Docker Hub
|
||||
|
||||
To authenticate against [Docker Hub](https://hub.docker.com) it's strongly recommended to create a
|
||||
[personal access token](https://docs.docker.com/docker-hub/access-tokens/) as an alternative to your password.
|
||||
When authenticating to [Docker Hub](https://hub.docker.com) with GitHub Actions,
|
||||
use a [personal access token](https://docs.docker.com/docker-hub/access-tokens/).
|
||||
Don't use your account password.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -47,7 +49,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
@ -55,9 +57,9 @@ jobs:
|
|||
|
||||
### GitHub Container Registry
|
||||
|
||||
To authenticate against the [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry),
|
||||
use the [`GITHUB_TOKEN`](https://docs.github.com/en/actions/reference/authentication-in-a-workflow) for the best
|
||||
security and experience.
|
||||
To authenticate to the [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry),
|
||||
use the [`GITHUB_TOKEN`](https://docs.github.com/en/actions/reference/authentication-in-a-workflow)
|
||||
secret.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -72,7 +74,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
@ -100,18 +102,23 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to GitLab
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.gitlab.com
|
||||
username: ${{ secrets.GITLAB_USERNAME }}
|
||||
password: ${{ secrets.GITLAB_PASSWORD }}
|
||||
```
|
||||
|
||||
If you have [Two-Factor Authentication](https://gitlab.com/help/user/profile/account/two_factor_authentication)
|
||||
enabled, use a [Personal Access Token](https://gitlab.com/help/user/profile/personal_access_tokens)
|
||||
instead of a password.
|
||||
|
||||
### Azure Container Registry (ACR)
|
||||
|
||||
[Create a service principal](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal#create-a-service-principal)
|
||||
with access to your container registry through the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
|
||||
and take note of the generated service principal's ID (also called _client ID_) and password (also called _client secret_).
|
||||
and take note of the generated service principal's ID (also called _client ID_)
|
||||
and password (also called _client secret_).
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -126,7 +133,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to ACR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <registry-name>.azurecr.io
|
||||
username: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
|
@ -137,16 +144,21 @@ jobs:
|
|||
|
||||
### Google Container Registry (GCR)
|
||||
|
||||
> [Google Artifact Registry](#google-artifact-registry-gar) is the evolution of Google Container Registry. As a
|
||||
> fully-managed service with support for both container images and non-container artifacts. If you currently use
|
||||
> Google Container Registry, use the information [on this page](https://cloud.google.com/artifact-registry/docs/transition/transition-from-gcr)
|
||||
> [Google Artifact Registry](#google-artifact-registry-gar) is the evolution of
|
||||
> Google Container Registry. As a fully-managed service with support for both
|
||||
> container images and non-container artifacts. If you currently use Google
|
||||
> Container Registry, use the information [on this page](https://cloud.google.com/artifact-registry/docs/transition/transition-from-gcr)
|
||||
> to learn about transitioning to Google Artifact Registry.
|
||||
|
||||
You can use either workload identity federation based keyless authentication or service account based authentication.
|
||||
You can authenticate with workload identity federation or a service account.
|
||||
|
||||
#### Workload identity federation based authentication
|
||||
#### Workload identity federation
|
||||
|
||||
Configure the workload identity federation for github actions in gcloud (for steps, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation)). In the steps, your service account should the ability to push to GCR. Then use google-github-actions/auth action for authentication using workload identity like below:
|
||||
Configure the workload identity federation for GitHub Actions in Google Cloud,
|
||||
[see here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
|
||||
Your service account must have permission to push to GCR. Use the
|
||||
`google-github-actions/auth` action to authenticate using workload identity as
|
||||
shown in the following example:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -159,32 +171,35 @@ jobs:
|
|||
login:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: 'auth'
|
||||
name: 'Authenticate to Google Cloud'
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
-
|
||||
name: Authenticate to Google Cloud
|
||||
id: auth
|
||||
uses: google-github-actions/auth@v1
|
||||
with:
|
||||
token_format: 'access_token'
|
||||
workload_identity_provider: '<workload_identity_provider>'
|
||||
service_account: '<service_account>'
|
||||
|
||||
- name: Login to GCR
|
||||
uses: docker/login-action@v1
|
||||
token_format: access_token
|
||||
workload_identity_provider: <workload_identity_provider>
|
||||
service_account: <service_account>
|
||||
-
|
||||
name: Login to GCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: gcr.io
|
||||
username: oauth2accesstoken
|
||||
password: ${{ steps.auth.outputs.access_token }}
|
||||
```
|
||||
|
||||
> Replace `<workload_identity_provider>` with configured workload identity provider. For steps to configure, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
|
||||
> Replace `<workload_identity_provider>` with configured workload identity
|
||||
> provider. For steps to configure, [see here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation).
|
||||
|
||||
> Replace `<service_account>` with configured service account in workload identity provider which has access to push to GCR
|
||||
> Replace `<service_account>` with configured service account in workload
|
||||
> identity provider which has access to push to GCR
|
||||
|
||||
#### Service account based authentication
|
||||
|
||||
Use a service account with the ability to push to GCR and [configure access control](https://cloud.google.com/container-registry/docs/access-control).
|
||||
Then create and download the JSON key for this service account and save content of `.json` file
|
||||
[as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
called `GCR_JSON_KEY` in your GitHub repo. Ensure you set the username to `_json_key`,
|
||||
Use a service account with permission to push to GCR and [configure access control](https://cloud.google.com/container-registry/docs/access-control).
|
||||
Download the key for the service account as a JSON file. Save the contents of
|
||||
the file [as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
named `GCR_JSON_KEY` in your GitHub repository. Set the username to `_json_key`,
|
||||
or `_json_key_base64` if you use a base64-encoded key.
|
||||
|
||||
```yaml
|
||||
|
@ -200,7 +215,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to GCR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: gcr.io
|
||||
username: _json_key
|
||||
|
@ -209,11 +224,13 @@ jobs:
|
|||
|
||||
### Google Artifact Registry (GAR)
|
||||
|
||||
You can use either workload identity federation based keyless authentication or service account based authentication.
|
||||
You can authenticate with workload identity federation or a service account.
|
||||
|
||||
#### Workload identity federation based authentication
|
||||
#### Workload identity federation
|
||||
|
||||
Configure the workload identity federation for github actions in gcloud (for steps, [refer here](https://github.com/google-github-actions/auth#setting-up-workload-identity-federation)). In the steps, your service account should the ability to push to GAR. Then use google-github-actions/auth action for authentication using workload identity like below:
|
||||
Your service account must have permission to push to GAR. Use the
|
||||
`google-github-actions/auth` action to authenticate using workload identity as
|
||||
shown in the following example:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -226,34 +243,38 @@ jobs:
|
|||
login:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: 'auth'
|
||||
name: 'Authenticate to Google Cloud'
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
-
|
||||
name: Authenticate to Google Cloud
|
||||
id: auth
|
||||
uses: google-github-actions/auth@v1
|
||||
with:
|
||||
token_format: 'access_token'
|
||||
workload_identity_provider: '<workload_identity_provider>'
|
||||
service_account: '<service_account>'
|
||||
|
||||
- name: Login to GAR
|
||||
uses: docker/login-action@v1
|
||||
token_format: access_token
|
||||
workload_identity_provider: <workload_identity_provider>
|
||||
service_account: <service_account>
|
||||
-
|
||||
name: Login to GAR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <location>-docker.pkg.dev
|
||||
username: oauth2accesstoken
|
||||
password: ${{ steps.auth.outputs.access_token }}
|
||||
```
|
||||
> Replace `<workload_identity_provider>` with configured workload identity provider
|
||||
|
||||
> Replace `<service_account>` with configured service account in workload identity provider which has access to push to GCR
|
||||
> Replace `<workload_identity_provider>` with configured workload identity
|
||||
> provider
|
||||
|
||||
> Replace `<service_account>` with configured service account in workload
|
||||
> identity provider which has access to push to GCR
|
||||
|
||||
> Replace `<location>` with the regional or multi-regional [location](https://cloud.google.com/artifact-registry/docs/repo-organize#locations)
|
||||
> of the repository where the image is stored.
|
||||
|
||||
#### Service account based authentication
|
||||
|
||||
Use a service account with the ability to push to GAR and [configure access control](https://cloud.google.com/artifact-registry/docs/access-control).
|
||||
Then create and download the JSON key for this service account and save content of `.json` file
|
||||
[as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
called `GAR_JSON_KEY` in your GitHub repo. Ensure you set the username to `_json_key`,
|
||||
Use a service account with permission to push to GAR and [configure access control](https://cloud.google.com/artifact-registry/docs/access-control).
|
||||
Download the key for the service account as a JSON file. Save the contents of
|
||||
the file [as a secret](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
named `GAR_JSON_KEY` in your GitHub repository. Set the username to `_json_key`,
|
||||
or `_json_key_base64` if you use a base64-encoded key.
|
||||
|
||||
```yaml
|
||||
|
@ -269,7 +290,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to GAR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <location>-docker.pkg.dev
|
||||
username: _json_key
|
||||
|
@ -282,7 +303,7 @@ jobs:
|
|||
### AWS Elastic Container Registry (ECR)
|
||||
|
||||
Use an IAM user with the ability to [push to ECR with `AmazonEC2ContainerRegistryPowerUser` managed policy for example](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr_managed_policies.html#AmazonEC2ContainerRegistryPowerUser).
|
||||
Then create and download access keys and save `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
Download the access keys and save them as `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
in your GitHub repo.
|
||||
|
||||
```yaml
|
||||
|
@ -298,15 +319,15 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to ECR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
|
||||
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
```
|
||||
|
||||
If you need to log in to Amazon ECR registries associated with other accounts, you can use the `AWS_ACCOUNT_IDS`
|
||||
environment variable:
|
||||
If you need to log in to Amazon ECR registries associated with other accounts,
|
||||
you can use the `AWS_ACCOUNT_IDS` environment variable:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -321,7 +342,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to ECR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
|
||||
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
|
@ -332,8 +353,8 @@ jobs:
|
|||
|
||||
> Only available with [AWS CLI version 1](https://docs.aws.amazon.com/cli/latest/reference/ecr/get-login.html)
|
||||
|
||||
You can also use the [Configure AWS Credentials](https://github.com/aws-actions/configure-aws-credentials) action in
|
||||
combination with this action:
|
||||
You can also use the [Configure AWS Credentials](https://github.com/aws-actions/configure-aws-credentials)
|
||||
action in combination with this action:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -348,14 +369,14 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: <region>
|
||||
-
|
||||
name: Login to ECR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <aws-account-number>.dkr.ecr.<region>.amazonaws.com
|
||||
```
|
||||
|
@ -364,9 +385,10 @@ jobs:
|
|||
|
||||
### AWS Public Elastic Container Registry (ECR)
|
||||
|
||||
Use an IAM user with the ability to [push to ECR Public with `AmazonElasticContainerRegistryPublicPowerUser` managed policy for example](https://docs.aws.amazon.com/AmazonECR/latest/public/public-ecr-managed-policies.html#AmazonElasticContainerRegistryPublicPowerUser).
|
||||
Then create and download access keys and save `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [as secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
in your GitHub repo.
|
||||
Use an IAM user with permission to push to ECR Public, for example using [managed policies](https://docs.aws.amazon.com/AmazonECR/latest/userguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonEC2ContainerRegistryPowerUser).
|
||||
Download the access keys and save them as `AWS_ACCESS_KEY_ID` and
|
||||
`AWS_SECRET_ACCESS_KEY` [secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
|
||||
in your GitHub repository.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -381,7 +403,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to Public ECR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: public.ecr.aws
|
||||
username: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
|
@ -415,7 +437,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to OCIR
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: <region>.ocir.io
|
||||
username: ${{ secrets.OCI_USERNAME }}
|
||||
|
@ -426,7 +448,8 @@ jobs:
|
|||
|
||||
### Quay.io
|
||||
|
||||
Use a [Robot account](https://docs.quay.io/glossary/robot-accounts.html) with the ability to push to a public/private Quay.io repository.
|
||||
Use a [Robot account](https://docs.quay.io/glossary/robot-accounts.html) with
|
||||
permission to push to a Quay.io repository.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -441,39 +464,52 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Login to Quay.io
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: quay.io
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
||||
```
|
||||
|
||||
### DigitalOcean Container Registry
|
||||
|
||||
Use your DigitalOcean registered email address and an API access token to authenticate.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: main
|
||||
|
||||
jobs:
|
||||
login:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Login to DigitalOcean Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.digitalocean.com
|
||||
username: ${{ secrets.DIGITALOCEAN_USERNAME }}
|
||||
password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
|
||||
```
|
||||
|
||||
## Customizing
|
||||
|
||||
### inputs
|
||||
|
||||
Following inputs can be used as `step.with` keys
|
||||
The following inputs can be used as `step.with` keys:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|------------------|---------|-----------------------------|------------------------------------|
|
||||
|------------|--------|---------|-------------------------------------------------------------------------------|
|
||||
| `registry` | String | | Server address of Docker registry. If not set then will default to Docker Hub |
|
||||
| `username` | String | | Username used to log against the Docker registry |
|
||||
| `password` | String | | Password or personal access token used to log against the Docker registry |
|
||||
| `username` | String | | Username for authenticating to the Docker registry |
|
||||
| `password` | String | | Password or personal access token for authenticating the Docker registry |
|
||||
| `ecr` | String | `auto` | Specifies whether the given registry is ECR (`auto`, `true` or `false`) |
|
||||
| `logout` | Bool | `true` | Log out from the Docker registry at the end of a job |
|
||||
|
||||
## Keep up-to-date with GitHub Dependabot
|
||||
## Contributing
|
||||
|
||||
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
|
||||
has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem),
|
||||
to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file:
|
||||
|
||||
```yaml
|
||||
version: 2
|
||||
updates:
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
```
|
||||
Want to contribute? Awesome! You can find information about contributing to
|
||||
this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
|
||||
import {AuthorizationData} from '@aws-sdk/client-ecr';
|
||||
|
||||
import * as aws from '../src/aws';
|
||||
|
||||
describe('isECR', () => {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import {expect, test} from '@jest/globals';
|
||||
|
||||
import {getInputs} from '../src/context';
|
||||
|
||||
test('with password and username getInputs does not throw error', async () => {
|
||||
|
@ -6,5 +8,5 @@ test('with password and username getInputs does not throw error', async () => {
|
|||
process.env['INPUT_LOGOUT'] = 'true';
|
||||
expect(() => {
|
||||
getInputs();
|
||||
}).not.toThrowError();
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
import {loginStandard, logout} from '../src/docker';
|
||||
|
||||
import {expect, jest, test} from '@jest/globals';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as exec from '@actions/exec';
|
||||
import {loginStandard, logout} from '../src/docker';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
||||
|
||||
process.env['RUNNER_TEMP'] = path.join(__dirname, 'runner');
|
||||
|
||||
test('loginStandard calls exec', async () => {
|
||||
const execSpy: jest.SpyInstance = jest.spyOn(exec, 'getExecOutput');
|
||||
execSpy.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput').mockImplementation(async () => {
|
||||
return {
|
||||
exitCode: expect.any(Number),
|
||||
stdout: expect.any(Function),
|
||||
stderr: expect.any(Function)
|
||||
})
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
const username: string = 'dbowie';
|
||||
const password: string = 'groundcontrol';
|
||||
const registry: string = 'https://ghcr.io';
|
||||
const username = 'dbowie';
|
||||
const password = 'groundcontrol';
|
||||
const registry = 'https://ghcr.io';
|
||||
|
||||
await loginStandard(registry, username, password);
|
||||
|
||||
|
@ -30,16 +31,17 @@ test('loginStandard calls exec', async () => {
|
|||
});
|
||||
|
||||
test('logout calls exec', async () => {
|
||||
const execSpy: jest.SpyInstance = jest.spyOn(exec, 'getExecOutput');
|
||||
execSpy.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const execSpy = jest.spyOn(Exec, 'getExecOutput').mockImplementation(async () => {
|
||||
return {
|
||||
exitCode: expect.any(Number),
|
||||
stdout: expect.any(Function),
|
||||
stderr: expect.any(Function)
|
||||
})
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
const registry: string = 'https://ghcr.io';
|
||||
const registry = 'https://ghcr.io';
|
||||
|
||||
await logout(registry);
|
||||
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
import osm = require('os');
|
||||
|
||||
import {run} from '../src/main';
|
||||
import * as docker from '../src/docker';
|
||||
import * as stateHelper from '../src/state-helper';
|
||||
|
||||
import * as core from '@actions/core';
|
||||
|
||||
test('errors without username and password', async () => {
|
||||
const platSpy = jest.spyOn(osm, 'platform');
|
||||
platSpy.mockImplementation(() => 'linux');
|
||||
|
||||
process.env['INPUT_LOGOUT'] = 'true'; // default value
|
||||
|
||||
const coreSpy: jest.SpyInstance = jest.spyOn(core, 'setFailed');
|
||||
|
||||
await run();
|
||||
|
||||
expect(coreSpy).toHaveBeenCalledWith('Username and password required');
|
||||
});
|
||||
|
||||
test('successful with username and password', async () => {
|
||||
const platSpy = jest.spyOn(osm, 'platform');
|
||||
platSpy.mockImplementation(() => 'linux');
|
||||
|
||||
const setRegistrySpy: jest.SpyInstance = jest.spyOn(stateHelper, 'setRegistry');
|
||||
const setLogoutSpy: jest.SpyInstance = jest.spyOn(stateHelper, 'setLogout');
|
||||
const dockerSpy: jest.SpyInstance = jest.spyOn(docker, 'login');
|
||||
dockerSpy.mockImplementation(() => {});
|
||||
|
||||
const username: string = 'dbowie';
|
||||
process.env[`INPUT_USERNAME`] = username;
|
||||
|
||||
const password: string = 'groundcontrol';
|
||||
process.env[`INPUT_PASSWORD`] = password;
|
||||
|
||||
const ecr: string = 'auto';
|
||||
process.env['INPUT_ECR'] = ecr;
|
||||
|
||||
const logout: boolean = false;
|
||||
process.env['INPUT_LOGOUT'] = String(logout);
|
||||
|
||||
await run();
|
||||
|
||||
expect(setRegistrySpy).toHaveBeenCalledWith('');
|
||||
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
|
||||
expect(dockerSpy).toHaveBeenCalledWith('', username, password, ecr);
|
||||
});
|
||||
|
||||
test('calls docker login', async () => {
|
||||
const platSpy = jest.spyOn(osm, 'platform');
|
||||
platSpy.mockImplementation(() => 'linux');
|
||||
|
||||
const setRegistrySpy: jest.SpyInstance = jest.spyOn(stateHelper, 'setRegistry');
|
||||
const setLogoutSpy: jest.SpyInstance = jest.spyOn(stateHelper, 'setLogout');
|
||||
const dockerSpy: jest.SpyInstance = jest.spyOn(docker, 'login');
|
||||
dockerSpy.mockImplementation(() => {});
|
||||
|
||||
const username: string = 'dbowie';
|
||||
process.env[`INPUT_USERNAME`] = username;
|
||||
|
||||
const password: string = 'groundcontrol';
|
||||
process.env[`INPUT_PASSWORD`] = password;
|
||||
|
||||
const registry: string = 'ghcr.io';
|
||||
process.env[`INPUT_REGISTRY`] = registry;
|
||||
|
||||
const ecr: string = 'auto';
|
||||
process.env['INPUT_ECR'] = ecr;
|
||||
|
||||
const logout: boolean = true;
|
||||
process.env['INPUT_LOGOUT'] = String(logout);
|
||||
|
||||
await run();
|
||||
|
||||
expect(setRegistrySpy).toHaveBeenCalledWith(registry);
|
||||
expect(setLogoutSpy).toHaveBeenCalledWith(logout);
|
||||
expect(dockerSpy).toHaveBeenCalledWith(registry, username, password, ecr);
|
||||
});
|
|
@ -26,6 +26,6 @@ inputs:
|
|||
required: false
|
||||
|
||||
runs:
|
||||
using: 'node12'
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
post: 'dist/index.js'
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
# syntax=docker/dockerfile:1.3-labs
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG NODE_VERSION
|
||||
ARG DOCKER_VERSION=20.10.10
|
||||
ARG BUILDX_VERSION=0.7.0
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
WORKDIR /src
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache <<EOT
|
||||
corepack enable
|
||||
yarn --version
|
||||
yarn config set --home enableTelemetry 0
|
||||
EOT
|
||||
|
||||
FROM base AS deps
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
||||
|
||||
|
@ -18,18 +23,19 @@ COPY --from=deps /vendor /
|
|||
|
||||
FROM deps AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
|
||||
git status --porcelain -- yarn.lock
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS build
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run build && mkdir /out && cp -Rf dist /out/
|
||||
|
||||
|
@ -38,41 +44,39 @@ COPY --from=build /out /
|
|||
|
||||
FROM build AS build-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||
git status --porcelain -- dist
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS format
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run format \
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
|
||||
|
||||
FROM scratch AS format-update
|
||||
COPY --from=format /out /
|
||||
|
||||
FROM deps AS format-validate
|
||||
FROM deps AS lint
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run format-check
|
||||
|
||||
FROM docker:${DOCKER_VERSION} as docker
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
|
||||
yarn run lint
|
||||
|
||||
FROM deps AS test
|
||||
ENV RUNNER_TEMP=/tmp/github_runner
|
||||
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
|
||||
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
|
||||
yarn run test --coverageDirectory=/tmp/coverage
|
||||
yarn run test --coverage --coverageDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
|
@ -1,984 +0,0 @@
|
|||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 989:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* __ ___ ____ _ _ ___ _ _ ____
|
||||
* \ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
|
||||
* \ \ /\ / / _ \ | |_) | \| || || \| | | _
|
||||
* \ V V / ___ \| _ <| |\ || || |\ | |_| |
|
||||
* \_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
|
||||
*
|
||||
* This file is critical for vm2. It implements the bridge between the host and the sandbox.
|
||||
* If you do not know exactly what you are doing, you should NOT edit this file.
|
||||
*
|
||||
* The file is loaded in the host and sandbox to handle objects in both directions.
|
||||
* This is done to ensure that RangeErrors are from the correct context.
|
||||
* The boundary between the sandbox and host might throw RangeErrors from both contexts.
|
||||
* Therefore, thisFromOther and friends can handle objects from both domains.
|
||||
*
|
||||
* Method parameters have comments to tell from which context they came.
|
||||
*
|
||||
*/
|
||||
|
||||
const globalsList = [
|
||||
'Number',
|
||||
'String',
|
||||
'Boolean',
|
||||
'Date',
|
||||
'RegExp',
|
||||
'Map',
|
||||
'WeakMap',
|
||||
'Set',
|
||||
'WeakSet',
|
||||
'Promise',
|
||||
'Function'
|
||||
];
|
||||
|
||||
const errorsList = [
|
||||
'RangeError',
|
||||
'ReferenceError',
|
||||
'SyntaxError',
|
||||
'TypeError',
|
||||
'EvalError',
|
||||
'URIError',
|
||||
'Error'
|
||||
];
|
||||
|
||||
const OPNA = 'Operation not allowed on contextified object.';
|
||||
|
||||
const thisGlobalPrototypes = {
|
||||
__proto__: null,
|
||||
Object: Object.prototype,
|
||||
Array: Array.prototype
|
||||
};
|
||||
|
||||
for (let i = 0; i < globalsList.length; i++) {
|
||||
const key = globalsList[i];
|
||||
const g = global[key];
|
||||
if (g) thisGlobalPrototypes[key] = g.prototype;
|
||||
}
|
||||
|
||||
for (let i = 0; i < errorsList.length; i++) {
|
||||
const key = errorsList[i];
|
||||
const g = global[key];
|
||||
if (g) thisGlobalPrototypes[key] = g.prototype;
|
||||
}
|
||||
|
||||
const {
|
||||
getPrototypeOf: thisReflectGetPrototypeOf,
|
||||
setPrototypeOf: thisReflectSetPrototypeOf,
|
||||
defineProperty: thisReflectDefineProperty,
|
||||
deleteProperty: thisReflectDeleteProperty,
|
||||
getOwnPropertyDescriptor: thisReflectGetOwnPropertyDescriptor,
|
||||
isExtensible: thisReflectIsExtensible,
|
||||
preventExtensions: thisReflectPreventExtensions,
|
||||
apply: thisReflectApply,
|
||||
construct: thisReflectConstruct,
|
||||
set: thisReflectSet,
|
||||
get: thisReflectGet,
|
||||
has: thisReflectHas,
|
||||
ownKeys: thisReflectOwnKeys,
|
||||
enumerate: thisReflectEnumerate,
|
||||
} = Reflect;
|
||||
|
||||
const thisObject = Object;
|
||||
const {
|
||||
freeze: thisObjectFreeze,
|
||||
prototype: thisObjectPrototype
|
||||
} = thisObject;
|
||||
const thisObjectHasOwnProperty = thisObjectPrototype.hasOwnProperty;
|
||||
const ThisProxy = Proxy;
|
||||
const ThisWeakMap = WeakMap;
|
||||
const {
|
||||
get: thisWeakMapGet,
|
||||
set: thisWeakMapSet
|
||||
} = ThisWeakMap.prototype;
|
||||
const ThisMap = Map;
|
||||
const thisMapGet = ThisMap.prototype.get;
|
||||
const thisMapSet = ThisMap.prototype.set;
|
||||
const thisFunction = Function;
|
||||
const thisFunctionBind = thisFunction.prototype.bind;
|
||||
const thisArrayIsArray = Array.isArray;
|
||||
const thisErrorCaptureStackTrace = Error.captureStackTrace;
|
||||
|
||||
const thisSymbolToString = Symbol.prototype.toString;
|
||||
const thisSymbolToStringTag = Symbol.toStringTag;
|
||||
|
||||
/**
|
||||
* VMError.
|
||||
*
|
||||
* @public
|
||||
* @extends {Error}
|
||||
*/
|
||||
class VMError extends Error {
|
||||
|
||||
/**
|
||||
* Create VMError instance.
|
||||
*
|
||||
* @public
|
||||
* @param {string} message - Error message.
|
||||
* @param {string} code - Error code.
|
||||
*/
|
||||
constructor(message, code) {
|
||||
super(message);
|
||||
|
||||
this.name = 'VMError';
|
||||
this.code = code;
|
||||
|
||||
thisErrorCaptureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
thisGlobalPrototypes['VMError'] = VMError.prototype;
|
||||
|
||||
function thisUnexpected() {
|
||||
return new VMError('Unexpected');
|
||||
}
|
||||
|
||||
if (!thisReflectSetPrototypeOf(exports, null)) throw thisUnexpected();
|
||||
|
||||
function thisSafeGetOwnPropertyDescriptor(obj, key) {
|
||||
const desc = thisReflectGetOwnPropertyDescriptor(obj, key);
|
||||
if (!desc) return desc;
|
||||
if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected();
|
||||
return desc;
|
||||
}
|
||||
|
||||
function thisThrowCallerCalleeArgumentsAccess(key) {
|
||||
'use strict';
|
||||
thisThrowCallerCalleeArgumentsAccess[key];
|
||||
return thisUnexpected();
|
||||
}
|
||||
|
||||
function thisIdMapping(factory, other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
const thisThrowOnKeyAccessHandler = thisObjectFreeze({
|
||||
__proto__: null,
|
||||
get(target, key, receiver) {
|
||||
if (typeof key === 'symbol') {
|
||||
key = thisReflectApply(thisSymbolToString, key, []);
|
||||
}
|
||||
throw new VMError(`Unexpected access to key '${key}'`);
|
||||
}
|
||||
});
|
||||
|
||||
const emptyForzenObject = thisObjectFreeze({
|
||||
__proto__: null
|
||||
});
|
||||
|
||||
const thisThrowOnKeyAccess = new ThisProxy(emptyForzenObject, thisThrowOnKeyAccessHandler);
|
||||
|
||||
function SafeBase() {}
|
||||
|
||||
if (!thisReflectDefineProperty(SafeBase, 'prototype', {
|
||||
__proto__: null,
|
||||
value: thisThrowOnKeyAccess
|
||||
})) throw thisUnexpected();
|
||||
|
||||
function SHARED_FUNCTION() {}
|
||||
|
||||
const TEST_PROXY_HANDLER = thisObjectFreeze({
|
||||
__proto__: thisThrowOnKeyAccess,
|
||||
construct() {
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
function thisIsConstructor(obj) {
|
||||
// Note: obj@any(unsafe)
|
||||
const Func = new ThisProxy(obj, TEST_PROXY_HANDLER);
|
||||
try {
|
||||
// eslint-disable-next-line no-new
|
||||
new Func();
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function thisCreateTargetObject(obj, proto) {
|
||||
// Note: obj@any(unsafe) proto@any(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
let base;
|
||||
if (typeof obj === 'function') {
|
||||
if (thisIsConstructor(obj)) {
|
||||
// Bind the function since bound functions do not have a prototype property.
|
||||
base = thisReflectApply(thisFunctionBind, SHARED_FUNCTION, [null]);
|
||||
} else {
|
||||
base = () => {};
|
||||
}
|
||||
} else if (thisArrayIsArray(obj)) {
|
||||
base = [];
|
||||
} else {
|
||||
return {__proto__: proto};
|
||||
}
|
||||
if (!thisReflectSetPrototypeOf(base, proto)) throw thisUnexpected();
|
||||
return base;
|
||||
}
|
||||
|
||||
function createBridge(otherInit, registerProxy) {
|
||||
|
||||
const mappingOtherToThis = new ThisWeakMap();
|
||||
const protoMappings = new ThisMap();
|
||||
const protoName = new ThisMap();
|
||||
|
||||
function thisAddProtoMapping(proto, other, name) {
|
||||
// Note: proto@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe)
|
||||
thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]);
|
||||
thisReflectApply(thisMapSet, protoMappings, [other,
|
||||
(factory, object) => thisProxyOther(factory, object, proto)]);
|
||||
if (name) thisReflectApply(thisMapSet, protoName, [proto, name]);
|
||||
}
|
||||
|
||||
function thisAddProtoMappingFactory(protoFactory, other, name) {
|
||||
// Note: protoFactory@this(unsafe) other@other(unsafe) name@this(unsafe) throws@this(unsafe)
|
||||
let proto;
|
||||
thisReflectApply(thisMapSet, protoMappings, [other,
|
||||
(factory, object) => {
|
||||
if (!proto) {
|
||||
proto = protoFactory();
|
||||
thisReflectApply(thisMapSet, protoMappings, [proto, thisIdMapping]);
|
||||
if (name) thisReflectApply(thisMapSet, protoName, [proto, name]);
|
||||
}
|
||||
return thisProxyOther(factory, object, proto);
|
||||
}]);
|
||||
}
|
||||
|
||||
const result = {
|
||||
__proto__: null,
|
||||
globalPrototypes: thisGlobalPrototypes,
|
||||
safeGetOwnPropertyDescriptor: thisSafeGetOwnPropertyDescriptor,
|
||||
fromArguments: thisFromOtherArguments,
|
||||
from: thisFromOther,
|
||||
fromWithFactory: thisFromOtherWithFactory,
|
||||
ensureThis: thisEnsureThis,
|
||||
mapping: mappingOtherToThis,
|
||||
connect: thisConnect,
|
||||
reflectSet: thisReflectSet,
|
||||
reflectGet: thisReflectGet,
|
||||
reflectDefineProperty: thisReflectDefineProperty,
|
||||
reflectDeleteProperty: thisReflectDeleteProperty,
|
||||
reflectApply: thisReflectApply,
|
||||
reflectConstruct: thisReflectConstruct,
|
||||
reflectHas: thisReflectHas,
|
||||
reflectOwnKeys: thisReflectOwnKeys,
|
||||
reflectEnumerate: thisReflectEnumerate,
|
||||
reflectGetPrototypeOf: thisReflectGetPrototypeOf,
|
||||
reflectIsExtensible: thisReflectIsExtensible,
|
||||
reflectPreventExtensions: thisReflectPreventExtensions,
|
||||
objectHasOwnProperty: thisObjectHasOwnProperty,
|
||||
weakMapSet: thisWeakMapSet,
|
||||
addProtoMapping: thisAddProtoMapping,
|
||||
addProtoMappingFactory: thisAddProtoMappingFactory,
|
||||
defaultFactory,
|
||||
protectedFactory,
|
||||
readonlyFactory,
|
||||
VMError
|
||||
};
|
||||
|
||||
const isHost = typeof otherInit !== 'object';
|
||||
|
||||
if (isHost) {
|
||||
otherInit = otherInit(result, registerProxy);
|
||||
}
|
||||
|
||||
result.other = otherInit;
|
||||
|
||||
const {
|
||||
globalPrototypes: otherGlobalPrototypes,
|
||||
safeGetOwnPropertyDescriptor: otherSafeGetOwnPropertyDescriptor,
|
||||
fromArguments: otherFromThisArguments,
|
||||
from: otherFromThis,
|
||||
mapping: mappingThisToOther,
|
||||
reflectSet: otherReflectSet,
|
||||
reflectGet: otherReflectGet,
|
||||
reflectDefineProperty: otherReflectDefineProperty,
|
||||
reflectDeleteProperty: otherReflectDeleteProperty,
|
||||
reflectApply: otherReflectApply,
|
||||
reflectConstruct: otherReflectConstruct,
|
||||
reflectHas: otherReflectHas,
|
||||
reflectOwnKeys: otherReflectOwnKeys,
|
||||
reflectEnumerate: otherReflectEnumerate,
|
||||
reflectGetPrototypeOf: otherReflectGetPrototypeOf,
|
||||
reflectIsExtensible: otherReflectIsExtensible,
|
||||
reflectPreventExtensions: otherReflectPreventExtensions,
|
||||
objectHasOwnProperty: otherObjectHasOwnProperty,
|
||||
weakMapSet: otherWeakMapSet
|
||||
} = otherInit;
|
||||
|
||||
function thisOtherHasOwnProperty(object, key) {
|
||||
// Note: object@other(safe) key@prim throws@this(unsafe)
|
||||
try {
|
||||
return otherReflectApply(otherObjectHasOwnProperty, object, [key]) === true;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
}
|
||||
|
||||
function thisDefaultGet(handler, object, key, desc) {
|
||||
// Note: object@other(unsafe) key@prim desc@other(safe)
|
||||
let ret; // @other(unsafe)
|
||||
if (desc.get || desc.set) {
|
||||
const getter = desc.get;
|
||||
if (!getter) return undefined;
|
||||
try {
|
||||
ret = otherReflectApply(getter, object, [key]);
|
||||
} catch (e) {
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
} else {
|
||||
ret = desc.value;
|
||||
}
|
||||
return handler.fromOtherWithContext(ret);
|
||||
}
|
||||
|
||||
function otherFromThisIfAvailable(to, from, key) {
|
||||
// Note: to@other(safe) from@this(safe) key@prim throws@this(unsafe)
|
||||
if (!thisReflectApply(thisObjectHasOwnProperty, from, [key])) return false;
|
||||
try {
|
||||
to[key] = otherFromThis(from[key]);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class BaseHandler extends SafeBase {
|
||||
|
||||
constructor(object) {
|
||||
// Note: object@other(unsafe) throws@this(unsafe)
|
||||
super();
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
getFactory() {
|
||||
return defaultFactory;
|
||||
}
|
||||
|
||||
fromOtherWithContext(other) {
|
||||
// Note: other@other(unsafe) throws@this(unsafe)
|
||||
return thisFromOtherWithFactory(this.getFactory(), other);
|
||||
}
|
||||
|
||||
doPreventExtensions(target, object, factory) {
|
||||
// Note: target@this(unsafe) object@other(unsafe) throws@this(unsafe)
|
||||
let keys; // @other(safe-array-of-prim)
|
||||
try {
|
||||
keys = otherReflectOwnKeys(object);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]; // @prim
|
||||
let desc;
|
||||
try {
|
||||
desc = otherSafeGetOwnPropertyDescriptor(object, key);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
if (!desc) continue;
|
||||
if (!desc.configurable) {
|
||||
const current = thisSafeGetOwnPropertyDescriptor(target, key);
|
||||
if (current && !current.configurable) continue;
|
||||
if (desc.get || desc.set) {
|
||||
desc.get = this.fromOtherWithContext(desc.get);
|
||||
desc.set = this.fromOtherWithContext(desc.set);
|
||||
} else if (typeof object === 'function' && (key === 'caller' || key === 'callee' || key === 'arguments')) {
|
||||
desc.value = null;
|
||||
} else {
|
||||
desc.value = this.fromOtherWithContext(desc.value);
|
||||
}
|
||||
} else {
|
||||
if (desc.get || desc.set) {
|
||||
desc = {
|
||||
__proto__: null,
|
||||
configurable: true,
|
||||
enumerable: desc.enumerable,
|
||||
writable: true,
|
||||
value: null
|
||||
};
|
||||
} else {
|
||||
desc.value = null;
|
||||
}
|
||||
}
|
||||
if (!thisReflectDefineProperty(target, key, desc)) throw thisUnexpected();
|
||||
}
|
||||
if (!thisReflectPreventExtensions(target)) throw thisUnexpected();
|
||||
}
|
||||
|
||||
get(target, key, receiver) {
|
||||
// Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
switch (key) {
|
||||
case 'constructor': {
|
||||
const desc = otherSafeGetOwnPropertyDescriptor(object, key);
|
||||
if (desc) return thisDefaultGet(this, object, key, desc);
|
||||
const proto = thisReflectGetPrototypeOf(target);
|
||||
return proto === null ? undefined : proto.constructor;
|
||||
}
|
||||
case '__proto__': {
|
||||
const desc = otherSafeGetOwnPropertyDescriptor(object, key);
|
||||
if (desc) return thisDefaultGet(this, object, key, desc);
|
||||
return thisReflectGetPrototypeOf(target);
|
||||
}
|
||||
case thisSymbolToStringTag:
|
||||
if (!thisOtherHasOwnProperty(object, thisSymbolToStringTag)) {
|
||||
const proto = thisReflectGetPrototypeOf(target);
|
||||
const name = thisReflectApply(thisMapGet, protoName, [proto]);
|
||||
if (name) return name;
|
||||
}
|
||||
break;
|
||||
case 'arguments':
|
||||
case 'caller':
|
||||
case 'callee':
|
||||
if (thisOtherHasOwnProperty(object, key)) throw thisThrowCallerCalleeArgumentsAccess(key);
|
||||
break;
|
||||
}
|
||||
let ret; // @other(unsafe)
|
||||
try {
|
||||
ret = otherReflectGet(object, key);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return this.fromOtherWithContext(ret);
|
||||
}
|
||||
|
||||
set(target, key, value, receiver) {
|
||||
// Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
if (key === '__proto__' && !thisOtherHasOwnProperty(object, key)) {
|
||||
return this.setPrototypeOf(target, value);
|
||||
}
|
||||
try {
|
||||
value = otherFromThis(value);
|
||||
return otherReflectSet(object, key, value) === true;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
}
|
||||
|
||||
getPrototypeOf(target) {
|
||||
// Note: target@this(unsafe)
|
||||
return thisReflectGetPrototypeOf(target);
|
||||
}
|
||||
|
||||
setPrototypeOf(target, value) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
throw new VMError(OPNA);
|
||||
}
|
||||
|
||||
apply(target, context, args) {
|
||||
// Note: target@this(unsafe) context@this(unsafe) args@this(safe-array) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
let ret; // @other(unsafe)
|
||||
try {
|
||||
context = otherFromThis(context);
|
||||
args = otherFromThisArguments(args);
|
||||
ret = otherReflectApply(object, context, args);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return thisFromOther(ret);
|
||||
}
|
||||
|
||||
construct(target, args, newTarget) {
|
||||
// Note: target@this(unsafe) args@this(safe-array) newTarget@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
let ret; // @other(unsafe)
|
||||
try {
|
||||
args = otherFromThisArguments(args);
|
||||
ret = otherReflectConstruct(object, args);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return thisFromOtherWithFactory(this.getFactory(), ret, thisFromOther(object));
|
||||
}
|
||||
|
||||
getOwnPropertyDescriptorDesc(target, prop, desc) {
|
||||
// Note: target@this(unsafe) prop@prim desc@other{safe} throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
if (desc && typeof object === 'function' && (prop === 'arguments' || prop === 'caller' || prop === 'callee')) desc.value = null;
|
||||
return desc;
|
||||
}
|
||||
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
// Note: target@this(unsafe) prop@prim throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
let desc; // @other(safe)
|
||||
try {
|
||||
desc = otherSafeGetOwnPropertyDescriptor(object, prop);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
|
||||
desc = this.getOwnPropertyDescriptorDesc(target, prop, desc);
|
||||
|
||||
if (!desc) return undefined;
|
||||
|
||||
let thisDesc;
|
||||
if (desc.get || desc.set) {
|
||||
thisDesc = {
|
||||
__proto__: null,
|
||||
get: this.fromOtherWithContext(desc.get),
|
||||
set: this.fromOtherWithContext(desc.set),
|
||||
enumerable: desc.enumerable === true,
|
||||
configurable: desc.configurable === true
|
||||
};
|
||||
} else {
|
||||
thisDesc = {
|
||||
__proto__: null,
|
||||
value: this.fromOtherWithContext(desc.value),
|
||||
writable: desc.writable === true,
|
||||
enumerable: desc.enumerable === true,
|
||||
configurable: desc.configurable === true
|
||||
};
|
||||
}
|
||||
if (!thisDesc.configurable) {
|
||||
const oldDesc = thisSafeGetOwnPropertyDescriptor(target, prop);
|
||||
if (!oldDesc || oldDesc.configurable || oldDesc.writable !== thisDesc.writable) {
|
||||
if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected();
|
||||
}
|
||||
}
|
||||
return thisDesc;
|
||||
}
|
||||
|
||||
definePropertyDesc(target, prop, desc) {
|
||||
// Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe)
|
||||
return desc;
|
||||
}
|
||||
|
||||
defineProperty(target, prop, desc) {
|
||||
// Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
if (!thisReflectSetPrototypeOf(desc, null)) throw thisUnexpected();
|
||||
|
||||
desc = this.definePropertyDesc(target, prop, desc);
|
||||
|
||||
if (!desc) return false;
|
||||
|
||||
let otherDesc = {__proto__: null};
|
||||
let hasFunc = true;
|
||||
let hasValue = true;
|
||||
let hasBasic = true;
|
||||
hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'get');
|
||||
hasFunc &= otherFromThisIfAvailable(otherDesc, desc, 'set');
|
||||
hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'value');
|
||||
hasValue &= otherFromThisIfAvailable(otherDesc, desc, 'writable');
|
||||
hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'enumerable');
|
||||
hasBasic &= otherFromThisIfAvailable(otherDesc, desc, 'configurable');
|
||||
|
||||
try {
|
||||
if (!otherReflectDefineProperty(object, prop, otherDesc)) return false;
|
||||
if (otherDesc.configurable !== true && (!hasBasic || !(hasFunc || hasValue))) {
|
||||
otherDesc = otherSafeGetOwnPropertyDescriptor(object, prop);
|
||||
}
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
|
||||
if (!otherDesc.configurable) {
|
||||
let thisDesc;
|
||||
if (otherDesc.get || otherDesc.set) {
|
||||
thisDesc = {
|
||||
__proto__: null,
|
||||
get: this.fromOtherWithContext(otherDesc.get),
|
||||
set: this.fromOtherWithContext(otherDesc.set),
|
||||
enumerable: otherDesc.enumerable,
|
||||
configurable: otherDesc.configurable
|
||||
};
|
||||
} else {
|
||||
thisDesc = {
|
||||
__proto__: null,
|
||||
value: this.fromOtherWithContext(otherDesc.value),
|
||||
writable: otherDesc.writable,
|
||||
enumerable: otherDesc.enumerable,
|
||||
configurable: otherDesc.configurable
|
||||
};
|
||||
}
|
||||
if (!thisReflectDefineProperty(target, prop, thisDesc)) throw thisUnexpected();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
deleteProperty(target, prop) {
|
||||
// Note: target@this(unsafe) prop@prim throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
try {
|
||||
return otherReflectDeleteProperty(object, prop) === true;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
}
|
||||
|
||||
has(target, key) {
|
||||
// Note: target@this(unsafe) key@prim throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
try {
|
||||
return otherReflectHas(object, key) === true;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
}
|
||||
|
||||
isExtensible(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
try {
|
||||
if (otherReflectIsExtensible(object)) return true;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
if (thisReflectIsExtensible(target)) {
|
||||
this.doPreventExtensions(target, object, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ownKeys(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
let res; // @other(unsafe)
|
||||
try {
|
||||
res = otherReflectOwnKeys(object);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return thisFromOther(res);
|
||||
}
|
||||
|
||||
preventExtensions(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
try {
|
||||
if (!otherReflectPreventExtensions(object)) return false;
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
if (thisReflectIsExtensible(target)) {
|
||||
this.doPreventExtensions(target, object, this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enumerate(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
let res; // @other(unsafe)
|
||||
try {
|
||||
res = otherReflectEnumerate(object);
|
||||
} catch (e) { // @other(unsafe)
|
||||
throw thisFromOther(e);
|
||||
}
|
||||
return this.fromOtherWithContext(res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function defaultFactory(object) {
|
||||
// Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
return new BaseHandler(object);
|
||||
}
|
||||
|
||||
class ProtectedHandler extends BaseHandler {
|
||||
|
||||
getFactory() {
|
||||
return protectedFactory;
|
||||
}
|
||||
|
||||
set(target, key, value, receiver) {
|
||||
// Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
|
||||
if (typeof value === 'function') {
|
||||
return thisReflectDefineProperty(receiver, key, {
|
||||
__proto__: null,
|
||||
value: value,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
}) === true;
|
||||
}
|
||||
return super.set(target, key, value, receiver);
|
||||
}
|
||||
|
||||
definePropertyDesc(target, prop, desc) {
|
||||
// Note: target@this(unsafe) prop@prim desc@this(safe) throws@this(unsafe)
|
||||
if (desc && (desc.set || desc.get || typeof desc.value === 'function')) return undefined;
|
||||
return desc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function protectedFactory(object) {
|
||||
// Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
return new ProtectedHandler(object);
|
||||
}
|
||||
|
||||
class ReadOnlyHandler extends BaseHandler {
|
||||
|
||||
getFactory() {
|
||||
return readonlyFactory;
|
||||
}
|
||||
|
||||
set(target, key, value, receiver) {
|
||||
// Note: target@this(unsafe) key@prim value@this(unsafe) receiver@this(unsafe) throws@this(unsafe)
|
||||
return thisReflectDefineProperty(receiver, key, {
|
||||
__proto__: null,
|
||||
value: value,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
setPrototypeOf(target, value) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
return false;
|
||||
}
|
||||
|
||||
defineProperty(target, prop, desc) {
|
||||
// Note: target@this(unsafe) prop@prim desc@this(unsafe) throws@this(unsafe)
|
||||
return false;
|
||||
}
|
||||
|
||||
deleteProperty(target, prop) {
|
||||
// Note: target@this(unsafe) prop@prim throws@this(unsafe)
|
||||
return false;
|
||||
}
|
||||
|
||||
isExtensible(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
return false;
|
||||
}
|
||||
|
||||
preventExtensions(target) {
|
||||
// Note: target@this(unsafe) throws@this(unsafe)
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function readonlyFactory(object) {
|
||||
// Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
return new ReadOnlyHandler(object);
|
||||
}
|
||||
|
||||
class ReadOnlyMockHandler extends ReadOnlyHandler {
|
||||
|
||||
constructor(object, mock) {
|
||||
// Note: object@other(unsafe) mock:this(unsafe) throws@this(unsafe)
|
||||
super(object);
|
||||
this.mock = mock;
|
||||
}
|
||||
|
||||
get(target, key, receiver) {
|
||||
// Note: target@this(unsafe) key@prim receiver@this(unsafe) throws@this(unsafe)
|
||||
const object = this.object; // @other(unsafe)
|
||||
const mock = this.mock;
|
||||
if (thisReflectApply(thisObjectHasOwnProperty, mock, key) && !thisOtherHasOwnProperty(object, key)) {
|
||||
return mock[key];
|
||||
}
|
||||
return super.get(target, key, receiver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function thisFromOther(other) {
|
||||
// Note: other@other(unsafe) returns@this(unsafe) throws@this(unsafe)
|
||||
return thisFromOtherWithFactory(defaultFactory, other);
|
||||
}
|
||||
|
||||
function thisProxyOther(factory, other, proto) {
|
||||
const target = thisCreateTargetObject(other, proto);
|
||||
const handler = factory(other);
|
||||
const proxy = new ThisProxy(target, handler);
|
||||
try {
|
||||
otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy, other]);
|
||||
registerProxy(proxy, handler);
|
||||
} catch (e) {
|
||||
throw new VMError('Unexpected error');
|
||||
}
|
||||
if (!isHost) {
|
||||
thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy]);
|
||||
return proxy;
|
||||
}
|
||||
const proxy2 = new ThisProxy(proxy, emptyForzenObject);
|
||||
try {
|
||||
otherReflectApply(otherWeakMapSet, mappingThisToOther, [proxy2, other]);
|
||||
registerProxy(proxy2, handler);
|
||||
} catch (e) {
|
||||
throw new VMError('Unexpected error');
|
||||
}
|
||||
thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, proxy2]);
|
||||
return proxy2;
|
||||
}
|
||||
|
||||
function thisEnsureThis(other) {
|
||||
const type = typeof other;
|
||||
switch (type) {
|
||||
case 'object':
|
||||
case 'function':
|
||||
if (other === null) {
|
||||
return null;
|
||||
} else {
|
||||
let proto = thisReflectGetPrototypeOf(other);
|
||||
if (!proto) {
|
||||
return other;
|
||||
}
|
||||
while (proto) {
|
||||
const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
|
||||
if (mapping) {
|
||||
const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
|
||||
if (mapped) return mapped;
|
||||
return mapping(defaultFactory, other);
|
||||
}
|
||||
proto = thisReflectGetPrototypeOf(proto);
|
||||
}
|
||||
return other;
|
||||
}
|
||||
|
||||
case 'undefined':
|
||||
case 'string':
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
case 'symbol':
|
||||
case 'bigint':
|
||||
return other;
|
||||
|
||||
default: // new, unknown types can be dangerous
|
||||
throw new VMError(`Unknown type '${type}'`);
|
||||
}
|
||||
}
|
||||
|
||||
function thisFromOtherWithFactory(factory, other, proto) {
|
||||
for (let loop = 0; loop < 10; loop++) {
|
||||
const type = typeof other;
|
||||
switch (type) {
|
||||
case 'object':
|
||||
case 'function':
|
||||
if (other === null) {
|
||||
return null;
|
||||
} else {
|
||||
const mapped = thisReflectApply(thisWeakMapGet, mappingOtherToThis, [other]);
|
||||
if (mapped) return mapped;
|
||||
if (proto) {
|
||||
return thisProxyOther(factory, other, proto);
|
||||
}
|
||||
try {
|
||||
proto = otherReflectGetPrototypeOf(other);
|
||||
} catch (e) { // @other(unsafe)
|
||||
other = e;
|
||||
break;
|
||||
}
|
||||
if (!proto) {
|
||||
return thisProxyOther(factory, other, null);
|
||||
}
|
||||
while (proto) {
|
||||
const mapping = thisReflectApply(thisMapGet, protoMappings, [proto]);
|
||||
if (mapping) return mapping(factory, other);
|
||||
try {
|
||||
proto = otherReflectGetPrototypeOf(proto);
|
||||
} catch (e) { // @other(unsafe)
|
||||
other = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return thisProxyOther(factory, other, thisObjectPrototype);
|
||||
}
|
||||
|
||||
case 'undefined':
|
||||
case 'string':
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
case 'symbol':
|
||||
case 'bigint':
|
||||
return other;
|
||||
|
||||
default: // new, unknown types can be dangerous
|
||||
throw new VMError(`Unknown type '${type}'`);
|
||||
}
|
||||
factory = defaultFactory;
|
||||
proto = undefined;
|
||||
}
|
||||
throw new VMError('Exception recursion depth');
|
||||
}
|
||||
|
||||
function thisFromOtherArguments(args) {
|
||||
// Note: args@other(safe-array) returns@this(safe-array) throws@this(unsafe)
|
||||
const arr = [];
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const value = thisFromOther(args[i]);
|
||||
thisReflectDefineProperty(arr, i, {
|
||||
__proto__: null,
|
||||
value: value,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function thisConnect(obj, other) {
|
||||
// Note: obj@this(unsafe) other@other(unsafe) throws@this(unsafe)
|
||||
try {
|
||||
otherReflectApply(otherWeakMapSet, mappingThisToOther, [obj, other]);
|
||||
} catch (e) {
|
||||
throw new VMError('Unexpected error');
|
||||
}
|
||||
thisReflectApply(thisWeakMapSet, mappingOtherToThis, [other, obj]);
|
||||
}
|
||||
|
||||
thisAddProtoMapping(thisGlobalPrototypes.Object, otherGlobalPrototypes.Object);
|
||||
thisAddProtoMapping(thisGlobalPrototypes.Array, otherGlobalPrototypes.Array);
|
||||
|
||||
for (let i = 0; i < globalsList.length; i++) {
|
||||
const key = globalsList[i];
|
||||
const tp = thisGlobalPrototypes[key];
|
||||
const op = otherGlobalPrototypes[key];
|
||||
if (tp && op) thisAddProtoMapping(tp, op, key);
|
||||
}
|
||||
|
||||
for (let i = 0; i < errorsList.length; i++) {
|
||||
const key = errorsList[i];
|
||||
const tp = thisGlobalPrototypes[key];
|
||||
const op = otherGlobalPrototypes[key];
|
||||
if (tp && op) thisAddProtoMapping(tp, op, 'Error');
|
||||
}
|
||||
|
||||
thisAddProtoMapping(thisGlobalPrototypes.VMError, otherGlobalPrototypes.VMError, 'Error');
|
||||
|
||||
result.BaseHandler = BaseHandler;
|
||||
result.ProtectedHandler = ProtectedHandler;
|
||||
result.ReadOnlyHandler = ReadOnlyHandler;
|
||||
result.ReadOnlyMockHandler = ReadOnlyMockHandler;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.createBridge = createBridge;
|
||||
exports.VMError = VMError;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat */
|
||||
/******/
|
||||
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";/************************************************************************/
|
||||
/******/
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
||||
/******/ var __webpack_exports__ = {};
|
||||
/******/ __webpack_modules__[989](0, __webpack_exports__);
|
||||
/******/ module.exports = __webpack_exports__;
|
||||
/******/
|
||||
/******/ })()
|
||||
;
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -1,473 +0,0 @@
|
|||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ /* webpack/runtime/compat */
|
||||
/******/
|
||||
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
/* global host, data, VMError */
|
||||
|
||||
|
||||
|
||||
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 + 1);
|
||||
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
|
||||
};
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
|
@ -1,462 +0,0 @@
|
|||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ /* webpack/runtime/compat */
|
||||
/******/
|
||||
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
/* global host, bridge, data, context */
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
return new LocalProxy(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
|
||||
};
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
File diff suppressed because one or more lines are too long
|
@ -1,70 +1,53 @@
|
|||
variable "NODE_VERSION" {
|
||||
default = "12"
|
||||
}
|
||||
|
||||
target "node-version" {
|
||||
args = {
|
||||
NODE_VERSION = NODE_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["build"]
|
||||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["vendor-update", "format", "build"]
|
||||
targets = ["vendor", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
targets = ["format-validate", "build-validate", "vendor-validate"]
|
||||
targets = ["lint", "build-validate", "vendor-validate"]
|
||||
}
|
||||
|
||||
target "build" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build-validate" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "format" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "format-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "format-validate" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
target = "format-validate"
|
||||
target "lint" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "lint"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor-update" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
target "vendor" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "vendor-validate" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
inherits = ["node-version"]
|
||||
dockerfile = "./hack/build.Dockerfile"
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "test-coverage"
|
||||
output = ["./coverage"]
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
setupFiles: ["dotenv/config"],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: false
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-login-action-')).split(path.sep).join(path.posix.sep);
|
||||
|
||||
process.env = Object.assign({}, process.env, {
|
||||
TEMP: tmpDir,
|
||||
GITHUB_REPOSITORY: 'docker/login-action',
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp').split(path.sep).join(path.posix.sep),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache').split(path.sep).join(path.posix.sep)
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||
},
|
||||
collectCoverageFrom: ['src/**/{!(main.ts),}.ts'],
|
||||
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__tests__/'],
|
||||
verbose: true
|
||||
};
|
62
package.json
62
package.json
|
@ -1,13 +1,16 @@
|
|||
{
|
||||
"name": "docker-login",
|
||||
"description": "GitHub Action to login against a Docker registry",
|
||||
"main": "lib/main.js",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"test": "jest --coverage",
|
||||
"pre-checkin": "yarn run format && yarn run build"
|
||||
"build": "ncc build --source-map --minify --license licenses.txt",
|
||||
"lint": "yarn run prettier && yarn run eslint",
|
||||
"format": "yarn run prettier:fix && yarn run eslint:fix",
|
||||
"eslint": "eslint --max-warnings=0 .",
|
||||
"eslint:fix": "eslint --fix .",
|
||||
"prettier": "prettier --check \"./**/*.ts\"",
|
||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -18,33 +21,30 @@
|
|||
"docker",
|
||||
"login"
|
||||
],
|
||||
"author": "Docker",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "CrazyMax",
|
||||
"url": "https://crazymax.dev"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "Docker Inc.",
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@3.6.3",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/io": "^1.1.1",
|
||||
"@aws-sdk/client-ecr": "^3.45.0",
|
||||
"@aws-sdk/client-ecr-public": "^3.45.0",
|
||||
"proxy-agent": "^5.0.0"
|
||||
"@actions/core": "^1.10.1",
|
||||
"@aws-sdk/client-ecr": "^3.583.0",
|
||||
"@aws-sdk/client-ecr-public": "^3.583.0",
|
||||
"@docker/actions-toolkit": "^0.24.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/node": "^14.17.4",
|
||||
"@vercel/ncc": "^0.28.6",
|
||||
"dotenv": "^8.6.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-circus": "^26.6.3",
|
||||
"jest-runtime": "^26.6.3",
|
||||
"prettier": "^2.3.2",
|
||||
"ts-jest": "^26.5.6",
|
||||
"typescript": "^3.9.10",
|
||||
"typescript-formatter": "^7.2.2"
|
||||
"@types/node": "^20.12.12",
|
||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||
"@typescript-eslint/parser": "^7.9.0",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
|
|
19
src/aws.ts
19
src/aws.ts
|
@ -1,8 +1,9 @@
|
|||
import * as core from '@actions/core';
|
||||
import {ECR} from '@aws-sdk/client-ecr';
|
||||
import {ECRPUBLIC} from '@aws-sdk/client-ecr-public';
|
||||
import {NodeHttpHandler} from '@aws-sdk/node-http-handler';
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import {NodeHttpHandler} from '@smithy/node-http-handler';
|
||||
import {HttpProxyAgent} from 'http-proxy-agent';
|
||||
import {HttpsProxyAgent} from 'https-proxy-agent';
|
||||
|
||||
const ecrRegistryRegex = /^(([0-9]{12})\.dkr\.ecr\.(.+)\.amazonaws\.com(.cn)?)(\/([^:]+)(:.+)?)?$/;
|
||||
|
||||
|
@ -33,7 +34,7 @@ export const getAccountIDs = (registry: string): string[] => {
|
|||
if (!matches) {
|
||||
return [];
|
||||
}
|
||||
let accountIDs: Array<string> = [matches[2]];
|
||||
const accountIDs: Array<string> = [matches[2]];
|
||||
if (process.env.AWS_ACCOUNT_IDS) {
|
||||
accountIDs.push(...process.env.AWS_ACCOUNT_IDS.split(','));
|
||||
}
|
||||
|
@ -56,18 +57,18 @@ export const getRegistriesData = async (registry: string, username?: string, pas
|
|||
authTokenRequest['registryIds'] = accountIDs;
|
||||
}
|
||||
|
||||
let httpProxyAgent: any = null;
|
||||
let httpProxyAgent;
|
||||
const httpProxy = process.env.http_proxy || process.env.HTTP_PROXY || '';
|
||||
if (httpProxy) {
|
||||
core.debug(`Using http proxy ${httpProxy}`);
|
||||
httpProxyAgent = new ProxyAgent(httpProxy);
|
||||
httpProxyAgent = new HttpProxyAgent(httpProxy);
|
||||
}
|
||||
|
||||
let httpsProxyAgent: any = null;
|
||||
let httpsProxyAgent;
|
||||
const httpsProxy = process.env.https_proxy || process.env.HTTPS_PROXY || '';
|
||||
if (httpsProxy) {
|
||||
core.debug(`Using https proxy ${httpsProxy}`);
|
||||
httpsProxyAgent = new ProxyAgent(httpsProxy);
|
||||
httpsProxyAgent = new HttpsProxyAgent(httpsProxy);
|
||||
}
|
||||
|
||||
const credentials =
|
||||
|
@ -95,6 +96,8 @@ export const getRegistriesData = async (registry: string, username?: string, pas
|
|||
}
|
||||
const authToken = Buffer.from(authTokenResponse.authorizationData.authorizationToken, 'base64').toString('utf-8');
|
||||
const creds = authToken.split(':', 2);
|
||||
core.setSecret(creds[0]); // redacted in workflow logs
|
||||
core.setSecret(creds[1]); // redacted in workflow logs
|
||||
return [
|
||||
{
|
||||
registry: 'public.ecr.aws',
|
||||
|
@ -121,6 +124,8 @@ export const getRegistriesData = async (registry: string, username?: string, pas
|
|||
for (const authData of authTokenResponse.authorizationData) {
|
||||
const authToken = Buffer.from(authData.authorizationToken || '', 'base64').toString('utf-8');
|
||||
const creds = authToken.split(':', 2);
|
||||
core.setSecret(creds[0]); // redacted in workflow logs
|
||||
core.setSecret(creds[1]); // redacted in workflow logs
|
||||
regDatas.push({
|
||||
registry: authData.proxyEndpoint || '',
|
||||
username: creds[0],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as aws from './aws';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
||||
|
||||
export async function login(registry: string, username: string, password: string, ecr: string): Promise<void> {
|
||||
if (/true/i.test(ecr) || (ecr == 'auto' && aws.isECR(registry))) {
|
||||
|
@ -11,11 +11,9 @@ export async function login(registry: string, username: string, password: string
|
|||
}
|
||||
|
||||
export async function logout(registry: string): Promise<void> {
|
||||
await exec
|
||||
.getExecOutput('docker', ['logout', registry], {
|
||||
await Exec.getExecOutput('docker', ['logout', registry], {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
.then(res => {
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(res.stderr.trim());
|
||||
}
|
||||
|
@ -23,11 +21,17 @@ export async function logout(registry: string): Promise<void> {
|
|||
}
|
||||
|
||||
export async function loginStandard(registry: string, username: string, password: string): Promise<void> {
|
||||
if (!username || !password) {
|
||||
if (!username && !password) {
|
||||
throw new Error('Username and password required');
|
||||
}
|
||||
if (!username) {
|
||||
throw new Error('Username required');
|
||||
}
|
||||
if (!password) {
|
||||
throw new Error('Password required');
|
||||
}
|
||||
|
||||
let loginArgs: Array<string> = ['login', '--password-stdin'];
|
||||
const loginArgs: Array<string> = ['login', '--password-stdin'];
|
||||
loginArgs.push('--username', username);
|
||||
loginArgs.push(registry);
|
||||
|
||||
|
@ -36,13 +40,11 @@ export async function loginStandard(registry: string, username: string, password
|
|||
} else {
|
||||
core.info(`Logging into Docker Hub...`);
|
||||
}
|
||||
await exec
|
||||
.getExecOutput('docker', loginArgs, {
|
||||
await Exec.getExecOutput('docker', loginArgs, {
|
||||
ignoreReturnCode: true,
|
||||
silent: true,
|
||||
input: Buffer.from(password)
|
||||
})
|
||||
.then(res => {
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
|
@ -55,13 +57,11 @@ export async function loginECR(registry: string, username: string, password: str
|
|||
const regDatas = await aws.getRegistriesData(registry, username, password);
|
||||
for (const regData of regDatas) {
|
||||
core.info(`Logging into ${regData.registry}...`);
|
||||
await exec
|
||||
.getExecOutput('docker', ['login', '--password-stdin', '--username', regData.username, regData.registry], {
|
||||
await Exec.getExecOutput('docker', ['login', '--password-stdin', '--username', regData.username, regData.registry], {
|
||||
ignoreReturnCode: true,
|
||||
silent: true,
|
||||
input: Buffer.from(regData.password)
|
||||
})
|
||||
.then(res => {
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.trim());
|
||||
}
|
||||
|
|
17
src/main.ts
17
src/main.ts
|
@ -1,28 +1,21 @@
|
|||
import * as core from '@actions/core';
|
||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
||||
|
||||
import * as context from './context';
|
||||
import * as docker from './docker';
|
||||
import * as stateHelper from './state-helper';
|
||||
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
export async function main(): Promise<void> {
|
||||
const input: context.Inputs = context.getInputs();
|
||||
stateHelper.setRegistry(input.registry);
|
||||
stateHelper.setLogout(input.logout);
|
||||
await docker.login(input.registry, input.username, input.password, input.ecr);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function logout(): Promise<void> {
|
||||
async function post(): Promise<void> {
|
||||
if (!stateHelper.logout) {
|
||||
return;
|
||||
}
|
||||
await docker.logout(stateHelper.registry);
|
||||
}
|
||||
|
||||
if (!stateHelper.IsPost) {
|
||||
run();
|
||||
} else {
|
||||
logout();
|
||||
}
|
||||
actionsToolkit.run(main, post);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
export const IsPost = !!process.env['STATE_isPost'];
|
||||
export const registry = process.env['STATE_registry'] || '';
|
||||
export const logout = /true/i.test(process.env['STATE_logout'] || '');
|
||||
|
||||
|
@ -11,7 +10,3 @@ export function setRegistry(registry: string) {
|
|||
export function setLogout(logout: boolean) {
|
||||
core.saveState('logout', logout);
|
||||
}
|
||||
|
||||
if (!IsPost) {
|
||||
core.saveState('isPost', 'true');
|
||||
}
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"strict": true,
|
||||
"newLine": "lf",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitAny": false,
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true
|
||||
"resolveJsonModule": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
"exclude": [
|
||||
"./__tests__/**/*",
|
||||
"./lib/**/*",
|
||||
"node_modules",
|
||||
"jest.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue