mirror of
https://github.com/redhat-actions/push-to-registry.git
synced 2025-04-20 23:31:22 +00:00
Resolve Review comments
Signed-off-by: divyansh42 <diagrawa@redhat.com>
This commit is contained in:
parent
4deaffac48
commit
34d200b35d
13 changed files with 332 additions and 136 deletions
|
@ -1,6 +1,6 @@
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
"@tetchel/eslint-config-actions",
|
"@redhat-actions/eslint-config",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
48
.github/workflows/verify-push-test1.yaml
vendored
Normal file
48
.github/workflows/verify-push-test1.yaml
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Test Push with Podman newer
|
||||||
|
on: [ push, workflow_dispatch ]
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: myimage
|
||||||
|
IMAGE_REGISTRY: quay.io
|
||||||
|
IMAGE_TAG: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push image to Quay.io
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
# Checkout push-to-registry action github repository
|
||||||
|
- name: Checkout Push to Registry action
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Build Image using Docker
|
||||||
|
run: |
|
||||||
|
docker build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Build Image using Podman
|
||||||
|
run: |
|
||||||
|
podman build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Push the image to image registry
|
||||||
|
- name: Push To Quay
|
||||||
|
uses: ./
|
||||||
|
id: push
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tag: ${{ env.IMAGE_TAG }}
|
||||||
|
registry: ${{ env.IMAGE_REGISTRY }}/${{ secrets.REGISTRY_USER }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Echo outputs
|
||||||
|
run: |
|
||||||
|
echo "registry-path ${{ steps.push.outputs.registry-path }}"
|
||||||
|
echo "digest ${{ steps.push.outputs.digest }}"
|
48
.github/workflows/verify-push-test2.yaml
vendored
Normal file
48
.github/workflows/verify-push-test2.yaml
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Test Push with docker newer
|
||||||
|
on: [ push, workflow_dispatch ]
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: myimage
|
||||||
|
IMAGE_REGISTRY: quay.io
|
||||||
|
IMAGE_TAG: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push image to Quay.io
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
# Checkout push-to-registry action github repository
|
||||||
|
- name: Checkout Push to Registry action
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Build Image using Podman
|
||||||
|
run: |
|
||||||
|
podman build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Build Image using Docker
|
||||||
|
run: |
|
||||||
|
docker build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Push the image to image registry
|
||||||
|
- name: Push To Quay
|
||||||
|
uses: ./
|
||||||
|
id: push
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tag: ${{ env.IMAGE_TAG }}
|
||||||
|
registry: ${{ env.IMAGE_REGISTRY }}/${{ secrets.REGISTRY_USER }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Echo outputs
|
||||||
|
run: |
|
||||||
|
echo "registry-path ${{ steps.push.outputs.registry-path }}"
|
||||||
|
echo "digest ${{ steps.push.outputs.digest }}"
|
41
.github/workflows/verify-push-test3.yaml
vendored
Normal file
41
.github/workflows/verify-push-test3.yaml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Test Push with only Podman
|
||||||
|
on: [ push, workflow_dispatch ]
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: myimage
|
||||||
|
IMAGE_REGISTRY: quay.io
|
||||||
|
IMAGE_TAG: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push image to Quay.io
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
# Checkout push-to-registry action github repository
|
||||||
|
- name: Checkout Push to Registry action
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Build Image using Podman
|
||||||
|
run: |
|
||||||
|
podman build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Push the image to image registry
|
||||||
|
- name: Push To Quay
|
||||||
|
uses: ./
|
||||||
|
id: push
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tag: ${{ env.IMAGE_TAG }}
|
||||||
|
registry: ${{ env.IMAGE_REGISTRY }}/${{ secrets.REGISTRY_USER }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Echo outputs
|
||||||
|
run: |
|
||||||
|
echo "registry-path ${{ steps.push.outputs.registry-path }}"
|
||||||
|
echo "digest ${{ steps.push.outputs.digest }}"
|
41
.github/workflows/verify-push-test4.yaml
vendored
Normal file
41
.github/workflows/verify-push-test4.yaml
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# This workflow will perform a test whenever there
|
||||||
|
# is some change in code done to ensure that the changes
|
||||||
|
# are not buggy and we are getting the desired output.
|
||||||
|
name: Test Push with only Docker
|
||||||
|
on: [ push, workflow_dispatch ]
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: myimage
|
||||||
|
IMAGE_REGISTRY: quay.io
|
||||||
|
IMAGE_TAG: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push image to Quay.io
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
# Checkout push-to-registry action github repository
|
||||||
|
- name: Checkout Push to Registry action
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Build Image using Docker
|
||||||
|
run: |
|
||||||
|
docker build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
|
FROM busybox
|
||||||
|
RUN echo "hello world"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Push the image to image registry
|
||||||
|
- name: Push To Quay
|
||||||
|
uses: ./
|
||||||
|
id: push
|
||||||
|
with:
|
||||||
|
image: ${{ env.IMAGE_NAME }}
|
||||||
|
tag: ${{ env.IMAGE_TAG }}
|
||||||
|
registry: ${{ env.IMAGE_REGISTRY }}/${{ secrets.REGISTRY_USER }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Echo outputs
|
||||||
|
run: |
|
||||||
|
echo "registry-path ${{ steps.push.outputs.registry-path }}"
|
||||||
|
echo "digest ${{ steps.push.outputs.digest }}"
|
16
.github/workflows/verify-push.yaml
vendored
16
.github/workflows/verify-push.yaml
vendored
|
@ -1,8 +1,8 @@
|
||||||
# This workflow will perform a test whenever there
|
# This workflow will perform a test whenever there
|
||||||
# is some change in code done to ensure that the changes
|
# is some change in code done to ensure that the changes
|
||||||
# are not buggy and we are getting the desired output.
|
# are not buggy and we are getting the desired output.
|
||||||
name: Test Push
|
name: Test Push without image
|
||||||
on: [push, pull_request, workflow_dispatch]
|
on: [ push, workflow_dispatch ]
|
||||||
env:
|
env:
|
||||||
IMAGE_NAME: myimage
|
IMAGE_NAME: myimage
|
||||||
IMAGE_REGISTRY: quay.io
|
IMAGE_REGISTRY: quay.io
|
||||||
|
@ -17,12 +17,12 @@ jobs:
|
||||||
- name: Checkout Push to Registry action
|
- name: Checkout Push to Registry action
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Build Image using Docker
|
# - name: Build Image using Docker
|
||||||
run: |
|
# run: |
|
||||||
docker build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
# docker build -t ${{ env.IMAGE_NAME }}:latest -<<EOF
|
||||||
FROM busybox
|
# FROM busybox
|
||||||
RUN echo "hello world"
|
# RUN echo "hello world"
|
||||||
EOF
|
# EOF
|
||||||
|
|
||||||
# Push the image to image registry
|
# Push the image to image registry
|
||||||
- name: Push To Quay
|
- name: Push To Quay
|
||||||
|
|
|
@ -120,6 +120,11 @@ jobs:
|
||||||
run: echo "New image has been pushed to ${{ steps.push-to-quay.outputs.registry-path }}"
|
run: echo "New image has been pushed to ${{ steps.push-to-quay.outputs.registry-path }}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**NOTE**:
|
||||||
|
- This action use `Docker` and `Podman` both as the command line tools. Docker and Podman stores image in their respective local image storage's.
|
||||||
|
- If image is present in Docker image storage then image will be pulled into Podman's image storage and will be removed once image is pushed to the desired image registry.
|
||||||
|
- In case image with same name and same version is present in Docker as well as Podman image storage, then this action will push the latest built version amongst the Docker and Podman image storage's.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
Note that quay.io repositories are private by default.<br>
|
Note that quay.io repositories are private by default.<br>
|
||||||
|
|
||||||
|
|
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
124
package-lock.json
generated
124
package-lock.json
generated
|
@ -62,9 +62,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@eslint/eslintrc": {
|
"@eslint/eslintrc": {
|
||||||
"version": "0.2.2",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz",
|
||||||
"integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==",
|
"integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.12.4",
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
"ignore": "^4.0.6",
|
"ignore": "^4.0.6",
|
||||||
"import-fresh": "^3.2.1",
|
"import-fresh": "^3.2.1",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.20",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
"strip-json-comments": "^3.1.1"
|
"strip-json-comments": "^3.1.1"
|
||||||
},
|
},
|
||||||
|
@ -113,16 +113,22 @@
|
||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@tetchel/eslint-config-actions": {
|
"@redhat-actions/eslint-config": {
|
||||||
"version": "0.0.8",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tetchel/eslint-config-actions/-/eslint-config-actions-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@redhat-actions/eslint-config/-/eslint-config-1.2.0.tgz",
|
||||||
"integrity": "sha512-DfR4CZ3wkkspIAf2DDgDoH1yN6zdiJ0NVVDlS5TziQgzDxydDGgjnQUxqB6YIqYEfw1NCL5eycZnscmbE3gvXQ==",
|
"integrity": "sha512-HFpdgXIB01wmZbCsEpaY0UhQlRBiM/kJxO0WCufIx/wTxepewwsLTsgCgKkljbGfSaqN7FMJ/TbwY1CY/ltHcw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"eslint-config-airbnb-base": ">= 14",
|
"eslint-config-airbnb-base": ">= 14",
|
||||||
"eslint-plugin-import": ">=2"
|
"eslint-plugin-import": ">=2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@redhat-actions/tsconfig": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@redhat-actions/tsconfig/-/tsconfig-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-9eiU6lLepYIO/h51F8bph2KI4/ZdqK0inDcoOtaBGfQslsoSRygaTmRwD6EaejcDTor/5MZZo9dIKmm+5BGkXw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/json-schema": {
|
"@types/json-schema": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||||
|
@ -142,13 +148,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.0.tgz",
|
||||||
"integrity": "sha512-ygqDUm+BUPvrr0jrXqoteMqmIaZ/bixYOc3A4BRwzEPTZPi6E+n44rzNZWaB0YvtukgP+aoj0i/fyx7FkM2p1w==",
|
"integrity": "sha512-IJ5e2W7uFNfg4qh9eHkHRUCbgZ8VKtGwD07kannJvM5t/GU8P8+24NX8gi3Hf5jST5oWPY8kyV1s/WtfiZ4+Ww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "4.13.0",
|
"@typescript-eslint/experimental-utils": "4.14.0",
|
||||||
"@typescript-eslint/scope-manager": "4.13.0",
|
"@typescript-eslint/scope-manager": "4.14.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
|
@ -158,55 +164,55 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.0.tgz",
|
||||||
"integrity": "sha512-/ZsuWmqagOzNkx30VWYV3MNB/Re/CGv/7EzlqZo5RegBN8tMuPaBgNK6vPBCQA8tcYrbsrTdbx3ixMRRKEEGVw==",
|
"integrity": "sha512-6i6eAoiPlXMKRbXzvoQD5Yn9L7k9ezzGRvzC/x1V3650rUk3c3AOjQyGYyF9BDxQQDK2ElmKOZRD0CbtdkMzQQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.3",
|
"@types/json-schema": "^7.0.3",
|
||||||
"@typescript-eslint/scope-manager": "4.13.0",
|
"@typescript-eslint/scope-manager": "4.14.0",
|
||||||
"@typescript-eslint/types": "4.13.0",
|
"@typescript-eslint/types": "4.14.0",
|
||||||
"@typescript-eslint/typescript-estree": "4.13.0",
|
"@typescript-eslint/typescript-estree": "4.14.0",
|
||||||
"eslint-scope": "^5.0.0",
|
"eslint-scope": "^5.0.0",
|
||||||
"eslint-utils": "^2.0.0"
|
"eslint-utils": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.14.0.tgz",
|
||||||
"integrity": "sha512-KO0J5SRF08pMXzq9+abyHnaGQgUJZ3Z3ax+pmqz9vl81JxmTTOUfQmq7/4awVfq09b6C4owNlOgOwp61pYRBSg==",
|
"integrity": "sha512-sUDeuCjBU+ZF3Lzw0hphTyScmDDJ5QVkyE21pRoBo8iDl7WBtVFS+WDN3blY1CH3SBt7EmYCw6wfmJjF0l/uYg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/scope-manager": "4.13.0",
|
"@typescript-eslint/scope-manager": "4.14.0",
|
||||||
"@typescript-eslint/types": "4.13.0",
|
"@typescript-eslint/types": "4.14.0",
|
||||||
"@typescript-eslint/typescript-estree": "4.13.0",
|
"@typescript-eslint/typescript-estree": "4.14.0",
|
||||||
"debug": "^4.1.1"
|
"debug": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/scope-manager": {
|
"@typescript-eslint/scope-manager": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.0.tgz",
|
||||||
"integrity": "sha512-UpK7YLG2JlTp/9G4CHe7GxOwd93RBf3aHO5L+pfjIrhtBvZjHKbMhBXTIQNkbz7HZ9XOe++yKrXutYm5KmjWgQ==",
|
"integrity": "sha512-/J+LlRMdbPh4RdL4hfP1eCwHN5bAhFAGOTsvE6SxsrM/47XQiPSgF5MDgLyp/i9kbZV9Lx80DW0OpPkzL+uf8Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.13.0",
|
"@typescript-eslint/types": "4.14.0",
|
||||||
"@typescript-eslint/visitor-keys": "4.13.0"
|
"@typescript-eslint/visitor-keys": "4.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.0.tgz",
|
||||||
"integrity": "sha512-/+aPaq163oX+ObOG00M0t9tKkOgdv9lq0IQv/y4SqGkAXmhFmCfgsELV7kOCTb2vVU5VOmVwXBXJTDr353C1rQ==",
|
"integrity": "sha512-VsQE4VvpldHrTFuVPY1ZnHn/Txw6cZGjL48e+iBxTi2ksa9DmebKjAeFmTVAYoSkTk7gjA7UqJ7pIsyifTsI4A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.0.tgz",
|
||||||
"integrity": "sha512-9A0/DFZZLlGXn5XA349dWQFwPZxcyYyCFX5X88nWs2uachRDwGeyPz46oTsm9ZJE66EALvEns1lvBwa4d9QxMg==",
|
"integrity": "sha512-wRjZ5qLao+bvS2F7pX4qi2oLcOONIB+ru8RGBieDptq/SudYwshveORwCVU4/yMAd4GK7Fsf8Uq1tjV838erag==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.13.0",
|
"@typescript-eslint/types": "4.14.0",
|
||||||
"@typescript-eslint/visitor-keys": "4.13.0",
|
"@typescript-eslint/visitor-keys": "4.14.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"globby": "^11.0.1",
|
"globby": "^11.0.1",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
|
@ -216,12 +222,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
"version": "4.13.0",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.0.tgz",
|
||||||
"integrity": "sha512-6RoxWK05PAibukE7jElqAtNMq+RWZyqJ6Q/GdIxaiUj2Ept8jh8+FUVlbq9WxMYxkmEOPvCE5cRSyupMpwW31g==",
|
"integrity": "sha512-MeHHzUyRI50DuiPgV9+LxcM52FCJFYjJiWHtXlbyC27b80mfOwKeiKI+MHOTEpcpfmoPFm/vvQS88bYIx6PZTA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.13.0",
|
"@typescript-eslint/types": "4.14.0",
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -524,23 +530,25 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-abstract": {
|
"es-abstract": {
|
||||||
"version": "1.18.0-next.1",
|
"version": "1.18.0-next.2",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz",
|
||||||
"integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
|
"integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"es-to-primitive": "^1.2.1",
|
"es-to-primitive": "^1.2.1",
|
||||||
"function-bind": "^1.1.1",
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.0.2",
|
||||||
"has": "^1.0.3",
|
"has": "^1.0.3",
|
||||||
"has-symbols": "^1.0.1",
|
"has-symbols": "^1.0.1",
|
||||||
"is-callable": "^1.2.2",
|
"is-callable": "^1.2.2",
|
||||||
"is-negative-zero": "^2.0.0",
|
"is-negative-zero": "^2.0.1",
|
||||||
"is-regex": "^1.1.1",
|
"is-regex": "^1.1.1",
|
||||||
"object-inspect": "^1.8.0",
|
"object-inspect": "^1.9.0",
|
||||||
"object-keys": "^1.1.1",
|
"object-keys": "^1.1.1",
|
||||||
"object.assign": "^4.1.1",
|
"object.assign": "^4.1.2",
|
||||||
"string.prototype.trimend": "^1.0.1",
|
"string.prototype.trimend": "^1.0.3",
|
||||||
"string.prototype.trimstart": "^1.0.1"
|
"string.prototype.trimstart": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-to-primitive": {
|
"es-to-primitive": {
|
||||||
|
@ -561,13 +569,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz",
|
||||||
"integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==",
|
"integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/code-frame": "^7.0.0",
|
"@babel/code-frame": "^7.0.0",
|
||||||
"@eslint/eslintrc": "^0.2.2",
|
"@eslint/eslintrc": "^0.3.0",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
"cross-spawn": "^7.0.2",
|
"cross-spawn": "^7.0.2",
|
||||||
|
@ -591,7 +599,7 @@
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
"levn": "^0.4.1",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.20",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.1",
|
"optionator": "^0.9.1",
|
||||||
|
@ -837,9 +845,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
|
||||||
"integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==",
|
"integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@nodelib/fs.stat": "^2.0.2",
|
"@nodelib/fs.stat": "^2.0.2",
|
||||||
|
|
|
@ -18,12 +18,13 @@
|
||||||
"@actions/io": "^1.0.2"
|
"@actions/io": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tetchel/eslint-config-actions": "0.0.8",
|
"@redhat-actions/eslint-config": "^1.2.0",
|
||||||
|
"@redhat-actions/tsconfig": "^1.1.0",
|
||||||
"@types/node": "^12.12.7",
|
"@types/node": "^12.12.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.13.0",
|
"@typescript-eslint/eslint-plugin": "^4.14.0",
|
||||||
"@typescript-eslint/parser": "^4.13.0",
|
"@typescript-eslint/parser": "^4.14.0",
|
||||||
"@vercel/ncc": "^0.25.1",
|
"@vercel/ncc": "^0.25.1",
|
||||||
"eslint": "^7.17.0",
|
"eslint": "^7.18.0",
|
||||||
"typescript": "^4.0.5"
|
"typescript": "^4.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
107
src/index.ts
107
src/index.ts
|
@ -4,12 +4,25 @@ import * as io from "@actions/io";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
interface Response {
|
interface ExecResult {
|
||||||
exitCode: number;
|
exitCode: number;
|
||||||
stdout: string;
|
stdout: string;
|
||||||
stderr: string;
|
stderr: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let podmanPath: string | undefined;
|
||||||
|
|
||||||
|
async function getPodmanPath(): Promise<string> {
|
||||||
|
if (podmanPath == null) {
|
||||||
|
podmanPath = await io.which("podman", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return podmanPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// base URL that gets appended if image is pulled from the Docker imaege storage
|
||||||
|
const dockerBaseUrl = "docker.io/library";
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
const imageInput = core.getInput("image", { required: true });
|
const imageInput = core.getInput("image", { required: true });
|
||||||
const tag = core.getInput("tag") || "latest";
|
const tag = core.getInput("tag") || "latest";
|
||||||
|
@ -19,51 +32,43 @@ async function run(): Promise<void> {
|
||||||
const tlsVerify = core.getInput("tls-verify");
|
const tlsVerify = core.getInput("tls-verify");
|
||||||
const digestFileInput = core.getInput("digestfile");
|
const digestFileInput = core.getInput("digestfile");
|
||||||
|
|
||||||
// get Podman cli
|
|
||||||
const podman = await io.which("podman", true);
|
|
||||||
|
|
||||||
let imageToPush = `${imageInput}:${tag}`;
|
let imageToPush = `${imageInput}:${tag}`;
|
||||||
|
|
||||||
// check if image exist in Podman local registry
|
// check if image exist in Podman image storage
|
||||||
const isPresentInPodman: boolean = await checkImageInPodman(
|
const isPresentInPodman: boolean = await checkImageInPodman(
|
||||||
imageToPush,
|
imageToPush,
|
||||||
podman,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// check if image exist in Docker local registry and if exist pull the image to Podman
|
// check if image exist in Docker image storage and if exist pull the image to Podman
|
||||||
const isPresentInDocker: boolean = await pullImageFromDocker(
|
const isPresentInDocker: boolean = await pullImageFromDocker(
|
||||||
imageToPush,
|
imageToPush,
|
||||||
podman,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// boolean value to check if pushed image is from Docker local registry
|
// failing if image is not found in Docker as well as Podman
|
||||||
|
if (!isPresentInDocker && !isPresentInPodman) {
|
||||||
|
throw new Error(`Image ${imageToPush} not found in Podman local storage, or Docker local storage.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// boolean value to check if pushed image is from Docker image storage
|
||||||
let isPushingDockerImage = false;
|
let isPushingDockerImage = false;
|
||||||
|
|
||||||
if (isPresentInPodman && isPresentInDocker) {
|
if (isPresentInPodman && isPresentInDocker) {
|
||||||
const warningMsg = "Image found in Podman as well as in Docker local registry.";
|
const isPodmanImageLatest = await isPodmanLocalImageLatest(
|
||||||
|
|
||||||
let isPodmanImageLatest = false;
|
|
||||||
try {
|
|
||||||
isPodmanImageLatest = await isPodmanLocalImageLatest(
|
|
||||||
imageToPush,
|
imageToPush,
|
||||||
podman,
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
core.setFailed(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPodmanImageLatest) {
|
if (!isPodmanImageLatest) {
|
||||||
core.warning(`${warningMsg} Using Docker local registry's image as that is built latest`);
|
core.warning(`The version of ${imageToPush} in the Docker image storage is more recent than the version in the Podman image storage. The image from the Docker image storage will be pushed.`);
|
||||||
imageToPush = `docker.io/library/${imageToPush}`;
|
imageToPush = `${dockerBaseUrl}/${imageToPush}`;
|
||||||
isPushingDockerImage = true;
|
isPushingDockerImage = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
core.warning(`${warningMsg} Using Podman local registry's image as that is built latest`);
|
core.warning(`The version of ${imageToPush} in the Podman image storage is more recent than the version in the Docker image storage. The image from the Podman image storage will be pushed.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isPresentInDocker) {
|
else if (isPresentInDocker) {
|
||||||
imageToPush = `docker.io/library/${imageToPush}`;
|
imageToPush = `${dockerBaseUrl}/${imageToPush}`;
|
||||||
|
core.info(`Image ${imageToPush} was found in the Docker image storage, but not in the Podman image storage. The image will be pulled into Podman image storage, pushed, and then removed from the Podman image storage.`);
|
||||||
isPushingDockerImage = true;
|
isPushingDockerImage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +78,8 @@ async function run(): Promise<void> {
|
||||||
}
|
}
|
||||||
core.info(pushMsg);
|
core.info(pushMsg);
|
||||||
|
|
||||||
const registryPath = `${registry.replace(/\/$/, "")}/${imageInput}:${tag}`;
|
const registryWithoutTrailingSlash = registry.replace(/\/$/, "");
|
||||||
|
const registryPath = `${registryWithoutTrailingSlash}/${imageInput}:${tag}`;
|
||||||
|
|
||||||
const creds = `${username}:${password}`;
|
const creds = `${username}:${password}`;
|
||||||
|
|
||||||
|
@ -85,7 +91,7 @@ async function run(): Promise<void> {
|
||||||
)}_digest.txt`;
|
)}_digest.txt`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push image
|
// push the image
|
||||||
const args = [
|
const args = [
|
||||||
"push",
|
"push",
|
||||||
"--quiet",
|
"--quiet",
|
||||||
|
@ -102,15 +108,15 @@ async function run(): Promise<void> {
|
||||||
args.push(`--tls-verify=${tlsVerify}`);
|
args.push(`--tls-verify=${tlsVerify}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await execute(podman, args);
|
await execute(await getPodmanPath(), args);
|
||||||
|
|
||||||
core.info(`Successfully pushed ${imageToPush} to ${registryPath}.`);
|
core.info(`Successfully pushed ${imageToPush} to ${registryPath}.`);
|
||||||
core.setOutput("registry-path", registryPath);
|
core.setOutput("registry-path", registryPath);
|
||||||
|
|
||||||
// remove the pulled image from the Podman local registry
|
// remove the pulled image from the Podman image storage
|
||||||
if (isPushingDockerImage) {
|
if (isPushingDockerImage) {
|
||||||
core.info(`Removing ${imageToPush} from the Podman local registry`);
|
core.info(`Removing ${imageToPush} from the Podman image storage`);
|
||||||
await execute(podman, [ "rmi", imageToPush ]);
|
await execute(await getPodmanPath(), [ "rmi", imageToPush ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -125,43 +131,40 @@ async function run(): Promise<void> {
|
||||||
|
|
||||||
async function pullImageFromDocker(
|
async function pullImageFromDocker(
|
||||||
imageName: string,
|
imageName: string,
|
||||||
podman: string,
|
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await execute(podman, [ "pull", `docker-daemon:${imageName}` ]);
|
await execute(await getPodmanPath(), [ "pull", `docker-daemon:${imageName}` ]);
|
||||||
core.info("Image found and sucessfully pulled from Docker local registry");
|
core.info(`Image ${imageName} found in Docker image storage`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
core.info("Image not found in Docker local registry");
|
core.info(`Image ${imageName} not found in Docker image storage`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkImageInPodman(
|
async function checkImageInPodman(
|
||||||
imageName: string,
|
imageName: string,
|
||||||
podman: string,
|
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
// check if images exist in Podman's local registry
|
// check if images exist in Podman's storage
|
||||||
core.info("Checking image in Podman local registry");
|
core.info("Checking image in Podman image storage");
|
||||||
try {
|
try {
|
||||||
await execute(podman, [ "image", "exists", imageName ]);
|
await execute(await getPodmanPath(), [ "image", "exists", imageName ]);
|
||||||
core.info("Image found in Podman local registry");
|
core.info(`Image ${imageName} found in Podman image storage`);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
core.info("Image not found in Podman local registry");
|
core.info(`Image ${imageName} not found in Podman image storage`);
|
||||||
core.debug(err);
|
core.debug(err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isPodmanLocalImageLatest(
|
async function isPodmanLocalImageLatest(
|
||||||
imageName: string,
|
imageName: string,
|
||||||
podman: string,
|
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
// get creation time of the image present in the Podman local registry
|
// get creation time of the image present in the Podman image storage
|
||||||
const podmanLocalImageTimeStamp = await execute(podman, [
|
const podmanLocalImageTimeStamp = await execute(await getPodmanPath(), [
|
||||||
"image",
|
"image",
|
||||||
"inspect",
|
"inspect",
|
||||||
imageName,
|
imageName,
|
||||||
|
@ -169,17 +172,21 @@ async function isPodmanLocalImageLatest(
|
||||||
"{{.Created}}",
|
"{{.Created}}",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// get creation time of the image pulled from the Docker local registry
|
core.info(`The image from Podman image storage was last modified at ${podmanLocalImageTimeStamp.stdout}`);
|
||||||
|
|
||||||
|
// get creation time of the image pulled from the Docker image storage
|
||||||
// appending 'docker.io/library' infront of image name as pulled image name
|
// appending 'docker.io/library' infront of image name as pulled image name
|
||||||
// from Docker local registry starts with the 'docker.io/library'
|
// from Docker image storage starts with the 'docker.io/library'
|
||||||
const pulledImageCreationTimeStamp = await execute(podman, [
|
const pulledImageCreationTimeStamp = await execute(await getPodmanPath(), [
|
||||||
"image",
|
"image",
|
||||||
"inspect",
|
"inspect",
|
||||||
`docker.io/library/${imageName}`,
|
`${dockerBaseUrl}/${imageName}`,
|
||||||
"--format",
|
"--format",
|
||||||
"{{.Created}}",
|
"{{.Created}}",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
core.info(`The image from Docker image storage was last modified at ${pulledImageCreationTimeStamp.stdout}`);
|
||||||
|
|
||||||
const podmanImageTime = new Date(podmanLocalImageTimeStamp.stdout).getTime();
|
const podmanImageTime = new Date(podmanLocalImageTimeStamp.stdout).getTime();
|
||||||
|
|
||||||
const dockerImageTime = new Date(pulledImageCreationTimeStamp.stdout).getTime();
|
const dockerImageTime = new Date(pulledImageCreationTimeStamp.stdout).getTime();
|
||||||
|
@ -191,7 +198,7 @@ async function execute(
|
||||||
executable: string,
|
executable: string,
|
||||||
args: string[],
|
args: string[],
|
||||||
execOptions: exec.ExecOptions = {},
|
execOptions: exec.ExecOptions = {},
|
||||||
): Promise<Response> {
|
): Promise<ExecResult> {
|
||||||
let stdout = "";
|
let stdout = "";
|
||||||
let stderr = "";
|
let stderr = "";
|
||||||
|
|
||||||
|
@ -199,10 +206,10 @@ async function execute(
|
||||||
finalExecOptions.ignoreReturnCode = true; // the return code is processed below
|
finalExecOptions.ignoreReturnCode = true; // the return code is processed below
|
||||||
|
|
||||||
finalExecOptions.listeners = {
|
finalExecOptions.listeners = {
|
||||||
stdline: (line) => {
|
stdline: (line): void => {
|
||||||
stdout += `${line}\n`;
|
stdout += `${line}\n`;
|
||||||
},
|
},
|
||||||
errline: (line) => {
|
errline: (line): void => {
|
||||||
stderr += `${line}\n`;
|
stderr += `${line}\n`;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
{
|
{
|
||||||
|
"extends": "@redhat-actions/tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES6",
|
"rootDir": "src/",
|
||||||
"module": "commonjs",
|
"outDir": "out/"
|
||||||
"lib": [
|
|
||||||
"ES2017"
|
|
||||||
],
|
|
||||||
"outDir": "out",
|
|
||||||
"rootDir": ".",
|
|
||||||
},
|
},
|
||||||
"exclude": [
|
"include": [
|
||||||
"node_modules"
|
"src/"
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue