Compare commits
307 Commits
Author | SHA1 | Date |
---|---|---|
|
29879c9c50 | |
|
f8ac9fdddd | |
|
83879f19b9 | |
|
3807dd4c7c | |
|
dcf0138dc6 | |
|
3a40496053 | |
|
bc3c31fde7 | |
|
a4e868e155 | |
|
9df84f7b03 | |
|
bd38964ec7 | |
|
45f4d187f9 | |
|
4f8ae8fd28 | |
|
b26d0fe557 | |
|
86fcb138e6 | |
|
dbb3458abb | |
|
7af4c38280 | |
|
a407622bea | |
|
9bd430f7c0 | |
|
797a8f926d | |
|
d3e079abc8 | |
|
f2c1806ecc | |
|
85d0539168 | |
|
721397fbe5 | |
|
6416e0636f | |
|
f706ab6c81 | |
|
8798824062 | |
|
ea0558a0ac | |
|
4b9c2bc1d0 | |
|
11a263a39f | |
|
561bd5f840 | |
|
43dac4fd47 | |
|
ea92a6881c | |
|
dc8b84db1b | |
|
15876b52b2 | |
|
c4cfe02e4a | |
|
167393ca86 | |
|
fa188d92c4 | |
|
2761b8147e | |
|
9eaaffae76 | |
|
5188ae6c0c | |
|
e0f65c2376 | |
|
0c6387ade9 | |
|
95c4a2e3e0 | |
|
2e01d11b55 | |
|
7e5f2a45f8 | |
|
759d882c40 | |
|
6118cb6eb2 | |
|
275616e6d6 | |
|
8a7094b572 | |
|
ee0788177a | |
|
84a3ef00f2 | |
|
bbfa2dea94 | |
|
3e50b9cbd6 | |
|
0739575d19 | |
|
94c69474ab | |
|
ce588474d9 | |
|
0bbe953f47 | |
|
6d0e077664 | |
|
eac9132746 | |
|
03b4c60805 | |
|
eec0881fc1 | |
|
f50b223a71 | |
|
e8602cd013 | |
|
3882127f14 | |
|
58fb211eaa | |
|
3642590829 | |
|
aa16d41420 | |
|
12c5f1378d | |
|
cd0c0f80d0 | |
|
f260de99d5 | |
|
3940e1f16f | |
|
167429b3a7 | |
|
b59e0bb244 | |
|
156b73cd35 | |
|
5373b209e3 | |
|
9190b7050f | |
|
ccbb16f8ac | |
|
afecbb70a5 | |
|
74dfa1ebe3 | |
|
18a38c7999 | |
|
bb084fb172 | |
|
4801c12a0d | |
|
d8f51b4fcd | |
|
362f7ab148 | |
|
b0b9b63a2b | |
|
6a88caada4 | |
|
bd76d5da33 | |
|
1ad4c5eed5 | |
|
853f7fdf00 | |
|
d7ec76e87d | |
|
6de9f8eb1b | |
|
578633f12f | |
|
e81023eaa7 | |
|
7611383486 | |
|
178c3463fe | |
|
555c5a1b17 | |
|
d143f06743 | |
|
2d1e43641d | |
|
f0d22114e6 | |
|
c31e080337 | |
|
dfddb51a2c | |
|
2448751fd9 | |
|
7c00be91fe | |
|
d968d04117 | |
|
5545335573 | |
|
06f4681b0c | |
|
754b838c85 | |
|
7a064a8722 | |
|
86dc9ad13e | |
|
0cc878fb1c | |
|
7442d487c7 | |
|
3d7d3a43a3 | |
|
fbd4b30546 | |
|
1f941c54e1 | |
|
c2ccc2a609 | |
|
b2eefc612d | |
|
90454bad8b | |
|
2722a7e0e8 | |
|
21ff4df81e | |
|
6999ceb69e | |
|
a718e19296 | |
|
999a5dfbbd | |
|
e84015862c | |
|
3101972c8d | |
|
1762af54f8 | |
|
17b54c2154 | |
|
bdd0ea2ba8 | |
|
cf43fe814e | |
|
9e565af7cf | |
|
fd77825384 | |
|
9012ee3efb | |
|
06bf631abd | |
|
0ff7d03986 | |
|
2b4dd59212 | |
|
a526834c45 | |
|
347b1fba18 | |
|
e5070427e1 | |
|
0a2f7ab5dd | |
|
bafc7f3b06 | |
|
17015f12cd | |
|
2880844317 | |
|
c873a2142f | |
|
b31bfa343f | |
|
530aaae00d | |
|
10f93f947b | |
|
4286318344 | |
|
160b69d5a7 | |
|
4f70ed00a0 | |
|
c08c18719e | |
|
189efe786a | |
|
45e286f118 | |
|
489660c43c | |
|
931cf064b1 | |
|
ee6f57f776 | |
|
7ba3c70bc2 | |
|
470872a772 | |
|
da593e409a | |
|
eaf1bba233 | |
|
fe081b8ff8 | |
|
b7caa6ef0c | |
|
6e5db379ae | |
|
2a88d048e4 | |
|
e3bbfe97ef | |
|
f25f67be1a | |
|
23dc87881b | |
|
4e8ea2133c | |
|
a6afcbf38c | |
|
01e60cb8a6 | |
|
282d559821 | |
|
f080cfe312 | |
|
442c62f6f9 | |
|
d9b923d0df | |
|
90a7ad6206 | |
|
24387e7a18 | |
|
01994e5338 | |
|
403b1af5c3 | |
|
1dc0595427 | |
|
ba55dff173 | |
|
cad1d86352 | |
|
9806b5c7fd | |
|
46e4420e4e | |
|
c84450af35 | |
|
ceee0467ab | |
|
af5d07ace6 | |
|
e4dab88b15 | |
|
70ce0ef4a2 | |
|
a3240732cc | |
|
da660578b6 | |
|
776cb83a20 | |
|
86eb8cae3d | |
|
75319b6b60 | |
|
5048ee83d4 | |
|
6d33f2c584 | |
|
258ff527f5 | |
|
b10bd0bd9f | |
|
68a36f79a5 | |
|
ad0391059c | |
|
d7fbd07027 | |
|
c1b40c718a | |
|
9fec294452 | |
|
49de6e0094 | |
|
2c6384d942 | |
|
bd76ea52ee | |
|
c70b9ddfc7 | |
|
df31b0710f | |
|
de84505bd2 | |
|
7fcc363468 | |
|
9b09723b78 | |
|
936ad2b27e | |
|
6ba93f2392 | |
|
7e6174a3f9 | |
|
ffacd070db | |
|
e58acb782c | |
|
40aa4c075c | |
|
1ddb6339a7 | |
|
d76a5c1225 | |
|
b0546ee465 | |
|
140d8974b2 | |
|
e875a5ea6b | |
|
fbcafce39f | |
|
e3255e48f1 | |
|
27e18710a2 | |
|
b0dad0af68 | |
|
b9d0ee21f0 | |
|
cabbb552bd | |
|
c12b6fa338 | |
|
a0bdb1eb28 | |
|
dfaff4bc16 | |
|
98a1174200 | |
|
7b5b4e83bb | |
|
833c5968c6 | |
|
ab0f1dff62 | |
|
9e6c1f1716 | |
|
339fa26872 | |
|
e4ab21315b | |
|
660cc04f5d | |
|
e3a025e776 | |
|
9d453ddaef | |
|
3a76b12c97 | |
|
3ee6c78e19 | |
|
694d72e260 | |
|
2335323cef | |
|
b754c2683a | |
|
86dc9241ab | |
|
ca3d21e7df | |
|
8d9e51b156 | |
|
3666f8cbb0 | |
|
34913cc220 | |
|
9b5950db3d | |
|
155a1b2496 | |
|
d80e2e8643 | |
|
93a7ae92fa | |
|
01c418855f | |
|
342905856c | |
|
dad51a172a | |
|
152a3f643c | |
|
244787990c | |
|
9a22b6aedb | |
|
c5bedb04f0 | |
|
a629be0217 | |
|
d8b3a9fe21 | |
|
b6fe808a15 | |
|
69b736d1b9 | |
|
bfe124c6f2 | |
|
35b9ed16cc | |
|
6dae4886cc | |
|
ce81a0a915 | |
|
1d74651e67 | |
|
e8a3cceee7 | |
|
f26a1c8545 | |
|
53335fcbc3 | |
|
a8af3ced89 | |
|
d5ceeead6e | |
|
3b64858965 | |
|
e2259ee878 | |
|
a048ff137d | |
|
0476732809 | |
|
32d21434f8 | |
|
0d8a42b02b | |
|
27de89d262 | |
|
041bfd2ac2 | |
|
19d4aa2873 | |
|
2d66f155ec | |
|
6a9c6c1053 | |
|
1e002130a1 | |
|
e830cc6a02 | |
|
56242a6b55 | |
|
023a4288c8 | |
|
b73c3549ba | |
|
5eb017ad25 | |
|
d21e29885c | |
|
43f1c152ef | |
|
7a82dd0c67 | |
|
ba79c8e24d | |
|
9ecad9383c | |
|
1c63749df7 | |
|
16aa6965bc | |
|
1a6dd30610 | |
|
3d91b9e5e2 | |
|
96ae875976 | |
|
25720e2cf9 | |
|
534ceafa2b | |
|
3cecf809d4 | |
|
98a4d0a817 | |
|
c01f5d5aef | |
|
af57a0b715 | |
|
18e8de0199 |
|
@ -0,0 +1,41 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
|
||||
name: Issue
|
||||
description: Report an issue about the Docker DX extension.
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to open an issue!
|
||||
Please take a look at our [FAQ](https://github.com/docker/vscode-extension/blob/main/FAQ.md) to see if it addresses the issue you are reporting.
|
||||
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Provide a description of the issue you are reporting here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Visual Studio Code version
|
||||
description: |
|
||||
Output of `code -v` command.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Installed extensions in Visual Studio Code
|
||||
description: |
|
||||
Output of `code --list-extensions --show-versions` command.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: |
|
||||
Please provide any additional information that could be useful.
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
signoff_regex="Signed-off-by:"
|
||||
commits=$(gh pr view "$1" --json commits -q ".commits[].oid")
|
||||
|
||||
missing=0
|
||||
|
||||
for sha in $commits; do
|
||||
echo "🔍 Checking commit $sha..."
|
||||
message=$(git log -1 --pretty=format:%B "$sha")
|
||||
|
||||
if echo "$message" | grep -q "$signoff_regex"; then
|
||||
echo "✔ 'Signed-off-by' message found."
|
||||
continue
|
||||
fi
|
||||
|
||||
is_verified=$(gh api repos/${GITHUB_REPOSITORY}/commits/$sha --jq '.commit.verification.verified')
|
||||
if [ "$is_verified" = "true" ]; then
|
||||
echo "✔ Verified signature found."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "::error file=.git/COMMIT_EDITMSG::❌ Commit $sha is missing either a valid Signed-off-by message or a verified (GPG, SSH, or S/MIME) signature."
|
||||
missing=$((missing + 1))
|
||||
done
|
||||
|
||||
if [ "$missing" -gt 0 ]; then
|
||||
echo "❌ Some commits are not properly signed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All commits are properly signed."
|
|
@ -1,52 +1,128 @@
|
|||
name: Build
|
||||
run-name: "Build: ${{ github.event_name != 'workflow_dispatch' && 'Automatic' || 'Release' }}"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
- '**'
|
||||
tags:
|
||||
- v*
|
||||
- v*
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test-latest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [linux, windows, darwin]
|
||||
arch: [amd64, arm64]
|
||||
include:
|
||||
- arch: amd64
|
||||
nodearch: x64
|
||||
- arch: arm64
|
||||
nodearch: arm64
|
||||
- os: windows
|
||||
nodeos: win32
|
||||
ext: .exe
|
||||
- os: darwin
|
||||
nodeos: darwin
|
||||
ext: ""
|
||||
- os: linux
|
||||
nodeos: linux
|
||||
ext: ""
|
||||
|
||||
steps:
|
||||
- name: actions/checkout@v4 (docker/docker-language-server)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: docker/docker-language-server
|
||||
path: docker-language-server
|
||||
|
||||
- name: actions/checkout@v4 (docker/vscode-extension)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: docker/vscode-extension
|
||||
path: vscode-extension
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22.x"
|
||||
node-version: '22.x'
|
||||
|
||||
- working-directory: vscode-extension
|
||||
run: |
|
||||
npm install
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23.8'
|
||||
|
||||
- run: npm install
|
||||
working-directory: vscode-extension
|
||||
|
||||
- run: rm -rf vscode-extension/bin
|
||||
|
||||
- run: mkdir vscode-extension/bin
|
||||
|
||||
- run: make build
|
||||
working-directory: docker-language-server
|
||||
|
||||
- run: mv docker-language-server/docker-language-server-linux-amd64 vscode-extension/bin
|
||||
|
||||
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
|
||||
- run: xvfb-run --auto-servernum --server-args='-screen 0 1920x1080x24' npm test
|
||||
working-directory: vscode-extension
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
path: /tmp/test-resources/screenshots/
|
||||
|
||||
test-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- run: npm install
|
||||
|
||||
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
|
||||
- run: xvfb-run --auto-servernum --server-args='-screen 0 1920x1080x24' npm test
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
path: /tmp/test-resources/screenshots/
|
||||
|
||||
upload:
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test-latest
|
||||
- test-release
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [alpine, linux, win32, darwin]
|
||||
nodearch: [x64, arm64]
|
||||
include:
|
||||
- os: win32
|
||||
nodeos: win32
|
||||
ext: .exe
|
||||
- os: darwin
|
||||
nodeos: darwin
|
||||
ext: ''
|
||||
- os: linux
|
||||
nodeos: linux
|
||||
ext: ''
|
||||
- os: alpine
|
||||
nodeos: linux
|
||||
ext: ''
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- run: |
|
||||
NODE_OS=${{ matrix.nodeos }} NODE_ARCH=${{ matrix.nodearch }} npm install
|
||||
|
||||
- name: Set variables
|
||||
id: set-variables
|
||||
working-directory: vscode-extension
|
||||
run: |
|
||||
VERSION=$(npm pkg get version | tr -d \")
|
||||
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
@ -54,61 +130,113 @@ jobs:
|
|||
SHA=$(git rev-parse --short HEAD)
|
||||
echo "SHA=$SHA" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: actions/checkout@v4 (docker/docker-language-server)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: docker/docker-language-server
|
||||
path: docker-language-server
|
||||
|
||||
- working-directory: docker-language-server
|
||||
run: |
|
||||
GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} make build
|
||||
|
||||
- working-directory: vscode-extension
|
||||
run: mkdir bin
|
||||
|
||||
- working-directory: docker-language-server
|
||||
run: |
|
||||
mv ./docker-language-server-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} ../vscode-extension/bin/
|
||||
|
||||
- name: Build the extension (refs/heads)
|
||||
if: startsWith(github.ref, 'refs/heads')
|
||||
- name: Build the extension
|
||||
env:
|
||||
VERSION: ${{ steps.set-variables.outputs.VERSION }}
|
||||
SHA: ${{ steps.set-variables.outputs.SHA }}
|
||||
working-directory: vscode-extension
|
||||
run: |
|
||||
npm install -g @vscode/vsce
|
||||
vsce package --target ${{ matrix.nodeos }}-${{ matrix.nodearch }} -o docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-$VERSION-$SHA.vsix
|
||||
vsce package --target ${{ matrix.os }}-${{ matrix.nodearch }} -o docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-$VERSION-$SHA.vsix
|
||||
|
||||
- name: actions/upload-artifact@v4 (refs/heads)
|
||||
if: startsWith(github.ref, 'refs/heads')
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}-${{ steps.set-variables.outputs.SHA }}.vsix
|
||||
path: vscode-extension/docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}-${{ steps.set-variables.outputs.SHA }}.vsix
|
||||
name: docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}-${{ steps.set-variables.outputs.SHA }}.vsix
|
||||
path: docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}-${{ steps.set-variables.outputs.SHA }}.vsix
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build the extension (refs/tags/v)
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
VERSION: ${{ steps.set-variables.outputs.VERSION }}
|
||||
working-directory: vscode-extension
|
||||
create-release:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test-latest
|
||||
- test-release
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- name: Set variables
|
||||
id: set-variables
|
||||
run: |
|
||||
npm install -g @vscode/vsce
|
||||
vsce package --target ${{ matrix.nodeos }}-${{ matrix.nodearch }} -o docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-$VERSION.vsix
|
||||
VERSION=$(npm pkg get version | tr -d \")
|
||||
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: actions/upload-artifact@v4 (refs/tags/v)
|
||||
uses: actions/upload-artifact@v4
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
name: docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
path: vscode-extension/docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
if-no-files-found: error
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
node build/releaser.mjs generate-release-notes > release-notes.tmp
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "current_date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 https://github.com/softprops/action-gh-release/commit/c062e08bd532815e2082a85e87e3ef29c3e6d191
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: vscode-extension/docker-vscode-extension-${{ matrix.nodeos }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
name: v${{ steps.set-variables.outputs.version }} - ${{ steps.date.outputs.current_date }}
|
||||
tag_name: v${{ steps.set-variables.outputs.version }}
|
||||
body_path: release-notes.tmp
|
||||
fail_on_unmatched_files: true
|
||||
|
||||
upload-release-binaries:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- create-release
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [alpine, linux, win32, darwin]
|
||||
nodearch: [x64, arm64]
|
||||
include:
|
||||
- os: win32
|
||||
nodeos: win32
|
||||
ext: .exe
|
||||
- os: darwin
|
||||
nodeos: darwin
|
||||
ext: ''
|
||||
- os: linux
|
||||
nodeos: linux
|
||||
ext: ''
|
||||
- os: alpine
|
||||
nodeos: linux
|
||||
ext: ''
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- run: |
|
||||
NODE_OS=${{ matrix.nodeos }} NODE_ARCH=${{ matrix.nodearch }} npm install
|
||||
|
||||
- name: Set variables
|
||||
id: set-variables
|
||||
run: |
|
||||
VERSION=$(npm pkg get version | tr -d \")
|
||||
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build the extension
|
||||
env:
|
||||
VERSION: ${{ steps.set-variables.outputs.VERSION }}
|
||||
run: |
|
||||
npm install -g @vscode/vsce
|
||||
vsce package --target ${{ matrix.os }}-${{ matrix.nodearch }} -o docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-$VERSION.vsix
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
path: docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
if-no-files-found: error
|
||||
|
||||
- uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 https://github.com/softprops/action-gh-release/commit/c062e08bd532815e2082a85e87e3ef29c3e6d191
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: v${{ steps.set-variables.outputs.version }}
|
||||
files: docker-vscode-extension-${{ matrix.os }}-${{ matrix.nodearch }}-${{ steps.set-variables.outputs.VERSION }}.vsix
|
||||
if-no-files-found: error
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
name: Prepare release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version_type:
|
||||
description: Version type
|
||||
required: true
|
||||
default: minor
|
||||
type: choice
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
prepare-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
- name: Update versions in package.json and package-lock.json
|
||||
id: version
|
||||
run: |
|
||||
npm version ${{ github.event.inputs.version_type }} --no-git-tag-version
|
||||
NEW_VERSION=$(npm pkg get version | tr -d \")
|
||||
echo "New version (${{ github.event.inputs.version_type }}): $NEW_VERSION"
|
||||
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Update changelog to version ${{ steps.version.outputs.new_version }}
|
||||
run: |
|
||||
node build/releaser.mjs update-changelog ${{ steps.version.outputs.new_version }}
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config --local user.email "${{ github.actor }}@users.noreply.github.com"
|
||||
git config --local user.name "${{ github.actor }}"
|
||||
|
||||
- name: Create pull request
|
||||
# https://github.com/peter-evans/create-pull-request/releases/tag/v7.0.8
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
base: main
|
||||
branch: bot/prepare-release-v${{ steps.version.outputs.new_version }}
|
||||
commit-message: |
|
||||
Prepare for the v${{ steps.version.outputs.new_version }} release
|
||||
|
||||
This commit was generated by a GitHub Action workflow. It was triggered
|
||||
by ${{ github.actor }}.
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
title: 'Prepare for the v${{ steps.version.outputs.new_version }} release (triggered by ${{ github.actor }})'
|
||||
body: |
|
||||
This pull request was generated by `./github/workflows/prepare-release.yml`.
|
||||
|
||||
It modifies the following three files:
|
||||
- `CHANGELOG.md` (update the section header to ${{ steps.version.outputs.new_version }} with today's date in UTC and the links at the bottom)
|
||||
- `package.json` (update version number to ${{ steps.version.outputs.new_version }} )
|
||||
- `package-lock.json` (update version number to ${{ steps.version.outputs.new_version }})
|
||||
draft: false
|
||||
add-paths: |
|
||||
CHANGELOG.md
|
||||
package.json
|
||||
package-lock.json
|
||||
assignees: ${{ github.actor }}
|
||||
reviewers: ${{ github.actor }}
|
|
@ -0,0 +1,20 @@
|
|||
name: Verify commit signatures
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
check-commits:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run commit sign-off check script
|
||||
run: |
|
||||
.github/scripts/check-commits.sh "${{ github.event.pull_request.number }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -3,4 +3,6 @@ dist
|
|||
node_modules
|
||||
bin
|
||||
.vscode-test/
|
||||
syntaxes/
|
||||
*.vsix
|
||||
.test-extensions
|
||||
|
|
|
@ -7,8 +7,7 @@ node_modules
|
|||
out
|
||||
bin
|
||||
.vscode-test/
|
||||
|
||||
.github/workflows/build.yml
|
||||
|
||||
|
||||
.test-extensions
|
||||
syntaxes/
|
||||
misc/
|
||||
*/coverage
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}/test/workspace"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
|
@ -18,4 +19,4 @@
|
|||
"preLaunchTask": "${defaultBuildTask}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,6 +1,12 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
.vscode/**
|
||||
.vscode-test/**
|
||||
node_modules/**
|
||||
build/**
|
||||
out/**
|
||||
resources/readme/**
|
||||
src/**
|
||||
test/**
|
||||
misc/**
|
||||
.gitignore
|
||||
.yarnrc
|
||||
webpack.config.js
|
||||
|
@ -17,3 +20,4 @@ vsc-extension-quickstart.md
|
|||
.devcontainer/**
|
||||
.prettierignore
|
||||
.prettierrc.yml
|
||||
.test-extensions
|
||||
|
|
489
CHANGELOG.md
|
@ -2,6 +2,470 @@
|
|||
|
||||
All notable changes to the Docker DX extension will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Dockerfile
|
||||
- textDocument/inlayHint
|
||||
- show when an image was last pushed ([docker/docker-language-server#431](https://github.com/docker/docker-language-server/issues/431))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- suggest image tags for images from Docker Hub ([docker/docker-language-server#375](https://github.com/docker/docker-language-server/issues/375))
|
||||
- textDocument/documentLink
|
||||
- support providing links for the `env_file` attribute of a service object ([docker/docker-language-server#436](https://github.com/docker/docker-language-server/issues/436))
|
||||
- support providing links for the `env_file` for included paths ([docker/docker-language-server#438](https://github.com/docker/docker-language-server/issues/438))
|
||||
- Bake
|
||||
- textDocument/completion
|
||||
- provide local file and folder name suggestions ([docker/docker-language-server#414](https://github.com/docker/docker-language-server/issues/414))
|
||||
- `context` attribute in a `target` block
|
||||
- `contexts` attribute in a `target` block
|
||||
- `dockerfile` attribute in a `target` block
|
||||
|
||||
### Fixed
|
||||
|
||||
- Dockerfile
|
||||
- textDocument/hover
|
||||
- ignore 4XX errors when hovering over images with a non-standard tag ([docker/docker-language-server#371](https://github.com/docker/docker-language-server/issues/371))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- correct file system suggestions if an absolute path is used ([docker/docker-language-server#443](https://github.com/docker/docker-language-server/issues/443))
|
||||
- textDocument/documentLink
|
||||
- stop returning links for alias nodes in included paths ([docker/docker-language-server#439](https://github.com/docker/docker-language-server/issues/439))
|
||||
- Bake
|
||||
- textDocument/completion
|
||||
- check the type of the block before suggesting items ([docker/docker-language-server#422](https://github.com/docker/docker-language-server/issues/422))
|
||||
|
||||
## [0.15.0] - 2025-08-13
|
||||
|
||||
### Added
|
||||
|
||||
- added a language configuration for the `dockerbake` language to improve the editing experience ([#184](https://github.com/docker/vscode-extension/issues/184))
|
||||
- Compose
|
||||
- updated Compose schema to the latest version
|
||||
|
||||
### Fixed
|
||||
|
||||
- Bake
|
||||
- textDocument/hover
|
||||
- fix error when hovering inside a comment ([docker/docker-language-server#410](https://github.com/docker/docker-language-server/issues/410))
|
||||
|
||||
## [0.14.0] - 2025-08-06
|
||||
|
||||
### Added
|
||||
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- provide local file and folder name suggestions when modifying simple strings
|
||||
- service volumes ([docker/docker-language-server#376](https://github.com/docker/docker-language-server/issues/376))
|
||||
- `context` attribute of a `build` object of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `dockerfile` attribute of a `build` object of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `file` attribute of a `credential_spec` object of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `env_file` of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `path` attribute of an `env_file` array item of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `file` attribute of an `extends` object of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `label_file` of a service ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `file` attribute of a config ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `file` attribute of a secret ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- string items of include objects ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `env_file` attribute of include objects ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
- `path` attribute of include objects ([docker/docker-language-server#403](https://github.com/docker/docker-language-server/issues/403))
|
||||
|
||||
### Fixed
|
||||
|
||||
- fix Dockerfile Language Server crash with tabbed heredoc delimiters ([#171](https://github.com/docker/vscode-extension/issues/171))
|
||||
- fix Buildx debugger integration so that it works on Windows ([#181](https://github.com/docker/vscode-extension/issues/181))
|
||||
- allow switching the builder used for debug sessions ([#183](https://github.com/docker/vscode-extension/pull/183))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- fix build stage lookups for files in a folder under the `\\wsl$` host ([docker/docker-language-server#382](https://github.com/docker/docker-language-server/issues/382))
|
||||
- textDocument/documentLink
|
||||
- improve handling of malformed image attribute values with registry prefixes ([docker/docker-language-server#369](https://github.com/docker/docker-language-server/issues/369))
|
||||
- convert links properly if a WSL URI with a dollar sign is used ([docker/docker-language-server#366](https://github.com/docker/docker-language-server/issues/366))
|
||||
- Bake
|
||||
- textDocument/codeLens
|
||||
- refactor the URI handling code so it will accept a WSL URI with a dollar sign ([docker/docker-language-server#388](https://github.com/docker/docker-language-server/issues/388))
|
||||
- textDocument/completion
|
||||
- fix build stage and ARG name inference completion items for files in a folder under the `\\wsl$` host ([docker/docker-language-server#396](https://github.com/docker/docker-language-server/issues/396))
|
||||
- textDocument/definition
|
||||
- handle WSL URIs with a dollar sign properly to fix build stage lookups on those hosts ([docker/docker-language-server#390](https://github.com/docker/docker-language-server/issues/390))
|
||||
- handle WSL URIs with a dollar sign properly to fix build ARG reference lookups on those hosts ([docker/docker-language-server#393](https://github.com/docker/docker-language-server/issues/393))
|
||||
- textDocument/documentLink
|
||||
- convert links properly if a WSL URI with a dollar sign is used ([docker/docker-language-server#378](https://github.com/docker/docker-language-server/issues/378))
|
||||
- textDocument/inlayHint
|
||||
- refactor the URI handling code so it will process a WSL URI with a dollar sign correctly ([docker/docker-language-server#395](https://github.com/docker/docker-language-server/issues/395))
|
||||
- textDocument/inlineCompletion
|
||||
- convert links properly if a WSL URI with a dollar sign is used ([docker/docker-language-server#384](https://github.com/docker/docker-language-server/issues/384))
|
||||
- textDocument/publishDiagnostics
|
||||
- update the URI handling so that a WSL URI with a dollar sign can be scanned for errors ([docker/docker-language-server#386](https://github.com/docker/docker-language-server/issues/386))
|
||||
|
||||
## [0.13.0] - 2025-07-17
|
||||
|
||||
### Added
|
||||
|
||||
- Compose
|
||||
- textDocument/documentLink
|
||||
- add anchor resolution for all supported document links ([docker/docker-language-server#348](https://github.com/docker/docker-language-server/issues/348))
|
||||
- return document links for the `file` attribute of a service object's `extends` attribute object ([docker/docker-language-server#172](https://github.com/docker/docker-language-server/issues/172))
|
||||
- provide document links for models on Docker Hub and Hugging Face ([docker/docker-language-server#356](https://github.com/docker/docker-language-server/issues/356))
|
||||
- return document links for the `label_file` attribute of a service object ([docker/docker-language-server#360](https://github.com/docker/docker-language-server/issues/360))
|
||||
- textDocument/hover
|
||||
- support hovering over referenced models ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
|
||||
### Changed
|
||||
|
||||
- errors with the Docker Language Server will no longer be hidden
|
||||
|
||||
### Fixed
|
||||
|
||||
- stop the language server from crashing when opened inside a WSL folder with a dollar sign ([#165](https://github.com/docker/vscode-extension/issues/165))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- prevent wildcard object attribute suggestions if the text cursor is not at the right indentation for attributes to be inserted ([docker/docker-language-server#342](https://github.com/docker/docker-language-server/issues/342))
|
||||
- textDocument/documentLink
|
||||
- fix bounds index error if a quoted string just has a registry and the colon character at the end ([docker/docker-language-server#351](https://github.com/docker/docker-language-server/issues/351))
|
||||
|
||||
## [0.12.0] - 2025-07-09
|
||||
|
||||
### Added
|
||||
|
||||
- a new experimental `docker.extension.enableBuildDebugging` setting for developing and testing the upcoming build debugging feature
|
||||
- this feature is under active development and is not ready for general use
|
||||
- Compose
|
||||
- update schema to the latest version
|
||||
- textDocument/completion
|
||||
- support completing model object names ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
- textDocument/definition
|
||||
- support jumping to referenced model objects ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
- textDocument/documentHighlight
|
||||
- support highlighting referenced models objects ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
- textDocument/documentLink
|
||||
- support recursing into anchors when searching for document links ([docker/docker-language-server#329](https://github.com/docker/docker-language-server/issues/329))
|
||||
- return document links for the `file` attribute of a service object's `credential_spec` ([docker/docker-language-server#338](https://github.com/docker/docker-language-server/issues/338))
|
||||
- textDocument/documentSymbol
|
||||
- show model objects in the document symbol tree ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
- textDocument/prepareRename
|
||||
- allow preparing rename on model objects ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
- textDocument/rename
|
||||
- support renaming model objects ([docker/docker-language-server#343](https://github.com/docker/docker-language-server/issues/343))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- prevent errors if an empty JSON object is the content of the YAML file ([docker/docker-language-server#330](https://github.com/docker/docker-language-server/issues/330))
|
||||
- check character offset before processing to prevent errors ([docker/docker-language-server#333](https://github.com/docker/docker-language-server/issues/333))
|
||||
|
||||
## [0.11.0] - 2025-06-23
|
||||
|
||||
### Added
|
||||
|
||||
- Dockerfile
|
||||
- include the Dockerfile Language Server written in TypeScript into the extension
|
||||
- draw horizontal lines between each `FROM` instruction to help users visually distinguish the different parts of a Dockerfile ([#147](https://github.com/docker/vscode-extension/issues/147))
|
||||
- a new `docker.extension.editor.dockerfileBuildStageDecorationLines` setting to toggle the divider lines, defaults to `true`
|
||||
|
||||
## [0.10.0] - 2025-06-12
|
||||
|
||||
### Added
|
||||
|
||||
- Dockerfile
|
||||
- textDocument/publishDiagnostics
|
||||
- provide code actions to easily ignore build checks ([docker/docker-language-server#320](https://github.com/docker/docker-language-server/issues/320))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- add support for suggesting `include` properties ([docker/docker-language-server#316](https://github.com/docker/docker-language-server/issues/316))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- fix error case triggered by using code completion before the first node ([docker/docker-language-server#314](https://github.com/docker/docker-language-server/issues/314))
|
||||
- textDocument/definition
|
||||
- check the type of a dependency node's value before assuming it is a map and recursing into it ([docker/docker-language-server#324](https://github.com/docker/docker-language-server/issues/324))
|
||||
- textDocument/hover
|
||||
- protect the processing of included files if the node is not a proper array ([docker/docker-language-server#322](https://github.com/docker/docker-language-server/issues/322))
|
||||
- Bake
|
||||
- textDocument/inlineCompletion
|
||||
- check that the request is within the document's bounds when processing the request ([docker/docker-language-server#318](https://github.com/docker/docker-language-server/issues/318))
|
||||
|
||||
## [0.9.0] - 2025-06-10
|
||||
|
||||
### Added
|
||||
|
||||
- Compose
|
||||
- textDocument/definition
|
||||
- recurse into anchors when evaluating the cursor's position ([docker/docker-language-server#305](https://github.com/docker/docker-language-server/issues/305))
|
||||
- textDocument/documentHighlight
|
||||
- recurse into anchors when evaluating the cursor's position ([docker/docker-language-server#305](https://github.com/docker/docker-language-server/issues/305))
|
||||
- textDocument/hover
|
||||
- resolve anchors when constructing the path of the hovered item ([docker/docker-language-server#303](https://github.com/docker/docker-language-server/issues/303))
|
||||
- textDocument/prepareRename
|
||||
- recurse into anchors when evaluating the cursor's position ([docker/docker-language-server#305](https://github.com/docker/docker-language-server/issues/305))
|
||||
- textDocument/rename
|
||||
- recurse into anchors when evaluating the cursor's position ([docker/docker-language-server#305](https://github.com/docker/docker-language-server/issues/305))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- stop volume named references from causing volume attributes to not be suggested ([docker/docker-language-server#309](https://github.com/docker/docker-language-server/issues/309))
|
||||
- textDocument/documentLink
|
||||
- ensure the image attribute is valid before trying to process it for document links ([docker/docker-language-server#306](https://github.com/docker/docker-language-server/issues/306))
|
||||
- Bake
|
||||
- textDocument/definition
|
||||
- fix nil pointers when navigating around a top level attribute that is not in any block ([docker/docker-language-server#311](https://github.com/docker/docker-language-server/issues/311))
|
||||
|
||||
## [0.8.1] - 2025-06-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- lock cache manager when deleting to prevent concurrent map writes ([docker/docker-language-server#298](https://github.com/docker/docker-language-server/issues/298))
|
||||
- initialize
|
||||
- return JSON-RPC error if an invalid URI was sent with the request ([docker/docker-language-server#292](https://github.com/docker/docker-language-server/issues/292))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- check for whitespace when performing prefix calculations for build target suggestions ([docker/docker-language-server#294](https://github.com/docker/docker-language-server/issues/294))
|
||||
- return an empty result instead of an internal server error if the request's parameters are outside the document's bounds ([docker/docker-language-server#296](https://github.com/docker/docker-language-server/issues/296))
|
||||
- check the node path's length before recursing deeper for pattern properties matches ([docker/docker-language-server#300](https://github.com/docker/docker-language-server/issues/300))
|
||||
- textDocument/hover
|
||||
- fix error caused by casting a node without checking its type first ([docker/docker-language-server#290](https://github.com/docker/docker-language-server/issues/290))
|
||||
|
||||
## [0.8.0] - 2025-06-05
|
||||
|
||||
### Added
|
||||
|
||||
- send errors to BugSnag if error telemetry is configured to be allowed and sent
|
||||
- Dockerfile
|
||||
- provide code actions for Scout vulnerabilities that will open the settings page so that users can opt-out of them easily ([#130](https://github.com/docker/vscode-extension/issues/130))
|
||||
- textDocument/hover
|
||||
- support configuring specific vulnerability hovers with an experimental setting ([#101](https://github.com/docker/vscode-extension/issues/101))
|
||||
- textDocument/publishDiagnostics
|
||||
- support filtering specific vulnerability diagnostics with an experimental setting ([#101](https://github.com/docker/vscode-extension/issues/101))
|
||||
- Compose
|
||||
- created `docker.extension.enableComposeLanguageServer` for globally toggling Compose editor features
|
||||
- updated Compose schema to the latest version ([docker/docker-language-server#117](https://github.com/docker/docker-language-server/issues/117))
|
||||
- textDocument/completion
|
||||
- add support for attribute name and value completion
|
||||
- suggest dependent service names for the `depends_on` attribute ([docker/docker-language-server#131](https://github.com/docker/docker-language-server/issues/131))
|
||||
- suggest dependent network names for the `networks` attribute ([docker/docker-language-server#132](https://github.com/docker/docker-language-server/issues/132))
|
||||
- suggest dependent volume names for the `volumes` attribute ([docker/docker-language-server#133](https://github.com/docker/docker-language-server/issues/133))
|
||||
- suggest dependent config names for the `configs` attribute ([docker/docker-language-server#134](https://github.com/docker/docker-language-server/issues/134))
|
||||
- suggest dependent secret names for the `secrets` attribute ([docker/docker-language-server#135](https://github.com/docker/docker-language-server/issues/135))
|
||||
- improve code completion by automatically including required attributes in completion items ([docker/docker-language-server#155](https://github.com/docker/docker-language-server/issues/155))
|
||||
- support build stage names for the `target` attribute ([docker/docker-language-server#173](https://github.com/docker/docker-language-server/issues/173))
|
||||
- suggest service names for a service's `extends` or `extends.service` attribute ([docker/docker-language-server#184](https://github.com/docker/docker-language-server/issues/184))
|
||||
- textDocument/definition
|
||||
- support looking up volume references ([docker/docker-language-server#147](https://github.com/docker/docker-language-server/issues/147))
|
||||
- support navigating to a dependency that is defined in another file ([docker/docker-language-server#190](https://github.com/docker/docker-language-server/issues/190))
|
||||
- support navigating to the defined YAML anchor from an alias reference ([#264](https://github.com/docker/docker-language-server/issues/264))
|
||||
- textDocument/documentHighlight
|
||||
- support highlighting object references and anchors and aliases
|
||||
- textDocument/documentLink
|
||||
- support opening a referenced Dockerfile from the `build` object's `dockerfile` attribute ([#69](https://github.com/docker/docker-language-server/issues/69))
|
||||
- support opening a referenced file from a config's `file` attribute ([#271](https://github.com/docker/docker-language-server/issues/271))
|
||||
- support opening a referenced file from a secret's `file` attribute ([#272](https://github.com/docker/docker-language-server/issues/272))
|
||||
- provide document links when an included file is also a YAML anchor ([#275](https://github.com/docker/docker-language-server/issues/275))
|
||||
- consider quotes when calculating the link's range ([#242](https://github.com/docker/docker-language-server/issues/242))
|
||||
- consider anchors and aliases instead of assuming everything are strings ([#266](https://github.com/docker/docker-language-server/issues/266))
|
||||
- textDocument/formatting
|
||||
- add support to format YAML files that do not have clear syntactical errors ([docker/docker-language-server#165](https://github.com/docker/docker-language-server/issues/165))
|
||||
- textDocument/hover
|
||||
- add support for hovering over attribute keys and showing the descriptions in the schema with links to the schema and the online documentation
|
||||
- render a referenced object's or YAML anchor or alias's textual YAML content as a hover
|
||||
- include the range of the hovered element to clearly identify what is being hovered over for the client ([#256](https://github.com/docker/docker-language-server/issues/256))
|
||||
- textDocument/inlayHint
|
||||
- show the parent service's value if it is being overridden and they are not object attributes ([docker/docker-language-server#156](https://github.com/docker/docker-language-server/issues/156))
|
||||
- textDocument/publishDiagnostics
|
||||
- report YAML syntax errors ([docker/docker-language-server#167](https://github.com/docker/docker-language-server/issues/167))
|
||||
- textDocument/prepareRename
|
||||
- support rename preparation requests ([docker/docker-language-server#150](https://github.com/docker/docker-language-server/issues/150))
|
||||
- textDocument/rename
|
||||
- support renaming named object references and YAML anchors and aliases
|
||||
- Bake
|
||||
- textDocument/publishDiagnostics
|
||||
- support filtering specific vulnerability diagnostics with an experimental setting ([#101](https://github.com/docker/vscode-extension/issues/101))
|
||||
|
||||
### Changed
|
||||
|
||||
- diagnostics will now include Docker DX in its name to help users identify which diagnostics are coming from this extension ([#127](https://github.com/docker/vscode-extension/issues/127))
|
||||
- Dockerfile
|
||||
- textDocument/hover
|
||||
- `recommended_tag` diagnostics are now hidden by default ([docker/docker-language-server#223](https://github.com/docker/docker-language-server/issues/223))
|
||||
- textDocument/publishDiagnostics
|
||||
- hide `not_pinned_digest` diagnostics from Scout by default ([docker/docker-language-server#216](https://github.com/docker/docker-language-server/issues/216))
|
||||
- recommended tag hovers are now hidden by default ([docker/docker-language-server#223](https://github.com/docker/docker-language-server/issues/223))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Dockerfile
|
||||
- textDocument/codeAction
|
||||
- preserve instruction flags when fixing a `not_pinned_digest` diagnostic ([docker/docker-language-server#123](https://github.com/docker/docker-language-server/issues/123))
|
||||
- textDocument/definition
|
||||
- fix range calculation when the element is quoted ([#255](https://github.com/docker/docker-language-server/issues/255))
|
||||
- textDocument/hover
|
||||
- hide vulnerability hovers if the top level setting is disabled ([docker/docker-language-server#226](https://github.com/docker/docker-language-server/issues/226))
|
||||
- textDocument/publishDiagnostics
|
||||
- ignore the diagnostic's URL and do not set it if it is evaluated to be the empty string ([docker/docker-language-server#219](https://github.com/docker/docker-language-server/issues/219))
|
||||
- consider flag changes when determining whether to scan a file again or not ([docker/docker-language-server#224](https://github.com/docker/docker-language-server/issues/224))
|
||||
- Compose
|
||||
- textDocument/completion
|
||||
- resolved a spacing offset issue with object or array completions ([docker/docker-language-server#115](https://github.com/docker/docker-language-server/issues/115))
|
||||
- suggest completion items for array items that use an object schema directly ([docker/docker-language-server#161](https://github.com/docker/docker-language-server/issues/161))
|
||||
- textDocument/definition
|
||||
- consider `extends` when looking up a service reference ([docker/docker-language-server#170](https://github.com/docker/docker-language-server/issues/170))
|
||||
- recurse into YAML anchors if they are defined on a service object ([#287](https://github.com/docker/docker-language-server/issues/287))
|
||||
- textDocument/hover
|
||||
- fixed a case where an object reference's description would not be returned in a hover result ([docker/docker-language-server#233](https://github.com/docker/docker-language-server/issues/233))
|
||||
- Bake
|
||||
- textDocument/publishDiagnostics
|
||||
- stop flagging `BUILDKIT_SYNTAX` as an unrecognized `ARG` ([docker/docker-language-server#187](https://github.com/docker/docker-language-server/issues/187))
|
||||
- use inheritance to determine if an `ARG` is truly unused ([docker/docker-language-server#198](https://github.com/docker/docker-language-server/issues/198))
|
||||
- correct range calculations for malformed variable interpolation errors ([docker/docker-language-server#203](https://github.com/docker/docker-language-server/issues/203))
|
||||
- filter out variables when resolving Dockerfile paths to prevent false positives from being reported ([docker/docker-language-server#263](https://github.com/docker/docker-language-server/issues/263))
|
||||
|
||||
### Removed
|
||||
|
||||
- Compose
|
||||
- removed the `docker.extension.experimental.composeCompletions` setting in favour for the new `docker.extension.enableComposeLanguageServer` setting
|
||||
|
||||
## [0.7.0] - 2025-05-21
|
||||
|
||||
### Added
|
||||
|
||||
- tagged appropriate settings to make them easier to search for
|
||||
- suggest the user install Docker Desktop if Scout cannot be found
|
||||
- prompt the user about duplicated Compose features if Red Hat's YAML extension is also installed
|
||||
|
||||
## [0.6.0] - 2025-04-29
|
||||
|
||||
### Added
|
||||
|
||||
- Compose
|
||||
- textDocument/definition
|
||||
- support lookup of `configs`, `networks`, and `secrets` referenced inside `services` object ([#91](https://github.com/docker/docker-language-server/issues/91))
|
||||
- textDocument/documentLink
|
||||
- support opening a referenced image's page as a link ([#91](https://github.com/docker/docker-language-server/issues/91))
|
||||
- textDocument/hover
|
||||
- extract descriptions and enum values from the Compose specification and display them as hovers ([#101](https://github.com/docker/docker-language-server/issues/101))
|
||||
|
||||
## [0.5.0] - 2025-04-28
|
||||
|
||||
### Added
|
||||
|
||||
- add support for the `alpine-x64` and `alpine-arm64` targets ([#93](https://github.com/docker/vscode-extension/issues/93))
|
||||
- Bake
|
||||
- textDocument/definition
|
||||
- allow jumping to a target block when referencing its attribute ([docker/docker-language-server#78](https://github.com/docker/docker-language-server/issues/78))
|
||||
- Compose
|
||||
- textDocument/definition
|
||||
- allow looking up referenced services when using the short form syntax for `depends_on` ([docker/docker-language-server#67](https://github.com/docker/docker-language-server/issues/67))
|
||||
- allow looking up referenced services when using the long form syntax for `depends_on` ([docker/docker-language-server#68](https://github.com/docker/docker-language-server/issues/68))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Bake
|
||||
- textDocument/semanticTokens/full
|
||||
- ensure semantic tokens are only calculated for Bake files ([docker/docker-language-server#85](https://github.com/docker/docker-language-server/pull/85))
|
||||
|
||||
## [0.4.10] - 2025-04-21
|
||||
|
||||
### Changed
|
||||
|
||||
- updated the included Docker Language Server from 0.3.5 to 0.3.7
|
||||
- Bake
|
||||
- textDocument/publishDiagnostics
|
||||
- consider the context attribute when determining which Dockerfile the Bake target is for ([docker/docker-language-server#57](https://github.com/docker/docker-language-server/issues/57))
|
||||
- textDocument/inlayHints
|
||||
- consider the context attribute when determining which Dockerfile to use for inlaying default values of `ARG` variables ([docker/docker-language-server#60](https://github.com/docker/docker-language-server/pull/60))
|
||||
- textDocument/completion
|
||||
- consider the context attribute when determining which Dockerfile to use for looking up build stages ([docker/docker-language-server#61](https://github.com/docker/docker-language-server/pull/61))
|
||||
- textDocument/definition
|
||||
- consider the context attribute when trying to resolve the Dockerfile to use for `ARG` variable definitions ([docker/docker-language-server#62](https://github.com/docker/docker-language-server/pull/62))
|
||||
- fix a panic that may occur if a for loop did not have a conditional expression ([docker/docker-language-server#65](https://github.com/docker/docker-language-server/pull/65))
|
||||
|
||||
### Fixed
|
||||
|
||||
- set the Docker Desktop prompt setting correctly ([#90](https://github.com/docker/vscode-extension/issues/90))
|
||||
|
||||
## [0.4.9] - 2025-04-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- apply the Scout vulnerability setting correctly if multiple files are opened ([#82](https://github.com/docker/vscode-extension/pull/82))
|
||||
- capture more error telemetry to try to understand the last few crashes ([#83](https://github.com/docker/vscode-extension/pull/83))
|
||||
- make the language server binary executable before trying to start it ([#84](https://github.com/docker/vscode-extension/pull/84))
|
||||
|
||||
## [0.4.8] - 2025-04-14
|
||||
|
||||
### Added
|
||||
|
||||
- capture errors from the language server not being able to start
|
||||
|
||||
## [0.4.7] - 2025-04-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- pick the user's home folder when scanning for CVEs with Scout if no workspace folder has been opened ([#76](https://github.com/docker/vscode-extension/issues/76))
|
||||
- ignore incorrect scalar values in Compose files so that they stop getting incorrectly rendered in the outline ([docker/docker-language-server#50](https://github.com/docker/docker-language-server/pull/50))
|
||||
|
||||
## [0.4.6] - 2025-04-09
|
||||
|
||||
### Added
|
||||
|
||||
- capture some more error messages to better understand why the language server is crashing on some systems
|
||||
- updated the readme so it calls out how this extension is getting installed
|
||||
|
||||
## [0.4.5] - 2025-04-09
|
||||
|
||||
### Fixed
|
||||
|
||||
- update the language server so that it will not crash when handling messages
|
||||
|
||||
## [0.4.4] - 2025-04-09
|
||||
|
||||
### Fixed
|
||||
|
||||
- include a language server fix to prevent it from crashing when opening Bake files with comments placed at the end of a line
|
||||
|
||||
## [0.4.3] - 2025-04-09
|
||||
|
||||
### Fixed
|
||||
|
||||
- surface errors with Docker Bake or Docker Scout to the user instead of failing silently
|
||||
|
||||
## [0.4.2] - 2025-04-08
|
||||
|
||||
### Changed
|
||||
|
||||
- include recognizable error messages in the telemetry data
|
||||
|
||||
## [0.4.1] - 2025-04-08
|
||||
|
||||
### Removed
|
||||
|
||||
- removed references to the feature flag in public-facing documentation
|
||||
|
||||
## [0.4.0] - 2025-04-08
|
||||
|
||||
### Changed
|
||||
|
||||
- automatically download a binary of the language server when `npm install` is run to make development a little easier
|
||||
|
||||
### Removed
|
||||
|
||||
- removed the feature flag so that the extension is live for everyone
|
||||
|
||||
## [0.3.0]
|
||||
|
||||
### Changed
|
||||
|
||||
- suppress duplicated errors that are reported by both the Dockerfile Language Server and the Docker Language Server ([#33](https://github.com/docker/vscode-extension/issues/33))
|
||||
|
||||
### Fixed
|
||||
|
||||
- always register the Scout command so that the gradual rollout will not prevent the command from working ([#44](https://github.com/docker/vscode-extension/issues/44))
|
||||
|
||||
## [0.2.0] - 2025-03-28
|
||||
|
||||
### Added
|
||||
|
@ -39,5 +503,30 @@ All notable changes to the Docker DX extension will be documented in this file.
|
|||
- error reporting
|
||||
- Compose outline support
|
||||
|
||||
[Unreleased]: https://github.com/docker/docker-language-server/compare/v0.15.0...main
|
||||
[0.15.0]: https://github.com/docker/docker-language-server/compare/v0.14.0...v0.15.0
|
||||
[0.14.0]: https://github.com/docker/vscode-extension/compare/v0.13.0...v0.14.0
|
||||
[0.13.0]: https://github.com/docker/vscode-extension/compare/v0.12.0...v0.13.0
|
||||
[0.12.0]: https://github.com/docker/vscode-extension/compare/v0.11.0...v0.12.0
|
||||
[0.11.0]: https://github.com/docker/vscode-extension/compare/v0.10.0...v0.11.0
|
||||
[0.10.0]: https://github.com/docker/vscode-extension/compare/v0.9.0...v0.10.0
|
||||
[0.9.0]: https://github.com/docker/vscode-extension/compare/v0.8.1...v0.9.0
|
||||
[0.8.1]: https://github.com/docker/vscode-extension/compare/v0.8.0...v0.8.1
|
||||
[0.8.0]: https://github.com/docker/vscode-extension/compare/v0.7.0...v0.8.0
|
||||
[0.7.0]: https://github.com/docker/vscode-extension/compare/v0.6.0...v0.7.0
|
||||
[0.6.0]: https://github.com/docker/vscode-extension/compare/v0.5.0...v0.6.0
|
||||
[0.5.0]: https://github.com/docker/vscode-extension/compare/v0.4.10...v0.5.0
|
||||
[0.4.10]: https://github.com/docker/vscode-extension/compare/v0.4.9...v0.4.10
|
||||
[0.4.9]: https://github.com/docker/vscode-extension/compare/v0.4.8...v0.4.9
|
||||
[0.4.8]: https://github.com/docker/vscode-extension/compare/v0.4.7...v0.4.8
|
||||
[0.4.7]: https://github.com/docker/vscode-extension/compare/v0.4.6...v0.4.7
|
||||
[0.4.6]: https://github.com/docker/vscode-extension/compare/v0.4.5...v0.4.6
|
||||
[0.4.5]: https://github.com/docker/vscode-extension/compare/v0.4.4...v0.4.5
|
||||
[0.4.4]: https://github.com/docker/vscode-extension/compare/v0.4.3...v0.4.4
|
||||
[0.4.3]: https://github.com/docker/vscode-extension/compare/v0.4.2...v0.4.3
|
||||
[0.4.2]: https://github.com/docker/vscode-extension/compare/v0.4.1...v0.4.2
|
||||
[0.4.1]: https://github.com/docker/vscode-extension/compare/v0.4.0...v0.4.1
|
||||
[0.4.0]: https://github.com/docker/vscode-extension/compare/v0.3.0...v0.4.0
|
||||
[0.3.0]: https://github.com/docker/vscode-extension/compare/v0.2.0...v0.3.0
|
||||
[0.2.0]: https://github.com/docker/vscode-extension/compare/v0.1.1...v0.2.0
|
||||
[0.1.1]: https://github.com/docker/vscode-extension/compare/v0.1.0...v0.1.1
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# Build Debugging
|
||||
|
||||
> ⚠️ This feature is under **active** development and there may be breaking changes as we continue experimenting and fine tuning it. If you have feedback about this feature, please [open an issue](https://github.com/docker/vscode-extension/issues) or [start a discussion thread](https://github.com/docker/vscode-extension/discussions) and let us know what you think.
|
||||
|
||||
## Overview
|
||||
|
||||
Buildx provides an implementation of the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/). This means development tools that support and implement the protocol can interface with Buildx directly and step through the build process in real-time.
|
||||
|
||||
## Requirements
|
||||
|
||||
To use the build debugging feature, you will need to have [Buildx](https://github.com/docker/buildx) installed. The minimum supported version is v0.26.1. You can install Buildx manually by following the instructions [here](https://github.com/docker/buildx?tab=readme-ov-file#manual-download).
|
||||
|
||||
1. Run `docker buildx version` to check your Buildx version.
|
||||
2. Run `BUILDX_EXPERIMENTAL=1 docker buildx dap` to check that the `dap` subcommand is available in your Buildx installation.
|
||||
3. Search for "docker enable build debugging" in the VS Code settings (<kbd>Ctrl+,</kbd> or <kbd>Command+,</kbd>) and enable the experimental "Enable Build Debugging" setting.
|
||||
4. Restart VS Code for the setting to take effect.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
### Debugging without a Launch Configuration
|
||||
|
||||
The Docker DX extension will fill in a debug configuration on a best effort basis. If you do not have a `launch.json` file or if it does not define any launch configurations, you can start debugging by simply opening a Dockerfile and then clicking on the "Run and Debug" button in the "Run and Debug" side panel.
|
||||
|
||||

|
||||
|
||||
### Debugging with a Launch Configuration
|
||||
|
||||
For more complicated build configurations, you can use the `launch.json` to define launch configurations for the buildx debugger.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```jsonc
|
||||
{
|
||||
"type": "dockerfile", // required, must not be modified
|
||||
"request": "launch", // required, must not be modified
|
||||
"name": "Docker: Build", // required, configurable
|
||||
"dockerfile": "Dockerfile", // required, configurable
|
||||
"contextPath": "${workspaceFolder}",
|
||||
"target": "test", // optional, should be a build stage in the Dockerfile
|
||||
"args": [
|
||||
// additional arguments for the build command
|
||||
"--build-arg",
|
||||
"NODE_ENV=development"
|
||||
],
|
||||
"stopOnEntry": true, // if the debugger should suspend on the first line, defaults to false
|
||||
}
|
||||
```
|
||||
|
||||
### Setting Breakpoints
|
||||
|
||||
The build debugger integration supports setting line breakpoints on an instruction. Visual Studio Code offers various ways for setting a breakpoint which you can read more about [here](https://code.visualstudio.com/docs/debugtest/debugging#_breakpoints).
|
||||
|
||||

|
||||
|
||||
### Opening a Shell Inside the Image Being Built
|
||||
|
||||
> ⚠️ Note that this feature is still being fine tuned.
|
||||
|
||||
When crafting a Dockerfile in the beginning, it is common to make changes and rerun the build again and again. With the shell exec feature, you can quickly open a shell for the image you are building and test commands there before copying them back into your Dockerfile.
|
||||
|
||||
1. Set a breakpoint in the build.
|
||||
2. When the build process has been suspended, open the Debug Console.
|
||||
3. Type in `exec` and press <kbd>Enter</kbd>.
|
||||
4. A new terminal with a shell inside the paused build image will be opened.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Inspecting Variables
|
||||
|
||||
The Variables pane in Visual Studio Code lets you view the value of `ARG` and `ENV` variables. The pane can help clarify what a value is if variable substitutions are involved.
|
||||
|
||||

|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter errors or issues with this feature, the DAP logs may help. Open the Output panel and select "Docker Buildx DAP" from the drop down.
|
||||
|
||||

|
|
@ -0,0 +1,76 @@
|
|||
# FAQ
|
||||
|
||||
### Where can I get help if I cannot find the answer in this FAQ?
|
||||
|
||||
You can search our [list of issues](https://github.com/docker/vscode-extension/issues) or the [discussions page](https://github.com/docker/vscode-extension/discussions) to see if someone else has asked about something similar. If not, feel free to open a new issue or discussion. We look forward to hearing from you!
|
||||
|
||||
### Why is this extension on my system? I do not remember installing it.
|
||||
|
||||
Please refer to [this blog post](https://www.docker.com/blog/docker-dx-extension-for-vs-code-update/) and/or [docker/vscode-extension#103](https://github.com/docker/vscode-extension/issues/103).
|
||||
|
||||
### Where I can learn more about the telemetry that the Docker DX extension collects?
|
||||
|
||||
For information regarding telemetry, please refer to [TELEMETRY.md](./TELEMETRY.md).
|
||||
|
||||
### Where can I find the language server logs?
|
||||
|
||||
The language server logs can be enabled by modifying your settings. After turning them on, you can look for "Docker Language Server" and/or "Docker Language Server" in the Output view.
|
||||
|
||||
```JSONC
|
||||
{
|
||||
// Docker Language Server (https://github.com/docker/docker-language-server)
|
||||
"dockerLanguageClient.trace.server": "verbose",
|
||||
// Dockerfile Language Server (https://github.com/rcjsuen/dockerfile-language-server)
|
||||
"dockerfile-language-server.trace.server": "verbose"
|
||||
}
|
||||
```
|
||||
|
||||
### How can I disable warnings related to vulnerabilities in images?
|
||||
|
||||
To disable everything, you can set the `docker.lsp.experimental.vulnerabilityScanning` setting to `false`.
|
||||
|
||||
If you would like to disable specific warnings about vulnerabilities, you can opt in or out of them individually as well.
|
||||
|
||||
- `docker.lsp.experimental.scout.criticalHighVulnerabilities`
|
||||
- `docker.lsp.experimental.scout.notPinnedDigest`
|
||||
- `docker.lsp.experimental.scout.recommendedTag`
|
||||
- `docker.lsp.experimental.scout.vulnerabilities`
|
||||
|
||||
### I am seeing duplicated editor features (such as code completion suggestions, hover tooltips, etc.) in Compose files.
|
||||
|
||||
Do you have any of the following extensions installed?
|
||||
|
||||
- [Red Hat's YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
|
||||
- [Microsoft's Container Tools extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers)
|
||||
- [Microsoft's Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)
|
||||
|
||||
If yes, you can refer to the steps below to remove the duplicates. Alternatively, if you would prefer to disable the Compose editing features that _this_ extension is providing, you can set the `docker.extension.enableComposeLanguageServer` setting to `false` and then restart Visual Studio Code.
|
||||
|
||||
- [Red Hat's YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) (powered by [redhat-developer/yaml-language-server](https://github.com/redhat-developer/yaml-language-server))
|
||||
1. To disable duplicates from this extension, open the [Command Palette](https://code.visualstudio.com/api/ux-guidelines/command-palette) in Visual Studio Code and open "Preferences: Open User Settings (JSON)".
|
||||
2. Set `docker.extension.enableComposeLanguageServer` to `true` by following the snippet below.
|
||||
3. Create an object attribute for `yaml.schemas` if it does not already exist.
|
||||
4. Inside the `yaml.schemas` object, copy the URL to [this empty JSON file](https://raw.githubusercontent.com/docker/vscode-extension/6a88caada42b57090df7ce91ec2a6561b422afe1/misc/empty.json) to Compose YAML files by following the snippet below.
|
||||
5. YAML files named `compose*y*ml` or `docker-compose*y*ml` will now no longer have the Compose schema associated with them in Red Hat's extension so Red Hat's extension will stop providing YAML features for Compose files. This admittedly is a strange way to disable YAML features for a given file but it is the only known workaround for resolving this until [redhat-developer/vscode-yaml#245](https://github.com/redhat-developer/vscode-yaml/issues/245) is implemented.
|
||||
|
||||
```JSONC
|
||||
{
|
||||
// this must be explicitly set to true in your settings.json file or
|
||||
// the auto-deduplication logic will programmatically set the value to
|
||||
// false if it detects that Red Hat's YAML extension is installed
|
||||
"docker.extension.enableComposeLanguageServer": true,
|
||||
"yaml.schemas": {
|
||||
// this tells Red Hat's YAML extension to consider Compose YAML
|
||||
// files as not having a schema so it will stop suggesting code
|
||||
// completion items, hover tooltips, and so on
|
||||
"https://raw.githubusercontent.com/docker/vscode-extension/6a88caada42b57090df7ce91ec2a6561b422afe1/misc/empty.json": ["compose*y*ml", "docker-compose*y*ml"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [Microsoft's Container Tools extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers) (powered by [microsoft/compose-language-service](https://github.com/microsoft/compose-language-service))
|
||||
- If [microsoft/vscode-containers#75](https://github.com/microsoft/vscode-containers/pull/75) is merged and you are on a release with this change, then the duplicates should already be taken of.
|
||||
- If not, you can you can set the `containers.enableComposeLanguageService` setting to `false` and restart Visual Studio Code.
|
||||
- [Microsoft's Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) (powered by [microsoft/compose-language-service](https://github.com/microsoft/compose-language-service))
|
||||
- If you have version 1.x installed, you can set the `docker.enableDockerComposeLanguageService` setting to `false` and restart Visual Studio Code.
|
||||
- If you have version 2.x installed, then you can refer to the steps above for Microsoft's Container Tools extension instead.
|
|
@ -0,0 +1,414 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>NOTICES AND INFORMATION</title>
|
||||
<style>
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
background: #eee;
|
||||
padding: 24px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NOTICES AND INFORMATION</h1>
|
||||
<p><strong>Do Not Translate or Localize</strong></p>
|
||||
<p>This software incorporates material from third parties.</p>
|
||||
<p>
|
||||
Notwithstanding any other terms, you may reverse engineer this software to
|
||||
the extent required to debug changes to any libraries licensed under the
|
||||
GNU Lesser General Public License.
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
<details>
|
||||
<summary>HashiCorp HCL - MPL-2.0</summary>
|
||||
<p>
|
||||
<a href="https://www.hashicorp.com/">https://www.hashicorp.com/</a>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Copyright (c) 2020 HashiCorp, Inc.</li>
|
||||
</ul>
|
||||
<pre>
|
||||
Copyright (c) 2020 HashiCorp, Inc.
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
</pre
|
||||
>
|
||||
</details>
|
||||
</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
73
README.md
|
@ -2,33 +2,25 @@
|
|||
|
||||
The **Docker DX (Developer Experience)** Visual Studio Code extension enhances your Visual Studio Code experience with Docker-related development by adding rich editing features and vulnerability scanning.
|
||||
|
||||
## Note ⚠️
|
||||
|
||||
> The Docker DX Visual Studio Code extension is in Beta. It is being gradually rolled out. If the extension's features are not visible, it's likely because the rollout hasn’t reached your profile yet.
|
||||
>
|
||||
> - To enable the extension's features manually, set `docker.extension.experimental.release.march2025` to `enabled` and restart VS Code.
|
||||
> - To turn them off, set the same setting to `disabled` and restart VS Code.
|
||||
>
|
||||
> Encountering a bug? [Let us know](https://github.com/docker/vscode-extension/issues) so we can take a look.
|
||||
|
||||
## Key features
|
||||
|
||||
- [Dockerfile linting](https://docs.docker.com/reference/build-checks/): Get build warnings and best-practice suggestions via BuildKit and BuildX.
|
||||
- [Bake](https://docs.docker.com/build/bake/) file support: Includes code completion, variable navigation, and inline suggestions for generating targets based on your Dockerfile stages.
|
||||
- [Compose file](https://docs.docker.com/reference/compose-file/) outline: Easily navigate complex Compose files with an outline view in the editor.
|
||||
- [Compose editing features](https://docs.docker.com/compose/): Provides contextual code completion, reference navigation, and schema descriptions in hovers.
|
||||
- [Bake editing features](https://docs.docker.com/build/bake/): Includes code completion, variable navigation, and inline suggestions for generating targets based on your Dockerfile stages.
|
||||
- Image vulnerability scanning (experimental): Flags references to container images with known vulnerabilities directly within Dockerfiles.
|
||||
|
||||
## Requirements
|
||||
|
||||
The extension requires Docker Engine to be running. [Install Docker Desktop](https://www.docker.com/get-started/) on your machine and make sure the `docker` CLI is available in your system `PATH`.
|
||||
|
||||
Docker currently supports the following operating systems and architectures:
|
||||
This extension currently supports the following operating systems and architectures:
|
||||
|
||||
| Operating system | Architectures |
|
||||
| ---------------- | ---------------- |
|
||||
| Windows | `amd64`, `arm64` |
|
||||
| macOS | `amd64`, `arm64` |
|
||||
| Linux | `amd64`, `arm64` |
|
||||
| Alpine | `amd64`, `arm64` |
|
||||
|
||||
If you are on an unsupported system, let us know of your interest in this extension so we can prioritize the work accordingly.
|
||||
|
||||
|
@ -38,12 +30,22 @@ If you are on an unsupported system, let us know of your interest in this extens
|
|||
|
||||
You can get linting checks from [BuildKit](https://github.com/moby/buildkit) and [BuildX](https://github.com/docker/buildx) when editing your Dockerfiles.
|
||||
|
||||
Any references to images with vulnerabilities are also flagged. Note: This is an experimental feature.
|
||||
Any references to images with vulnerabilities are also flagged. This is an **experimental** feature and may change in the future. Refer to our [FAQ.md](./FAQ.md) to see how you can opt in or out of these warnings.
|
||||
|
||||
Errors are visible directly in your editor or you can look at them by opening up the Problems panel (<kbd>Ctrl+Shift+M</kbd> on Windows/Linux, <kbd>Shift+Command+M</kbd> on Mac).
|
||||
|
||||

|
||||
|
||||
### Editing Compose files
|
||||
|
||||
Code completion support in the Docker DX extension goes beyond just the Compose schema. The Docker DX extension understands the contextual link between your Compose file and your Dockerfile.
|
||||
|
||||

|
||||
|
||||
Compose files can get pretty big and complicated when you start including other files. Docker DX lets you hover over a reference to quickly see how something is defined.
|
||||
|
||||

|
||||
|
||||
### Editing Bake files
|
||||
|
||||
You can get code completion when editing your `docker-bake.hcl` file. You are also able to hover over variables and navigate around the file by jumping to a variable's definition or jumping to the build stage within a Dockerfile.
|
||||
|
@ -54,26 +56,26 @@ The extension provides inline suggestions to generate a Bake target to correspon
|
|||
|
||||

|
||||
|
||||
### Editing Compose files
|
||||
### Build Debugging (EXPERIMENTAL)
|
||||
|
||||
You can view an outline of your Compose file which makes it easier to navigate.
|
||||
This feature is under active development and requires version `v0.26.1` of `docker buildx` or newer. This is disabled by default. Open [DEBUGGING.md](./DEBUGGING.md) to learn more about this feature in Visual Studio Code and how to enable it.
|
||||
|
||||

|
||||
For information about Buildx and the Debug Adapter Protocol, go [here](https://github.com/docker/buildx/blob/master/docs/dap.md). If you have any bugs, feature requests, or feedback about Buildx's support for Debug Adapter Protocol, please report them [here](https://github.com/docker/buildx/issues/new/choose).
|
||||
|
||||
## Builds
|
||||
|
||||
[GitHub Actions](https://github.com/docker/vscode-extension/actions) builds six `.vsix` files - one for each platform combination(Windows, macOS, Linux x `amd64`/`arm64`).
|
||||
[GitHub Actions](https://github.com/docker/vscode-extension/actions) builds eight `.vsix` files - one for each platform combination (Windows, macOS, Linux, Alpine Linux x `amd64`/`arm64`).
|
||||
|
||||
Note: The language server binary from these builds are not signed and/or notarized. You may encounter issues when using `.vsix` files from this repository as your operating system may refuse to open an unsigned binary.
|
||||
|
||||
## Development
|
||||
|
||||
To debug the VS Code extension:
|
||||
To develop this extension, you should first make sure you have the following extensions installed:
|
||||
|
||||
1. Clone this repository.
|
||||
2. Open the folder in VS Code.
|
||||
3. Create a `bin` folder at the root.
|
||||
4. Download the [Docker Language Server binary](https://github.com/docker/docker-language-server) and place it in `bin/` Alternatively, follow the instructions in that repository and build a binary yourself to place in the `bin` folder.
|
||||
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
- [TypeScript + Webpack Problem Matchers](https://marketplace.visualstudio.com/items?itemName=amodio.tsl-problem-matcher)
|
||||
|
||||
To debug the VS Code extension, clone this repository and then run `npm install`. This will download a binary of the [Docker Language Server](https://github.com/docker/docker-language-server/releases) to the `bin` folder. If you would like to test your own custom build of the language server, simply replace the file in the `bin` folder with your own binary.
|
||||
|
||||
### Debugging both the extension and language server
|
||||
|
||||
|
@ -82,6 +84,33 @@ To debug the VS Code extension:
|
|||
3. In VS Code, update the `docker.lsp.debugServerPort` setting to `49201`. This is the default port that is used for any launch configurations saved in Git.
|
||||
4. Launch the extension in debug mode. It will connect to the language server you started in debug mode instead of trying to execute a binary in `bin/`.
|
||||
|
||||
### Testing
|
||||
|
||||
Run `npm test` to launch the UI tests.
|
||||
|
||||
### Releasing
|
||||
|
||||
Follow the following steps to create a new release of the Docker DX Visual Studio Code extension:
|
||||
|
||||
1. Run the "[prepare release](https://github.com/docker/vscode-extension/actions/workflows/prepare-release.yml)" workflow with the desired bump in semantic versioning. This workflow will update `CHANGELOG.md`, `package.json`, and `package-lock.json` and create a pull request with the three files.
|
||||
2. Review the generated [pull request](https://github.com/docker/vscode-extension/pulls).
|
||||
1. The pull request's description will describe the changes to the three files. Verify that the changes make sense.
|
||||
2. If the changes look good and the builds and checks have completed and passed, approve the pull request and merge it manually.
|
||||
3. Now that the pull request has been merged into the `main` branch, a build named "Build: Automatic" will be triggered. Wait for the automated build from the "[build](https://github.com/docker/vscode-extension/actions/workflows/build.yml)" workflow to complete.
|
||||
4. If the build has completed successfully, use the "Run workflow" button to manually trigger the "[build](https://github.com/docker/vscode-extension/actions/workflows/build.yml)" workflow.
|
||||
5. This manually triggered workflow will start a "Build: Release" which will run the tests, create the release, build the binaries, and attach the binaries to the release.
|
||||
6. When the workflow has completed, open the [releases](https://github.com/docker/vscode-extension/releases) page. It should have been automatically generated by the workflow and the resulting VSIX files should be attached to the release.
|
||||
|
||||
## Telemetry
|
||||
|
||||
The Docker DX extension collects telemetry. We collect this telemetry so that we can improve the extension by understanding usage patterns and catching crashes and errors for diagnostic purposes. Note that if you have already opted out of sending telemetry in Visual Studio Code then no telemetry will be sent.
|
||||
|
||||
See [TELEMETRY.md](./TELEMETRY.md) for details about what kind of telemetry we collect and how to configure your telemetry settings.
|
||||
|
||||
## FAQ
|
||||
|
||||
Please refer to [FAQ.md](./FAQ.md) for our list of frequently asked questions.
|
||||
|
||||
## License
|
||||
|
||||
[Apache License Version 2.0](./LICENSE)
|
||||
|
|
11
TELEMETRY.md
|
@ -22,9 +22,20 @@ If you have already opted out of sending telemetry in Visual Studio Code then no
|
|||
- version of the installed extension
|
||||
- Docker version
|
||||
- function names and parameters for diagnosing errors and crashes
|
||||
- error messages when the language server is unable to start or is crashing
|
||||
- if certain extensions are also installed
|
||||
- [Microsoft's Container Tools extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers)
|
||||
- [Microsoft's Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)
|
||||
- [Red Hat's YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)
|
||||
- values of certain settings from this extension
|
||||
- `docker.extension.enableComposeLanguageServer`
|
||||
|
||||
The list above does _not_ include any telemetry collected by the [Docker Language Server](https://github.com/docker/docker-language-server). For telemetry collected by the Docker Language Server, please refer to the telemetry documentation of that project.
|
||||
|
||||
## BugSnag
|
||||
|
||||
This extension integrates with BugSnag and sends errors and stack traces to BugSnag if telemetry is configured.
|
||||
|
||||
## Privacy Policy
|
||||
|
||||
Read our [privacy policy](https://www.docker.com/legal/docker-privacy-policy/) to learn more about how the information is collected and used.
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
import * as fs from 'fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import axios from 'axios';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
async function fileFromUrl(url) {
|
||||
const response = await axios.get(url, { responseType: 'arraybuffer' });
|
||||
return Buffer.from(response.data, 'binary');
|
||||
}
|
||||
|
||||
async function downloadFile(url, dest) {
|
||||
console.info(`Downloading ${url}...`);
|
||||
console.info(`Saving to ${dest}...`);
|
||||
try {
|
||||
const buffer = await fileFromUrl(url);
|
||||
fs.writeFileSync(dest, buffer);
|
||||
} catch (error) {
|
||||
console.error(`Error downloading file: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function run(directory, url, file) {
|
||||
const cwd = path.resolve(__dirname);
|
||||
const buildDir = path.basename(cwd);
|
||||
const repoDir = cwd.replace(buildDir, '');
|
||||
const installPath = path.join(repoDir, directory);
|
||||
|
||||
if (fs.existsSync(installPath)) {
|
||||
if (process.env.downloader_log === 'true') {
|
||||
console.info(`Target folder path exists at ${installPath}. Removing`);
|
||||
}
|
||||
fs.rmSync(installPath, { recursive: true });
|
||||
}
|
||||
|
||||
fs.mkdirSync(installPath);
|
||||
|
||||
await downloadFile(url, path.join(installPath, file));
|
||||
}
|
||||
|
||||
async function downloadSyntaxesFile() {
|
||||
const hclSyntaxFile = `hcl.tmGrammar.json`;
|
||||
const url = `https://github.com/hashicorp/syntax/releases/download/v0.7.1/${hclSyntaxFile}`;
|
||||
run('syntaxes', url, hclSyntaxFile);
|
||||
}
|
||||
|
||||
function getPlatform() {
|
||||
const platform =
|
||||
process.env['NODE_OS'] === undefined
|
||||
? process.platform
|
||||
: process.env['NODE_OS'];
|
||||
if (platform === 'win32') {
|
||||
return 'windows';
|
||||
}
|
||||
return platform === 'alpine' ? 'linux' : platform;
|
||||
}
|
||||
|
||||
function getArch() {
|
||||
const arch =
|
||||
process.env['NODE_ARCH'] === undefined
|
||||
? process.arch
|
||||
: process.env['NODE_ARCH'];
|
||||
return arch === 'x64' ? 'amd64' : 'arm64';
|
||||
}
|
||||
|
||||
async function downloadLanguageServerBinary() {
|
||||
if (process.arch !== 'x64' && process.arch !== 'arm64') {
|
||||
console.error(
|
||||
`No language server binary can be found for the ${process.arch} architecture.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const platform = getPlatform();
|
||||
const arch = getArch();
|
||||
const suffix = platform === 'windows' ? '.exe' : '';
|
||||
const version = '0.17.0';
|
||||
const binaryFile = `docker-language-server-${platform}-${arch}-v${version}${suffix}`;
|
||||
const targetFile = `docker-language-server-${platform}-${arch}${suffix}`;
|
||||
const url = `https://github.com/docker/docker-language-server/releases/download/v${version}/${binaryFile}`;
|
||||
await run('bin', url, targetFile);
|
||||
fs.chmodSync(`bin/${targetFile}`, 0o755);
|
||||
}
|
||||
|
||||
downloadSyntaxesFile();
|
||||
downloadLanguageServerBinary();
|
|
@ -0,0 +1,170 @@
|
|||
import * as fs from 'fs';
|
||||
import * as readline from 'readline';
|
||||
|
||||
const changelogPath = 'CHANGELOG.md';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length < 1) {
|
||||
console.error(
|
||||
`Usage: node releaser.mjs <update-changelog|generate-release-notes> [args...]`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const command = args[0].toLowerCase();
|
||||
|
||||
if (command === 'update-changelog') {
|
||||
if (args.length < 2) {
|
||||
console.error(`Usage: node releaser.js update-changelog <version>`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const version = args[1];
|
||||
if (!/^\d+\.\d+\.\d+$/.test(version)) {
|
||||
console.error(`Error: version must be in format x.y.z (e.g., 1.2.3)`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
updateChangelog(changelogPath, changelogPath, version)
|
||||
.then(() =>
|
||||
console.log(`Successfully updated CHANGELOG.md with version ${version}`),
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(`Error: ${err.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
} else if (command === 'generate-release-notes') {
|
||||
generateReleaseNotes(changelogPath)
|
||||
.then((content) => console.log(content))
|
||||
.catch((err) => {
|
||||
console.error(`Error: ${err.message}`);
|
||||
process.exit(1);
|
||||
});
|
||||
} else {
|
||||
console.error(
|
||||
`Error: unknown command '${command}'. Use 'update-changelog' or 'generate-release-notes'`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function readFileLines(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const lines = [];
|
||||
const rl = readline.createInterface({
|
||||
input: fs.createReadStream(filePath),
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
rl.on('line', (line) => lines.push(line));
|
||||
rl.on('close', () => resolve(lines));
|
||||
rl.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateChangelog(inputPath, outputPath, newVersion) {
|
||||
const lines = await readFileLines(inputPath);
|
||||
|
||||
let unreleasedIndex = -1;
|
||||
let nextVersionIndex = -1;
|
||||
let linksStartIndex = -1;
|
||||
let previousVersion = '';
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
if (line.includes('## [Unreleased]')) {
|
||||
unreleasedIndex = i;
|
||||
} else if (
|
||||
nextVersionIndex === -1 &&
|
||||
unreleasedIndex !== -1 &&
|
||||
line.startsWith('## [') &&
|
||||
!line.includes('Unreleased')
|
||||
) {
|
||||
nextVersionIndex = i;
|
||||
const match = line.match(/^## \[([0-9]+\.[0-9]+\.[0-9]+)\]/);
|
||||
if (match) {
|
||||
previousVersion = match[1];
|
||||
}
|
||||
} else if (
|
||||
linksStartIndex === -1 &&
|
||||
line.startsWith('[') &&
|
||||
line.includes(']: https://github.com/')
|
||||
) {
|
||||
linksStartIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unreleasedIndex === -1) {
|
||||
throw new Error("could not find 'Unreleased' section in changelog");
|
||||
}
|
||||
if (nextVersionIndex === -1 || !previousVersion) {
|
||||
throw new Error(
|
||||
"could not find previous version section after 'Unreleased'",
|
||||
);
|
||||
}
|
||||
if (linksStartIndex === -1) {
|
||||
throw new Error('could not find links section in changelog');
|
||||
}
|
||||
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
|
||||
lines[unreleasedIndex] = `## [${newVersion}] - ${today}`;
|
||||
|
||||
const updatedLinks = updateLinks(
|
||||
lines.slice(linksStartIndex),
|
||||
newVersion,
|
||||
previousVersion,
|
||||
);
|
||||
const updatedContent = lines.slice(0, linksStartIndex).concat(updatedLinks);
|
||||
|
||||
await fs.promises.writeFile(outputPath, updatedContent.join('\n') + '\n');
|
||||
}
|
||||
|
||||
function updateLinks(linkLines, newVersion, previousVersion) {
|
||||
// first link unreleased, second link with the new tag
|
||||
const newLinks = [
|
||||
`[Unreleased]: https://github.com/docker/docker-language-server/compare/v${newVersion}...main`,
|
||||
`[${newVersion}]: https://github.com/docker/docker-language-server/compare/v${previousVersion}...v${newVersion}`,
|
||||
];
|
||||
|
||||
// all other links can be from the original, after skipping the first one
|
||||
for (let i = 1; i < linkLines.length; i++) {
|
||||
newLinks.push(linkLines[i]);
|
||||
}
|
||||
|
||||
return newLinks;
|
||||
}
|
||||
|
||||
async function generateReleaseNotes(filePath) {
|
||||
const lines = await readFileLines(filePath);
|
||||
|
||||
let firstHeader = -1,
|
||||
secondHeader = -1;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('## ')) {
|
||||
if (firstHeader === -1) {
|
||||
firstHeader = i;
|
||||
} else if (secondHeader === -1) {
|
||||
secondHeader = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (secondHeader === -1) {
|
||||
throw new Error('could not find two ## headers in the changelog');
|
||||
}
|
||||
|
||||
// remove leading and trailing empty newlines
|
||||
const content = lines.slice(firstHeader + 1, secondHeader);
|
||||
while (content.length > 0 && content[0].trim() === '') {
|
||||
content.shift();
|
||||
}
|
||||
while (content.length > 0 && content[content.length - 1].trim() === '') {
|
||||
content.pop();
|
||||
}
|
||||
|
||||
return content.join('\n');
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"comments": {
|
||||
"blockComment": ["/*", "*/"],
|
||||
"lineComment": {
|
||||
"comment": "//",
|
||||
"noIndent": false
|
||||
}
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
{ "open": "{", "close": "}" },
|
||||
{ "open": "[", "close": "]" },
|
||||
{ "open": "(", "close": ")" },
|
||||
{ "open": "\"", "close": "\"", "notIn": ["string"] },
|
||||
{ "open": "/*", "close": " */", "notIn": ["string"] }
|
||||
],
|
||||
"surroundingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""]
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{}
|
199
package.json
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"name": "docker",
|
||||
"displayName": "Docker DX",
|
||||
"description": "",
|
||||
"version": "0.2.0",
|
||||
"icon": "resources/docker-logo-vertical-blue.png",
|
||||
"description": "Edit smarter, ship faster with an enhanced Docker-development experience",
|
||||
"version": "0.15.0",
|
||||
"icon": "resources/logo-256x256.png",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"vscode": "^1.92.0"
|
||||
|
@ -11,17 +11,16 @@
|
|||
"publisher": "docker",
|
||||
"categories": [
|
||||
"Programming Languages",
|
||||
"Linters"
|
||||
"Linters",
|
||||
"Debuggers"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/docker/vscode-extension"
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"ms-azuretools.vscode-docker"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:dockerbake",
|
||||
"onDebugResolve:dockerfile",
|
||||
"onDebugDynamicConfigurations:dockerfile",
|
||||
"onLanguage:dockercompose",
|
||||
"onLanguage:dockerfile"
|
||||
],
|
||||
|
@ -36,7 +35,11 @@
|
|||
{
|
||||
"title": "Scan for CVEs with Docker Scout",
|
||||
"command": "docker.scout.imageScan",
|
||||
"enablement": "view == dockerImages && viewItem == image"
|
||||
"enablement": "(view == dockerImages || view == vscode-containers.views.images) && viewItem == image"
|
||||
},
|
||||
{
|
||||
"title": "Build with Debugger",
|
||||
"command": "docker.debug.editorContents"
|
||||
}
|
||||
],
|
||||
"languages": [
|
||||
|
@ -45,36 +48,128 @@
|
|||
"filenames": [
|
||||
"docker-bake.hcl",
|
||||
"docker-bake.override.hcl"
|
||||
]
|
||||
],
|
||||
"configuration": "./configs/dockerbake-language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "dockerbake",
|
||||
"scopeName": "source.hcl",
|
||||
"path": "./syntaxes/hcl.tmGrammar.json"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"view/item/context": [
|
||||
{
|
||||
"command": "docker.scout.imageScan",
|
||||
"when": "view == dockerImages && viewItem == image",
|
||||
"when": "(view == dockerImages || view == vscode-containers.views.images) && viewItem == image",
|
||||
"group": "images_group_dockerdx"
|
||||
}
|
||||
]
|
||||
},
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "dockerfile"
|
||||
}
|
||||
],
|
||||
"debuggers": [
|
||||
{
|
||||
"type": "dockerfile",
|
||||
"languages": [
|
||||
"dockerfile"
|
||||
],
|
||||
"label": "Docker: Build",
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"required": [
|
||||
"contextPath"
|
||||
],
|
||||
"properties": {
|
||||
"dockerfile": {
|
||||
"type": "string",
|
||||
"description": "Relative path from the context to the dockerfile.",
|
||||
"default": "Dockerfile"
|
||||
},
|
||||
"contextPath": {
|
||||
"type": "string",
|
||||
"description": "Path to the context.",
|
||||
"default": "${workspaceFolder}"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"description": "Target build stage to build."
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Stop the docker build on the first instruction.",
|
||||
"default": false
|
||||
},
|
||||
"builder": {
|
||||
"type": "string",
|
||||
"description": "Builder to use."
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "Arguments to pass to the build."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"type": "dockerfile",
|
||||
"request": "launch",
|
||||
"name": "Docker: Build",
|
||||
"dockerfile": "Dockerfile",
|
||||
"contextPath": "${workspaceFolder}"
|
||||
}
|
||||
],
|
||||
"configurationSnippets": [
|
||||
{
|
||||
"label": "Docker: Build",
|
||||
"description": "A new configuration for debugging a user selected Dockerfile.",
|
||||
"body": {
|
||||
"type": "dockerfile",
|
||||
"request": "launch",
|
||||
"name": "Docker: Build",
|
||||
"dockerfile": "${2:Dockerfile}",
|
||||
"contextPath": "^\"\\${workspaceFolder}\""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "Docker",
|
||||
"title": "Docker DX",
|
||||
"properties": {
|
||||
"docker.extension.enableBuildDebugging": {
|
||||
"type": "boolean",
|
||||
"description": "Enables build debugging features from the Docker DX extension. This feature is under active development. Note that changing this value requires a restart of Visual Studio Code to take effect.",
|
||||
"markdownDescription": "Enable build debugging features from the Docker DX extension. This feature is under active development. Note that changing this value requires a **restart** of Visual Studio Code to take effect.",
|
||||
"default": false,
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
},
|
||||
"docker.extension.enableComposeLanguageServer": {
|
||||
"type": "boolean",
|
||||
"description": "Enable Compose editing features from the Docker DX extension. Note that changing this value requires a restart of Visual Studio Code to take effect.",
|
||||
"markdownDescription": "Enable Compose editing features from the Docker DX extension. Note that changing this value requires a **restart** of Visual Studio Code to take effect.\n\nIf you have [Red Hat's YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml), note that both Docker DX and Red Hat's YAML extension are handling Compose files. This creates duplicate completions, hovers, and syntax errors.\n\nYou can follow the steps [here](https://github.com/docker/vscode-extension/blob/main/FAQ.md) to update your `settings.json` to turn off Compose support in the YAML extension and streamline your experience.",
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
},
|
||||
"docker.extension.dockerEngineAvailabilityPrompt": {
|
||||
"type": "boolean",
|
||||
"description": "Be notified when Docker Engine is not available.",
|
||||
"default": true
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
},
|
||||
"docker.extension.experimental.release.march2025": {
|
||||
"scope": "application",
|
||||
"type": "string",
|
||||
"description": "Enable feature manually. Enables the Docker VS Code extension regardless of the current rollout status.",
|
||||
"enum": [
|
||||
"enabled",
|
||||
"featureFlag",
|
||||
"disabled"
|
||||
],
|
||||
"default": "featureFlag"
|
||||
"docker.extension.editor.dockerfileBuildStageDecorationLines": {
|
||||
"type": "boolean",
|
||||
"description": "Render a divider line between each build stage of a Dockerfile.",
|
||||
"default": true,
|
||||
"scope": "resource"
|
||||
},
|
||||
"docker.lsp.telemetry": {
|
||||
"type": "string",
|
||||
|
@ -84,7 +179,11 @@
|
|||
"error",
|
||||
"off"
|
||||
],
|
||||
"default": "all"
|
||||
"default": "all",
|
||||
"tags": [
|
||||
"telemetry",
|
||||
"usesOnlineServices"
|
||||
]
|
||||
},
|
||||
"docker.lsp.debugServerPort": {
|
||||
"type": [
|
||||
|
@ -98,42 +197,86 @@
|
|||
"docker.lsp.experimental.vulnerabilityScanning": {
|
||||
"type": "boolean",
|
||||
"description": "Enable image analysis of Dockerfiles (Experimental)",
|
||||
"default": true
|
||||
"default": true,
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
},
|
||||
"docker.lsp.experimental.scout.criticalHighVulnerabilities": {
|
||||
"markdownDescription": "Determines if `critical_high_vulnerabilities` diagnostics should be shown. If `docker.lsp.experimental.vulnerabilityScanning` is false then this setting will be ignored.",
|
||||
"default": true,
|
||||
"type": "boolean",
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
},
|
||||
"docker.lsp.experimental.scout.notPinnedDigest": {
|
||||
"markdownDescription": "Determines if `not_pinned_digest` diagnostics should be shown. If `docker.lsp.experimental.vulnerabilityScanning` is false then this setting will be ignored.",
|
||||
"default": false,
|
||||
"type": "boolean",
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
},
|
||||
"docker.lsp.experimental.scout.recommendedTag": {
|
||||
"markdownDescription": "Determines if `recommended_tag` diagnostics should be shown. If `docker.lsp.experimental.vulnerabilityScanning` is false then this setting will be ignored.",
|
||||
"default": false,
|
||||
"type": "boolean",
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
},
|
||||
"docker.lsp.experimental.scout.vulnerabilities": {
|
||||
"markdownDescription": "Determines if `vulnerabilities` diagnostics should be shown. If `docker.lsp.experimental.vulnerabilityScanning` is false then this setting will be ignored.",
|
||||
"default": true,
|
||||
"type": "boolean",
|
||||
"tags": [
|
||||
"experimental"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "npm run download:artifacts",
|
||||
"vscode:prepublish": "npm run package",
|
||||
"compile": "webpack",
|
||||
"watch": "webpack --watch",
|
||||
"package": "webpack --mode production --devtool hidden-source-map",
|
||||
"download:artifacts": "node build/downloader.mjs",
|
||||
"compile-tests": "tsc -p . --outDir out",
|
||||
"watch-tests": "tsc -p . -w --outDir out",
|
||||
"pretest": "npm run compile-tests && npm run compile && npm run lint",
|
||||
"lint": "eslint src --ext ts",
|
||||
"test": "vscode-test",
|
||||
"test": "extest setup-and-run './out/ui-test/*.test.js' --code_version max --code_settings test/settings.json --extensions_dir .test-extensions",
|
||||
"make-vsix": "vsce package",
|
||||
"prettier:check": "prettier --check --config .prettierrc.yml --ignore-path .prettierignore .",
|
||||
"prettier:fix": "prettier --write --config .prettierrc.yml --ignore-path .prettierignore ."
|
||||
},
|
||||
"dependencies": {
|
||||
"unleash-proxy-client": "3.7.3",
|
||||
"@bugsnag/js": "~8.2.0",
|
||||
"dockerfile-ast": "0.7.1",
|
||||
"dockerfile-language-server-nodejs": "0.14.1",
|
||||
"vscode-languageclient": "9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.16",
|
||||
"@types/mocha": "^10.0.7",
|
||||
"@types/node": "20.x",
|
||||
"@types/vscode": "^1.8.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.11.0",
|
||||
"@vscode/vsce": "^3.3.0",
|
||||
"@vscode/test-cli": "^0.0.9",
|
||||
"@vscode/test-electron": "^2.4.0",
|
||||
"@vscode/vsce": "^3.3.0",
|
||||
"axios": "^1.8.4",
|
||||
"chai": "^4.5.0",
|
||||
"eslint": "^8.57.0",
|
||||
"prettier": "^3.5.3",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.5",
|
||||
"umd-compat-loader": "^2.1.2",
|
||||
"vscode-extension-tester": "^8.17.0",
|
||||
"webpack": "^5.92.1",
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 244 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 141 KiB |
|
@ -0,0 +1,182 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { registerCommand } from '../extension';
|
||||
import { getExtensionSetting } from '../utils/settings';
|
||||
|
||||
export const DebugEditorContentsCommandId = 'docker.debug.editorContents';
|
||||
|
||||
class DebugAdapterExecutableFactory
|
||||
implements vscode.DebugAdapterDescriptorFactory
|
||||
{
|
||||
createDebugAdapterDescriptor(
|
||||
session: vscode.DebugSession,
|
||||
): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
var args = ['buildx'];
|
||||
if (session.configuration?.builder) {
|
||||
args = args.concat(['--builder', session.configuration?.builder]);
|
||||
}
|
||||
args = args.concat(['dap', 'build']);
|
||||
if (session.configuration?.args) {
|
||||
args = args.concat(session.configuration?.args);
|
||||
}
|
||||
|
||||
const options = {
|
||||
cwd: session.workspaceFolder?.uri.fsPath,
|
||||
env: { BUILDX_EXPERIMENTAL: '1' },
|
||||
};
|
||||
|
||||
return new vscode.DebugAdapterExecutable('docker', args, options);
|
||||
}
|
||||
}
|
||||
|
||||
class DockerfileConfigurationProvider
|
||||
implements vscode.DebugConfigurationProvider
|
||||
{
|
||||
resolveDebugConfiguration(
|
||||
_folder: vscode.WorkspaceFolder | undefined,
|
||||
config: vscode.DebugConfiguration,
|
||||
): vscode.ProviderResult<vscode.DebugConfiguration> {
|
||||
// this can happen when debugging without anything in launch.json
|
||||
if (!config.type && !config.request && !config.name) {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor !== undefined && editor.document.languageId === 'dockerfile') {
|
||||
config.type = 'dockerfile';
|
||||
config.name = 'Docker: Build';
|
||||
config.request = 'launch';
|
||||
config.dockerfile = editor.document.uri.fsPath;
|
||||
config.contextPath = '${workspaceFolder}';
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
class DockerfileDebugAdapterTracker implements vscode.DebugAdapterTracker {
|
||||
constructor(
|
||||
private id: string,
|
||||
private name: string,
|
||||
private channel: vscode.OutputChannel,
|
||||
) {}
|
||||
|
||||
log(logLevel: string, message: any): void {
|
||||
message.id = this.id;
|
||||
message.name = this.name;
|
||||
this.channel.appendLine(
|
||||
`${new Date().toISOString()} [${logLevel}] ${JSON.stringify(message)}`,
|
||||
);
|
||||
}
|
||||
|
||||
onWillStartSession(): void {
|
||||
this.log('debug', { message: 'DAP session about to be started' });
|
||||
}
|
||||
|
||||
onWillStopSession(): void {
|
||||
this.log('debug', { message: 'DAP session about to be stopped' });
|
||||
}
|
||||
|
||||
onWillReceiveMessage(message: any): void {
|
||||
this.log('debug', {
|
||||
message: 'DAP message will be received from the editor',
|
||||
dapMessage: message,
|
||||
});
|
||||
}
|
||||
|
||||
onDidSendMessage(message: any): void {
|
||||
this.log('debug', {
|
||||
message: 'DAP message has been sent to the editor',
|
||||
dapMessage: message,
|
||||
});
|
||||
}
|
||||
|
||||
onExit(code: number | undefined, signal: string | undefined): void {
|
||||
const message = { message: 'DAP exited', code: code, signal: signal };
|
||||
if (code === 0) {
|
||||
this.log('debug', message);
|
||||
} else {
|
||||
this.log('error', message);
|
||||
}
|
||||
}
|
||||
|
||||
onError(error: Error): void {
|
||||
this.log('error', {
|
||||
message: 'DAP error occurred',
|
||||
dapMessage: { error: String(error) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function setupDebugging(ctx: vscode.ExtensionContext) {
|
||||
if (!getExtensionSetting<boolean>('enableBuildDebugging')) {
|
||||
// the command is still contributed to the Command Palette because of package.json
|
||||
registerCommand(ctx, DebugEditorContentsCommandId, async () => {
|
||||
vscode.window.showErrorMessage(
|
||||
'Build Debugging for Docker is an experimental feature that is under active development. ' +
|
||||
'Enable the feature by toggling the docker.extension.enableBuildDebugging setting to true and restarting your client.',
|
||||
);
|
||||
return Promise.resolve(false);
|
||||
});
|
||||
|
||||
// the debugger is still contributed and technically registered because of package.json
|
||||
ctx.subscriptions.push(
|
||||
vscode.debug.registerDebugConfigurationProvider('dockerfile', {
|
||||
resolveDebugConfiguration(): vscode.ProviderResult<vscode.DebugConfiguration> {
|
||||
vscode.window.showErrorMessage(
|
||||
'Build Debugging for Docker is an experimental feature that is under active development. ' +
|
||||
'Enable the feature by toggling the docker.extension.enableBuildDebugging setting to true and restarting your client.',
|
||||
);
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let channel = vscode.window.createOutputChannel('Docker Buildx DAP', 'log');
|
||||
|
||||
registerCommand(
|
||||
ctx,
|
||||
DebugEditorContentsCommandId,
|
||||
async (resource: vscode.Uri) => {
|
||||
let targetResource = resource;
|
||||
if (!targetResource && vscode.window.activeTextEditor) {
|
||||
targetResource = vscode.window.activeTextEditor.document.uri;
|
||||
}
|
||||
if (targetResource) {
|
||||
vscode.debug.startDebugging(undefined, {
|
||||
type: 'dockerfile',
|
||||
name: 'Docker: Build',
|
||||
request: 'launch',
|
||||
dockerfile: targetResource.fsPath,
|
||||
contextPath: '${workspaceFolder}',
|
||||
});
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
},
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(
|
||||
vscode.debug.registerDebugConfigurationProvider(
|
||||
'dockerfile',
|
||||
new DockerfileConfigurationProvider(),
|
||||
),
|
||||
);
|
||||
|
||||
ctx.subscriptions.push(
|
||||
vscode.debug.registerDebugAdapterDescriptorFactory(
|
||||
'dockerfile',
|
||||
new DebugAdapterExecutableFactory(),
|
||||
),
|
||||
);
|
||||
|
||||
vscode.debug.registerDebugAdapterTrackerFactory('dockerfile', {
|
||||
createDebugAdapterTracker(
|
||||
session,
|
||||
): vscode.ProviderResult<vscode.DebugAdapterTracker> {
|
||||
return new DockerfileDebugAdapterTracker(
|
||||
session.id,
|
||||
session.name,
|
||||
channel,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
418
src/extension.ts
|
@ -1,90 +1,97 @@
|
|||
import { spawn } from 'child_process';
|
||||
import { homedir } from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import Bugsnag, { Event, Session } from '@bugsnag/js';
|
||||
import {
|
||||
activateDockerNativeLanguageClient,
|
||||
getNativeClient,
|
||||
} from './utils/lsp/lsp';
|
||||
import { DidChangeConfigurationNotification } from 'vscode-languageclient/node';
|
||||
import { publishTelemetry, queueTelemetryEvent } from './telemetry/client';
|
||||
import {
|
||||
EVENT_CLIENT_HEARTBEAT,
|
||||
notifyBugsnag,
|
||||
publishTelemetry,
|
||||
queueTelemetryEvent,
|
||||
} from './telemetry/client';
|
||||
import { checkForDockerEngine } from './utils/monitor';
|
||||
|
||||
const unleashLibrary = import('unleash-proxy-client');
|
||||
|
||||
let unleashClient: any = null;
|
||||
import { spawnDockerCommand } from './utils/spawnDockerCommand';
|
||||
import {
|
||||
disableEnableComposeLanguageServer,
|
||||
getExtensionSetting,
|
||||
inspectExtensionSetting,
|
||||
} from './utils/settings';
|
||||
import { redact } from './telemetry/filter';
|
||||
import { hookDecorators } from './utils/editor';
|
||||
import { setupDebugging } from './dap/config';
|
||||
|
||||
export const BakeBuildCommandId = 'dockerLspClient.bake.build';
|
||||
export const ScoutImageScanCommandId = 'docker.scout.imageScan';
|
||||
|
||||
export let extensionVersion: string;
|
||||
|
||||
const errorRegExp = new RegExp('(E[A-Z]+)');
|
||||
|
||||
function registerCommands(ctx: vscode.ExtensionContext) {
|
||||
registerCommand(ctx, BakeBuildCommandId, (commandArgs: any) => {
|
||||
return new Promise((resolve) => {
|
||||
const process = spawn('docker', ['buildx', 'bake', '--help']);
|
||||
process.on('error', () => {
|
||||
resolve(false);
|
||||
});
|
||||
process.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
const args = ['buildx', 'bake'];
|
||||
registerCommand(ctx, BakeBuildCommandId, async (commandArgs: any) => {
|
||||
const result = await spawnDockerCommand(
|
||||
'buildx',
|
||||
['bake', '--help'],
|
||||
"Bake is not available. To access Docker Bake's features, install Docker Desktop.",
|
||||
);
|
||||
const args = ['buildx', 'bake'];
|
||||
|
||||
if (commandArgs['call'] === 'print') {
|
||||
args.push('--print');
|
||||
args.push(commandArgs['target']);
|
||||
} else {
|
||||
args.push('--call');
|
||||
args.push(commandArgs['call']);
|
||||
args.push(commandArgs['target']);
|
||||
}
|
||||
if (commandArgs['call'] === 'print') {
|
||||
args.push('--print');
|
||||
args.push(commandArgs['target']);
|
||||
} else {
|
||||
args.push('--call');
|
||||
args.push(commandArgs['call']);
|
||||
args.push(commandArgs['target']);
|
||||
}
|
||||
|
||||
const task = new vscode.Task(
|
||||
{ type: 'shell' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'docker buildx bake',
|
||||
'docker-vscode-extension',
|
||||
new vscode.ShellExecution('docker', args, {
|
||||
cwd: commandArgs['cwd'],
|
||||
}),
|
||||
);
|
||||
vscode.tasks.executeTask(task);
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
const task = new vscode.Task(
|
||||
{ type: 'shell' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'docker buildx bake',
|
||||
'docker-vscode-extension',
|
||||
new vscode.ShellExecution('docker', args, {
|
||||
cwd: commandArgs['cwd'],
|
||||
}),
|
||||
);
|
||||
vscode.tasks.executeTask(task);
|
||||
return result;
|
||||
});
|
||||
|
||||
registerCommand(ctx, ScoutImageScanCommandId, (args) => {
|
||||
return new Promise((resolve) => {
|
||||
const process = spawn('docker', ['scout']);
|
||||
process.on('error', () => {
|
||||
resolve(false);
|
||||
});
|
||||
process.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
const task = new vscode.Task(
|
||||
{ type: 'shell' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'docker scout',
|
||||
'docker scout',
|
||||
new vscode.ShellExecution(
|
||||
'docker',
|
||||
['scout', 'cves', args.fullTag],
|
||||
{},
|
||||
),
|
||||
);
|
||||
vscode.tasks.executeTask(task);
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
registerCommand(ctx, ScoutImageScanCommandId, async (args) => {
|
||||
const result = spawnDockerCommand(
|
||||
'scout',
|
||||
[],
|
||||
"Docker Scout is not available. To access Docker Scout's features, install Docker Desktop.",
|
||||
);
|
||||
const options: vscode.ShellExecutionOptions = {};
|
||||
if (
|
||||
vscode.workspace.workspaceFolders === undefined ||
|
||||
vscode.workspace.workspaceFolders.length === 0
|
||||
) {
|
||||
options.cwd = homedir();
|
||||
}
|
||||
const task = new vscode.Task(
|
||||
{ type: 'shell' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'docker scout',
|
||||
'docker scout',
|
||||
new vscode.ShellExecution(
|
||||
'docker',
|
||||
['scout', 'cves', args.fullTag],
|
||||
options,
|
||||
),
|
||||
);
|
||||
vscode.tasks.executeTask(task);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function registerCommand(
|
||||
export function registerCommand(
|
||||
ctx: vscode.ExtensionContext,
|
||||
id: string,
|
||||
commandCallback: (...args: any[]) => Promise<boolean>,
|
||||
|
@ -101,121 +108,143 @@ function registerCommand(
|
|||
}
|
||||
|
||||
const activateDockerLSP = async (ctx: vscode.ExtensionContext) => {
|
||||
registerCommands(ctx);
|
||||
|
||||
if (await activateDockerNativeLanguageClient(ctx)) {
|
||||
getNativeClient().start();
|
||||
getNativeClient()
|
||||
.start()
|
||||
.then(
|
||||
() => {},
|
||||
(reject) => {
|
||||
notifyBugsnag(reject);
|
||||
if (typeof reject === 'string') {
|
||||
const matches = reject.match(errorRegExp);
|
||||
if (matches !== null && matches.length > 0) {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
error_function: 'DockerLanguageClient.start',
|
||||
message: matches[0],
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (reject.code !== undefined) {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
error_function: 'DockerLanguageClient.start',
|
||||
message: String(reject.code),
|
||||
});
|
||||
return;
|
||||
}
|
||||
queueTelemetryEvent('client_heartbeat', true, {
|
||||
error_function: 'DockerLanguageClient.start',
|
||||
message: 'unrecognized',
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export function activate(ctx: vscode.ExtensionContext) {
|
||||
extensionVersion = String(ctx.extension.packageJSON.version);
|
||||
|
||||
const configValue = vscode.workspace
|
||||
.getConfiguration('docker.extension.experimental.release')
|
||||
.get<string>('march2025');
|
||||
if (configValue === 'disabled') {
|
||||
recordVersionTelemetry(configValue, 'ignored');
|
||||
|
||||
// register the Scout command even if the extension is disabled as it will show up in the UI
|
||||
registerCommand(ctx, ScoutImageScanCommandId, (args) => {
|
||||
return new Promise((resolve) => {
|
||||
const process = spawn('docker', ['scout']);
|
||||
process.on('error', () => {
|
||||
resolve(false);
|
||||
});
|
||||
process.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
const task = new vscode.Task(
|
||||
{ type: 'shell' },
|
||||
vscode.TaskScope.Workspace,
|
||||
'docker scout',
|
||||
'docker scout',
|
||||
new vscode.ShellExecution(
|
||||
'docker',
|
||||
['scout', 'cves', args.fullTag],
|
||||
{},
|
||||
),
|
||||
);
|
||||
vscode.tasks.executeTask(task);
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
async function toggleComposeLanguageServerSetting(): Promise<string> {
|
||||
const setting = inspectExtensionSetting('enableComposeLanguageServer');
|
||||
if (vscode.extensions.getExtension('redhat.vscode-yaml') !== undefined) {
|
||||
// if Red Hat's YAML extension is installed, we will auto-disable
|
||||
// the Compose language server features to prevent duplicates
|
||||
if (setting !== undefined && setting.globalValue === undefined) {
|
||||
await disableEnableComposeLanguageServer();
|
||||
return 'false';
|
||||
}
|
||||
}
|
||||
|
||||
if (configValue === 'enabled') {
|
||||
recordVersionTelemetry(configValue, 'ignored');
|
||||
activateExtension(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
unleashLibrary.then((library) => {
|
||||
const client = new library.UnleashClient({
|
||||
url: 'https://hub.docker.com/v2/feature-flags/proxy/',
|
||||
clientKey: 'changeme',
|
||||
appName: 'vscode-extension',
|
||||
});
|
||||
client.updateContext({
|
||||
userId: vscode.env.machineId,
|
||||
properties: {
|
||||
vscodeExtensionVersion: extensionVersion,
|
||||
operatingSystem:
|
||||
process.platform === 'win32' ? 'windows' : process.platform,
|
||||
},
|
||||
});
|
||||
client.on('ready', () => {
|
||||
const enabled = client.isEnabled('VSCodeReleaseMarch2025');
|
||||
recordVersionTelemetry(configValue, enabled ? 'true' : 'false');
|
||||
if (enabled) {
|
||||
activateExtension(ctx);
|
||||
}
|
||||
});
|
||||
client.start();
|
||||
unleashClient = client;
|
||||
});
|
||||
return setting === undefined ? 'undefined' : String(setting.globalValue);
|
||||
}
|
||||
|
||||
async function activateExtension(ctx: vscode.ExtensionContext) {
|
||||
if (
|
||||
vscode.workspace
|
||||
.getConfiguration('docker.extension')
|
||||
.get('dockerEngineAvailabilityPrompt')
|
||||
) {
|
||||
let notified = false;
|
||||
for (const document of vscode.workspace.textDocuments) {
|
||||
if (
|
||||
document.languageId === 'dockerfile' &&
|
||||
document.uri.scheme === 'file'
|
||||
) {
|
||||
// if a Dockerfile is open, check if a Docker engine is available
|
||||
await checkForDockerEngine();
|
||||
notified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!notified) {
|
||||
// no Dockerfiles have been opened yet,
|
||||
// listen for one being opened and check if a Docker Engine is available
|
||||
const disposable = vscode.workspace.onDidOpenTextDocument((document) => {
|
||||
if (
|
||||
document.languageId === 'dockerfile' &&
|
||||
document.uri.scheme === 'file'
|
||||
) {
|
||||
checkForDockerEngine();
|
||||
disposable.dispose();
|
||||
export async function activate(ctx: vscode.ExtensionContext) {
|
||||
setupDebugging(ctx);
|
||||
hookDecorators(ctx);
|
||||
const composeSetting = await toggleComposeLanguageServerSetting();
|
||||
extensionVersion = String(ctx.extension.packageJSON.version);
|
||||
Bugsnag.start({
|
||||
apiKey: 'c5b75b41a335069129747c7196ec207a',
|
||||
appType: 'vscode',
|
||||
appVersion: extensionVersion,
|
||||
autoDetectErrors: false,
|
||||
hostname: vscode.env.machineId,
|
||||
metadata: {
|
||||
system: {
|
||||
os: process.platform === 'win32' ? 'windows' : process.platform,
|
||||
arch: process.arch === 'x64' ? 'amd64' : process.arch,
|
||||
app_host: vscode.env.appHost,
|
||||
app_name: vscode.env.appName,
|
||||
machine_id: vscode.env.machineId,
|
||||
client_session: vscode.env.sessionId,
|
||||
},
|
||||
},
|
||||
onError: (event: Event): void => {
|
||||
for (let i = 0; i < event.errors.length; i++) {
|
||||
event.errors[i].errorMessage = redact(event.errors[i].errorMessage);
|
||||
for (let j = 0; j < event.errors[i].stacktrace.length; j++) {
|
||||
event.errors[i].stacktrace[j].file = redact(
|
||||
event.errors[i].stacktrace[j].file,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
event.device.hostname = vscode.env.machineId;
|
||||
},
|
||||
onSession: (session: Session): void | boolean => {
|
||||
session.id = vscode.env.sessionId;
|
||||
},
|
||||
sendCode: false,
|
||||
});
|
||||
|
||||
recordVersionTelemetry(composeSetting);
|
||||
registerCommands(ctx);
|
||||
listenForOpenedDocuments();
|
||||
activateDockerLSP(ctx);
|
||||
listenForConfigurationChanges(ctx);
|
||||
}
|
||||
|
||||
async function listenForOpenedDocument(
|
||||
languageId: string,
|
||||
shouldReact: () => boolean,
|
||||
fileOpened: () => Promise<void>,
|
||||
) {
|
||||
let reacted = false;
|
||||
for (const document of vscode.workspace.textDocuments) {
|
||||
if (document.languageId === languageId && document.uri.scheme === 'file') {
|
||||
// if the expected file type is currently opened, react if necessary
|
||||
if (shouldReact()) {
|
||||
await fileOpened();
|
||||
}
|
||||
reacted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
activateDockerLSP(ctx);
|
||||
listenForConfigurationChanges(ctx);
|
||||
if (!reacted) {
|
||||
// no documents for the expected file type is currently opened,
|
||||
// listen for one being opened and react if necessary
|
||||
const disposable = vscode.workspace.onDidOpenTextDocument((document) => {
|
||||
if (
|
||||
document.languageId === languageId &&
|
||||
document.uri.scheme === 'file'
|
||||
) {
|
||||
if (shouldReact()) {
|
||||
fileOpened();
|
||||
}
|
||||
disposable.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for Dockerfiles files being opened.
|
||||
*
|
||||
* If a Dockerfile is opened, we want to check to see if a Docker Engine
|
||||
* is available. If not, we will prompt the user to install Docker
|
||||
* Desktop or open Docker Desktop.
|
||||
*/
|
||||
function listenForOpenedDocuments(): void {
|
||||
listenForOpenedDocument(
|
||||
'dockerfile',
|
||||
() => getExtensionSetting('dockerEngineAvailabilityPrompt') === true,
|
||||
checkForDockerEngine,
|
||||
);
|
||||
}
|
||||
|
||||
function listenForConfigurationChanges(ctx: vscode.ExtensionContext) {
|
||||
|
@ -243,6 +272,10 @@ function listenForConfigurationChanges(ctx: vscode.ExtensionContext) {
|
|||
const configurations = [
|
||||
'docker.lsp.telemetry',
|
||||
'docker.lsp.experimental.vulnerabilityScanning',
|
||||
'docker.lsp.experimental.scout.criticalHighVulnerabilities',
|
||||
'docker.lsp.experimental.scout.notPinnedDigest',
|
||||
'docker.lsp.experimental.scout.recommendedTag',
|
||||
'docker.lsp.experimental.scout.vulnerabilities',
|
||||
];
|
||||
const filtered = configurations.filter((config) =>
|
||||
e.affectsConfiguration(config),
|
||||
|
@ -257,36 +290,51 @@ function listenForConfigurationChanges(ctx: vscode.ExtensionContext) {
|
|||
);
|
||||
}
|
||||
|
||||
function recordVersionTelemetry(
|
||||
featureFlag: string | undefined,
|
||||
featureFlagValue: 'true' | 'false' | 'ignored',
|
||||
) {
|
||||
function recordVersionTelemetry(composeSetting: string) {
|
||||
const installedExtensions = vscode.extensions.all
|
||||
.filter((extension) => {
|
||||
return (
|
||||
extension.id === 'ms-azuretools.vscode-docker' ||
|
||||
extension.id === 'ms-azuretools.vscode-containers' ||
|
||||
extension.id === 'redhat.vscode-yaml'
|
||||
);
|
||||
})
|
||||
.map((extension) => extension.id);
|
||||
let versionString: string | null = null;
|
||||
const process = spawn('docker', ['-v']);
|
||||
process.stdout.on('data', (data) => {
|
||||
versionString = String(data).trim();
|
||||
if (versionString === null) {
|
||||
versionString = '';
|
||||
}
|
||||
versionString += String(data).trim();
|
||||
});
|
||||
process.on('error', () => {
|
||||
// this happens if docker cannot be found on the PATH
|
||||
queueTelemetryEvent('client_heartbeat', false, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, false, {
|
||||
docker_version: 'spawn docker -v failed',
|
||||
feature_flag: featureFlag,
|
||||
feature_flag_value: featureFlagValue,
|
||||
installedExtensions,
|
||||
settings: {
|
||||
'docker.extension.enableComposeLanguageServer': composeSetting,
|
||||
},
|
||||
});
|
||||
publishTelemetry();
|
||||
});
|
||||
process.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
queueTelemetryEvent('client_heartbeat', false, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, false, {
|
||||
docker_version: String(versionString),
|
||||
feature_flag: featureFlag,
|
||||
feature_flag_value: featureFlagValue,
|
||||
installedExtensions,
|
||||
settings: {
|
||||
'docker.extension.enableComposeLanguageServer': composeSetting,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
queueTelemetryEvent('client_heartbeat', false, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, false, {
|
||||
docker_version: String(code),
|
||||
feature_flag: featureFlag,
|
||||
feature_flag_value: featureFlagValue,
|
||||
installedExtensions,
|
||||
settings: {
|
||||
'docker.extension.enableComposeLanguageServer': composeSetting,
|
||||
},
|
||||
});
|
||||
}
|
||||
publishTelemetry();
|
||||
|
@ -294,10 +342,6 @@ function recordVersionTelemetry(
|
|||
}
|
||||
|
||||
export async function deactivate() {
|
||||
if (unleashClient !== null) {
|
||||
unleashClient.stop();
|
||||
unleashClient = null;
|
||||
}
|
||||
const client = getNativeClient();
|
||||
if (client !== undefined) {
|
||||
client.stop();
|
||||
|
|
|
@ -2,20 +2,40 @@ import https from 'https';
|
|||
import * as process from 'process';
|
||||
import * as vscode from 'vscode';
|
||||
import { extensionVersion } from '../extension';
|
||||
import Bugsnag from '@bugsnag/js';
|
||||
|
||||
export const EVENT_CLIENT_HEARTBEAT = 'client_heartbeat';
|
||||
|
||||
interface TelemetryRecord {
|
||||
event: string;
|
||||
source: string;
|
||||
event_timestamp: number;
|
||||
properties: { [key: string]: boolean | number | string | undefined };
|
||||
properties: { [key: string]: boolean | number | string | object | undefined };
|
||||
}
|
||||
|
||||
const events: TelemetryRecord[] = [];
|
||||
|
||||
function shouldReportToBugsnag(): boolean {
|
||||
if (!vscode.env.isTelemetryEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const config = vscode.workspace
|
||||
.getConfiguration('docker.lsp')
|
||||
.get('telemetry');
|
||||
return config === 'error' || config === 'all';
|
||||
}
|
||||
|
||||
export function notifyBugsnag(err: any): void {
|
||||
if (shouldReportToBugsnag()) {
|
||||
Bugsnag.notify(err);
|
||||
}
|
||||
}
|
||||
|
||||
export function queueTelemetryEvent(
|
||||
event: string,
|
||||
error: boolean,
|
||||
properties: { [key: string]: boolean | number | string | undefined },
|
||||
properties: { [key: string]: boolean | number | string | object | undefined },
|
||||
) {
|
||||
if (!vscode.env.isTelemetryEnabled) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
function redactFilePath(path: string): string {
|
||||
const split = path.split(/[/\\]/);
|
||||
if (split.length < 2) {
|
||||
return path;
|
||||
}
|
||||
const redacted = split.pop();
|
||||
if (redacted === undefined) {
|
||||
return '';
|
||||
}
|
||||
return `REDACTED/${redacted}`;
|
||||
}
|
||||
|
||||
export function redact(s: string): string {
|
||||
const words = s.split(/\s+/);
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
words[i] = redactFilePath(words[i]);
|
||||
}
|
||||
return words.join(' ');
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
import {
|
||||
BottomBarPanel,
|
||||
EditorView,
|
||||
MarkerType,
|
||||
ProblemsView,
|
||||
TextEditor,
|
||||
VSBrowser,
|
||||
} from 'vscode-extension-tester';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { expect } from 'chai';
|
||||
|
||||
async function problemsExist(view: ProblemsView) {
|
||||
const markers = await view.getAllVisibleMarkers(MarkerType.Any);
|
||||
return markers.length > 0;
|
||||
}
|
||||
|
||||
describe('Problems', function () {
|
||||
let bottomBar: BottomBarPanel;
|
||||
let view: ProblemsView;
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
bottomBar = new BottomBarPanel();
|
||||
await bottomBar.toggle(true);
|
||||
|
||||
view = await bottomBar.openProblemsView();
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await bottomBar.toggle(false);
|
||||
});
|
||||
|
||||
describe('Problems', function () {
|
||||
let editorView: EditorView;
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
|
||||
editorView = new EditorView();
|
||||
|
||||
const dockerfilePath = path.join('test', 'resources', 'Dockerfile');
|
||||
fs.writeFileSync(dockerfilePath, 'FROM scratch\nENTRYPOINT ""\n');
|
||||
|
||||
await VSBrowser.instance.openResources(dockerfilePath);
|
||||
|
||||
await view.getDriver().wait(async function () {
|
||||
return await problemsExist(view);
|
||||
}, 15000);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await editorView.closeAllEditors();
|
||||
|
||||
const dockerfilePath = path.join('test', 'resources', 'Dockerfile');
|
||||
fs.writeFileSync(dockerfilePath, '');
|
||||
});
|
||||
|
||||
it('Dockerfile has no errors', async function () {
|
||||
const errors = await view.getAllVisibleMarkers(MarkerType.Error);
|
||||
expect(errors).is.empty;
|
||||
});
|
||||
|
||||
it('Dockerfile has a JSONArgsRecommended warning', async function () {
|
||||
const warnings = await view.getAllVisibleMarkers(MarkerType.Warning);
|
||||
expect(warnings.length).equals(1);
|
||||
|
||||
const warningText = await warnings[0].getText();
|
||||
expect(warningText).equal(
|
||||
'Warning: JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals (JSON arguments recommended for ENTRYPOINT to prevent unintended behavior related to OS signals) at line 2 and character 1. generated by Docker DX (docker-language-server)',
|
||||
);
|
||||
});
|
||||
|
||||
it('Dockerfile modified with a FromAsCasing warning', async function () {
|
||||
this.timeout(30000);
|
||||
|
||||
const editor = (await editorView.openEditor('Dockerfile')) as TextEditor;
|
||||
await editor.clearText();
|
||||
await editor.setText('FROM scratch\n');
|
||||
await editor.typeTextAt(2, 1, 'FROM scratch as base');
|
||||
|
||||
await view.getDriver().wait(async function () {
|
||||
return await problemsExist(view);
|
||||
}, 15000);
|
||||
|
||||
const warnings = await view.getAllVisibleMarkers(MarkerType.Warning);
|
||||
expect(warnings.length).equals(1);
|
||||
|
||||
const warningText = await warnings[0].getText();
|
||||
expect(warningText).equal(
|
||||
"Warning: The 'as' keyword should match the case of the 'from' keyword ('as' and 'FROM' keywords' casing do not match) at line 2 and character 1. generated by Docker DX (docker-language-server)",
|
||||
);
|
||||
|
||||
await editor.save();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Docker Bake', function () {
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
|
||||
await VSBrowser.instance.openResources(
|
||||
path.join('test', 'resources', 'docker-bake.hcl'),
|
||||
);
|
||||
|
||||
await view.getDriver().wait(async function () {
|
||||
return await problemsExist(view);
|
||||
}, 15000);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await new EditorView().closeAllEditors();
|
||||
});
|
||||
|
||||
it('Bake file has an error about not being able to find an ARG', async function () {
|
||||
const errors = await view.getAllVisibleMarkers(MarkerType.Error);
|
||||
expect(errors.length).equals(1);
|
||||
|
||||
const errorText = await errors[0].getText();
|
||||
expect(errorText).equal(
|
||||
"Error: 'var' not defined as an ARG in your Dockerfile at line 3 and character 9. generated by Docker DX (docker-language-server)",
|
||||
);
|
||||
});
|
||||
|
||||
it('Bake file has no warnings', async function () {
|
||||
const warnings = await view.getAllVisibleMarkers(MarkerType.Warning);
|
||||
expect(warnings).is.empty;
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { DockerfileParser } from 'dockerfile-ast';
|
||||
|
||||
/**
|
||||
* Decoration that inserts a horizontal line into the editor.
|
||||
*/
|
||||
const decoration = vscode.window.createTextEditorDecorationType({
|
||||
isWholeLine: true,
|
||||
borderWidth: '1px 0 0 0',
|
||||
borderStyle: 'solid',
|
||||
borderColor: new vscode.ThemeColor('panelTitle.activeBorder'),
|
||||
});
|
||||
|
||||
function getDecorationRanges(document: vscode.TextDocument): vscode.Range[] {
|
||||
if (
|
||||
vscode.workspace
|
||||
.getConfiguration('docker.extension.editor', document)
|
||||
.get<boolean>('dockerfileBuildStageDecorationLines') &&
|
||||
document.languageId === 'dockerfile' &&
|
||||
document.uri.scheme === 'file'
|
||||
) {
|
||||
const dockerfile = DockerfileParser.parse(document.getText());
|
||||
return dockerfile.getFROMs().map((from) => {
|
||||
const line = from.getRange().start.line;
|
||||
return new vscode.Range(line, 0, line, 0);
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function hookDecorators(ctx: vscode.ExtensionContext): void {
|
||||
vscode.workspace.onDidChangeConfiguration(
|
||||
(event) => {
|
||||
if (
|
||||
event.affectsConfiguration(
|
||||
'docker.extension.editor.dockerfileBuildStageDecorationLines',
|
||||
)
|
||||
) {
|
||||
vscode.window.visibleTextEditors.forEach((editor) =>
|
||||
editor.setDecorations(
|
||||
decoration,
|
||||
getDecorationRanges(editor.document),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
null,
|
||||
ctx.subscriptions,
|
||||
);
|
||||
|
||||
vscode.window.visibleTextEditors.forEach((editor) =>
|
||||
editor.setDecorations(decoration, getDecorationRanges(editor.document)),
|
||||
);
|
||||
|
||||
vscode.window.onDidChangeVisibleTextEditors(
|
||||
(editors) => {
|
||||
for (const editor of editors) {
|
||||
editor.setDecorations(decoration, getDecorationRanges(editor.document));
|
||||
}
|
||||
},
|
||||
null,
|
||||
ctx.subscriptions,
|
||||
);
|
||||
|
||||
vscode.workspace.onDidChangeTextDocument(
|
||||
(event) => {
|
||||
for (const editor of vscode.window.visibleTextEditors) {
|
||||
if (
|
||||
event.document.uri.scheme === editor.document.uri.scheme &&
|
||||
event.document.uri.path === editor.document.uri.path
|
||||
) {
|
||||
editor.setDecorations(
|
||||
decoration,
|
||||
getDecorationRanges(editor.document),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
ctx.subscriptions,
|
||||
);
|
||||
}
|
|
@ -9,13 +9,30 @@ import {
|
|||
} from 'vscode-languageclient/node';
|
||||
import { BakeBuildCommandId } from '../../extension';
|
||||
import { getTelemetryValue } from './lsp';
|
||||
import { queueTelemetryEvent } from '../../telemetry/client';
|
||||
import {
|
||||
EVENT_CLIENT_HEARTBEAT,
|
||||
notifyBugsnag,
|
||||
queueTelemetryEvent,
|
||||
} from '../../telemetry/client';
|
||||
|
||||
export class DockerLanguageClient extends LanguageClient {
|
||||
protected fillInitializeParams(params: InitializeParams): void {
|
||||
super.fillInitializeParams(params);
|
||||
const removeOverlappingIssues =
|
||||
vscode.extensions.getExtension('ms-azuretools.vscode-docker') !==
|
||||
undefined ||
|
||||
vscode.extensions.getExtension('ms-azuretools.vscode-containers') !==
|
||||
undefined;
|
||||
const dockerConfiguration = vscode.workspace.getConfiguration('docker.lsp');
|
||||
const extensionConfiguration =
|
||||
vscode.workspace.getConfiguration('docker.extension');
|
||||
params.initializationOptions = {
|
||||
dockercomposeExperimental: {
|
||||
composeSupport: extensionConfiguration.get<boolean>(
|
||||
'enableComposeLanguageServer',
|
||||
),
|
||||
},
|
||||
dockerfileExperimental: { removeOverlappingIssues },
|
||||
telemetry: getTelemetryValue(dockerConfiguration.get('telemetry')),
|
||||
};
|
||||
params.capabilities.experimental = {
|
||||
|
@ -34,7 +51,8 @@ export class DockerLanguageClient extends LanguageClient {
|
|||
data?: any,
|
||||
showNotification?: boolean | 'force',
|
||||
): void {
|
||||
queueTelemetryEvent('client_heartbeat', true, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
message: filterMessage(message),
|
||||
error_function: 'DockerLanguageClient.error',
|
||||
show_notification: showNotification,
|
||||
});
|
||||
|
@ -51,19 +69,21 @@ export class DockerLanguageClient extends LanguageClient {
|
|||
): ErrorHandlerResult | Promise<ErrorHandlerResult> {
|
||||
const result: any = handler.error(error, message, count);
|
||||
if (result.action !== undefined) {
|
||||
queueTelemetryEvent('client_heartbeat', true, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
error_function: 'ErrorHandler.error',
|
||||
count: count,
|
||||
action: result.action,
|
||||
});
|
||||
}
|
||||
notifyBugsnag(error);
|
||||
return result;
|
||||
},
|
||||
|
||||
closed(): CloseHandlerResult | Promise<CloseHandlerResult> {
|
||||
const result: any = handler.closed();
|
||||
if (result.action !== undefined) {
|
||||
queueTelemetryEvent('client_heartbeat', true, {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
message: filterMessage(result.message),
|
||||
error_function: 'ErrorHandler.closed',
|
||||
action: result.action,
|
||||
});
|
||||
|
@ -73,3 +93,21 @@ export class DockerLanguageClient extends LanguageClient {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
function filterMessage(message: string): string {
|
||||
if (
|
||||
message ===
|
||||
'The Docker Language Server server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.' ||
|
||||
message ===
|
||||
"Docker Language Server client: couldn't create connection to server." ||
|
||||
message ===
|
||||
'Connection to server got closed. Server will not be restarted.' ||
|
||||
message === 'Server initialization failed.' ||
|
||||
message === 'Connection to server got closed. Server will restart.' ||
|
||||
message === 'Restarting server failed' ||
|
||||
message === 'Stopping server failed'
|
||||
) {
|
||||
return message;
|
||||
}
|
||||
return 'unrecognized';
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import * as fs from 'fs';
|
||||
import * as net from 'net';
|
||||
import * as path from 'path';
|
||||
import * as process from 'process';
|
||||
|
@ -12,6 +13,10 @@ import {
|
|||
} from 'vscode-languageclient/node';
|
||||
import { DockerLanguageClient } from './languageClient';
|
||||
import { InlineCompletionItemFeature } from 'vscode-languageclient/lib/common/inlineCompletion';
|
||||
import {
|
||||
EVENT_CLIENT_HEARTBEAT,
|
||||
queueTelemetryEvent,
|
||||
} from '../../telemetry/client';
|
||||
|
||||
let nativeClient: LanguageClient;
|
||||
|
||||
|
@ -86,6 +91,7 @@ async function getServerOptions(
|
|||
|
||||
const binaryPath = getBinaryPath(ctx);
|
||||
if (binaryPath !== null) {
|
||||
await chmod(binaryPath);
|
||||
return {
|
||||
command: binaryPath,
|
||||
transport: TransportKind.stdio,
|
||||
|
@ -95,6 +101,27 @@ async function getServerOptions(
|
|||
return null;
|
||||
}
|
||||
|
||||
async function chmod(binaryPath: string): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
fs.access(binaryPath, fs.constants.X_OK, (accessErr) => {
|
||||
if (accessErr !== null) {
|
||||
fs.chmod(binaryPath, 0o755, (chmodErr) => {
|
||||
if (chmodErr !== null) {
|
||||
queueTelemetryEvent(EVENT_CLIENT_HEARTBEAT, true, {
|
||||
error_function: 'chmod',
|
||||
code: chmodErr.code,
|
||||
errno: chmodErr.errno,
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the telemetry setting that should be used for the extension and the Docker Language Server.
|
||||
* If the user has telemetry disabled then "off" regardless of what the Docker telemetry setting has been set to.
|
||||
|
@ -115,28 +142,90 @@ export function getTelemetryValue(
|
|||
return 'all';
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a code actions provider for Dockerfiles so that diagnostics
|
||||
* from Scout will have a corresponding code action for opening the
|
||||
* Settings editor to disable the warning.
|
||||
*/
|
||||
function registerSettingsToggleCodeActions() {
|
||||
vscode.languages.registerCodeActionsProvider('dockerfile', {
|
||||
provideCodeActions(_document, _range, ctx) {
|
||||
const filtered = ctx.diagnostics.filter((diagnostic) => {
|
||||
if (diagnostic.source === 'Docker DX (docker-language-server)') {
|
||||
let code = diagnostic.code;
|
||||
if (typeof code === 'object' && code.value !== undefined) {
|
||||
code = code.value;
|
||||
}
|
||||
switch (code) {
|
||||
case 'critical_high_vulnerabilities':
|
||||
case 'not_pinned_digest':
|
||||
case 'recommended_tag':
|
||||
case 'vulnerabilities':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return filtered.map((diagnostic) => {
|
||||
let code = diagnostic.code;
|
||||
if (typeof code === 'object' && code.value !== undefined) {
|
||||
code = code.value;
|
||||
}
|
||||
const command: vscode.Command = {
|
||||
command: 'workbench.action.openSettings',
|
||||
title: `Ignore ${code} errors`,
|
||||
};
|
||||
switch (code) {
|
||||
case 'critical_high_vulnerabilities':
|
||||
command.arguments = [
|
||||
'docker.lsp.experimental.scout.criticalHighVulnerabilities',
|
||||
];
|
||||
break;
|
||||
case 'not_pinned_digest':
|
||||
command.arguments = [
|
||||
'docker.lsp.experimental.scout.notPinnedDigest',
|
||||
];
|
||||
break;
|
||||
case 'recommended_tag':
|
||||
command.arguments = [
|
||||
'docker.lsp.experimental.scout.recommendedTag',
|
||||
];
|
||||
break;
|
||||
case 'vulnerabilities':
|
||||
command.arguments = [
|
||||
'docker.lsp.experimental.scout.vulnerabilities',
|
||||
];
|
||||
break;
|
||||
}
|
||||
return command;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createNative(ctx: vscode.ExtensionContext): Promise<boolean> {
|
||||
const clientOptions: LanguageClientOptions = {
|
||||
progressOnInitialization: true,
|
||||
outputChannel: vscode.window.createOutputChannel('Docker Language Server'),
|
||||
revealOutputChannelOn: RevealOutputChannelOn.Never,
|
||||
markdown: {
|
||||
isTrusted: false,
|
||||
supportHtml: true,
|
||||
},
|
||||
middleware: {
|
||||
handleDiagnostics(uri, diagnostics, next) {
|
||||
diagnostics.map((diagnostic) => {
|
||||
diagnostic.source = `Docker DX (${diagnostic.source})`;
|
||||
});
|
||||
next(uri, diagnostics);
|
||||
},
|
||||
|
||||
workspace: {
|
||||
configuration: (params, token, next) => {
|
||||
const result = next(params, token) as any;
|
||||
return [
|
||||
{
|
||||
experimental: {
|
||||
vulnerabilityScanning:
|
||||
result[0].experimental.vulnerabilityScanning,
|
||||
},
|
||||
telemetry: getTelemetryValue(result[0].telemetry),
|
||||
},
|
||||
];
|
||||
const result = next(params, token) as any[];
|
||||
return result.map((value) => {
|
||||
value.telemetry = getTelemetryValue(value.telemetry);
|
||||
return value;
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -163,10 +252,65 @@ async function createNative(ctx: vscode.ExtensionContext): Promise<boolean> {
|
|||
return true;
|
||||
}
|
||||
|
||||
async function startDockerfileLanguageServer(
|
||||
ctx: vscode.ExtensionContext,
|
||||
): Promise<void> {
|
||||
const serverModule = ctx.asAbsolutePath(
|
||||
path.join('dist', 'dockerfile-language-server-nodejs', 'lib', 'server.js'),
|
||||
);
|
||||
const serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: { execArgv: ['--nolazy', '--inspect=6009'] },
|
||||
},
|
||||
};
|
||||
|
||||
const dockerfileLanguageClient = new LanguageClient(
|
||||
'dockerfile-language-server',
|
||||
'Dockerfile Language Server',
|
||||
serverOptions,
|
||||
{
|
||||
documentSelector: [{ language: 'dockerfile', scheme: 'file' }],
|
||||
middleware: {
|
||||
handleDiagnostics() {
|
||||
// leave all error reporting to the Docker Language Server
|
||||
return [];
|
||||
},
|
||||
workspace: {
|
||||
configuration: (params) => {
|
||||
return params.items.map((value) => {
|
||||
if (value.section === 'docker.languageserver.formatter') {
|
||||
return { ignoreMultilineInstructions: true };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
dockerfileLanguageClient.registerProposedFeatures();
|
||||
|
||||
await dockerfileLanguageClient.start();
|
||||
ctx.subscriptions.push(dockerfileLanguageClient);
|
||||
}
|
||||
|
||||
export async function activateDockerNativeLanguageClient(
|
||||
ctx: vscode.ExtensionContext,
|
||||
): Promise<boolean> {
|
||||
if (
|
||||
vscode.extensions.getExtension('ms-azuretools.vscode-docker') ===
|
||||
undefined &&
|
||||
vscode.extensions.getExtension('ms-azuretools.vscode-containers') ===
|
||||
undefined
|
||||
) {
|
||||
// start the Dockerfile Language Server if Microsoft's extensions are not installed
|
||||
await startDockerfileLanguageServer(ctx);
|
||||
}
|
||||
if (await createNative(ctx)) {
|
||||
registerSettingsToggleCodeActions();
|
||||
ctx.subscriptions.push(nativeClient);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { access } from 'fs';
|
||||
import { spawn } from 'child_process';
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
promptOpenDockerDesktop,
|
||||
promptInstallDesktop,
|
||||
promptUnauthenticatedDesktop,
|
||||
} from './prompt';
|
||||
import { isDockerDesktopInstalled } from './os';
|
||||
import { getExtensionSetting } from './settings';
|
||||
import { spawnDockerCommand } from './spawnDockerCommand';
|
||||
|
||||
enum DockerEngineStatus {
|
||||
Unavailable,
|
||||
|
@ -13,11 +18,7 @@ enum DockerEngineStatus {
|
|||
* either install or open Docker Desktop.
|
||||
*/
|
||||
export async function checkForDockerEngine(): Promise<void> {
|
||||
if (
|
||||
!vscode.workspace
|
||||
.getConfiguration('docker.extension')
|
||||
.get('dockerEngineAvailabilityPrompt')
|
||||
) {
|
||||
if (!getExtensionSetting('dockerEngineAvailabilityPrompt')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -38,130 +39,26 @@ export async function checkForDockerEngine(): Promise<void> {
|
|||
*/
|
||||
function checkDockerStatus(): Promise<DockerEngineStatus> {
|
||||
return new Promise<DockerEngineStatus>((resolve) => {
|
||||
const s = spawn('docker', ['ps']);
|
||||
let output = '';
|
||||
s.stderr.on('data', (chunk) => {
|
||||
output += String(chunk);
|
||||
});
|
||||
s.on('error', () => {
|
||||
// this happens if docker cannot be found on the PATH
|
||||
return resolve(DockerEngineStatus.Unavailable);
|
||||
});
|
||||
s.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
return resolve(DockerEngineStatus.Available);
|
||||
}
|
||||
if (
|
||||
output.includes('Sign-in enforcement is enabled') ||
|
||||
output.includes(
|
||||
'request returned Internal Server Error for API route and version',
|
||||
)
|
||||
) {
|
||||
return resolve(DockerEngineStatus.Unauthenticated);
|
||||
}
|
||||
return resolve(DockerEngineStatus.Unavailable);
|
||||
spawnDockerCommand('ps', [], undefined, {
|
||||
onError: () => resolve(DockerEngineStatus.Unavailable),
|
||||
onStderr: (chunk) => {
|
||||
output += String(chunk);
|
||||
},
|
||||
onExit: (code) => {
|
||||
if (code === 0) {
|
||||
return resolve(DockerEngineStatus.Available);
|
||||
}
|
||||
if (
|
||||
output.includes('Sign-in enforcement is enabled') ||
|
||||
output.includes(
|
||||
'request returned Internal Server Error for API route and version',
|
||||
)
|
||||
) {
|
||||
return resolve(DockerEngineStatus.Unauthenticated);
|
||||
}
|
||||
return resolve(DockerEngineStatus.Unavailable);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getDockerDesktopPath(): string {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
return 'C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe';
|
||||
case 'darwin':
|
||||
return '/Applications/Docker.app';
|
||||
}
|
||||
return '/opt/docker-desktop/bin/com.docker.backend';
|
||||
}
|
||||
|
||||
async function isDockerDesktopInstalled(): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
const s = spawn('docker', ['desktop', 'version']);
|
||||
s.on('error', () => {
|
||||
// this happens if docker cannot be found on the PATH
|
||||
resolve(false);
|
||||
});
|
||||
s.on('exit', (code) => {
|
||||
if (code === 0) {
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
access(getDockerDesktopPath(), (err) => {
|
||||
resolve(err === null);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function disableDockerEngineAvailabilityPrompt(): void {
|
||||
vscode.workspace
|
||||
.getConfiguration('docker.extension')
|
||||
.set('dockerEngineAvailabilityPrompt', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to login to Docker Desktop.
|
||||
*/
|
||||
async function promptUnauthenticatedDesktop(): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
'Docker is not running. To get help with your Dockerfile, sign in to Docker Desktop.',
|
||||
"Don't show again",
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
disableDockerEngineAvailabilityPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to open Docker Desktop.
|
||||
*/
|
||||
async function promptOpenDockerDesktop(): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
'Docker is not running. To get help with your Dockerfile, start Docker.',
|
||||
"Don't show again",
|
||||
'Open Docker Desktop',
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
disableDockerEngineAvailabilityPrompt();
|
||||
} else if (response === 'Open Docker Desktop') {
|
||||
const dockerDesktopPath = getDockerDesktopPath();
|
||||
if (process.platform === 'darwin') {
|
||||
spawn('open', [dockerDesktopPath]).on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to open Docker Desktop: open ${dockerDesktopPath}`,
|
||||
{ modal: true },
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
spawn(dockerDesktopPath).on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to open Docker Desktop: ${dockerDesktopPath}`,
|
||||
{ modal: true },
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to install Docker Desktop by navigating to the
|
||||
* website.
|
||||
*/
|
||||
async function promptInstallDesktop(): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
'Docker is not running. To get help with your Dockerfile, start Docker.',
|
||||
"Don't show again",
|
||||
'Install Docker Desktop',
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
disableDockerEngineAvailabilityPrompt();
|
||||
} else if (response === 'Install Docker Desktop') {
|
||||
vscode.env.openExternal(
|
||||
vscode.Uri.parse('https://docs.docker.com/install/'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { access } from 'fs';
|
||||
import { spawnDockerCommand } from './spawnDockerCommand';
|
||||
|
||||
export function getDockerDesktopPath(): string {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
return 'C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe';
|
||||
case 'darwin':
|
||||
return '/Applications/Docker.app';
|
||||
}
|
||||
return '/opt/docker-desktop/bin/com.docker.backend';
|
||||
}
|
||||
|
||||
export async function isDockerDesktopInstalled(): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
spawnDockerCommand('desktop', ['version'], undefined, {
|
||||
onError: () => resolve(false),
|
||||
|
||||
onExit: (code) => {
|
||||
if (code === 0) {
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
access(getDockerDesktopPath(), (err) => {
|
||||
resolve(err === null);
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { spawn } from 'child_process';
|
||||
import { disableDockerEngineAvailabilityPrompt } from './settings';
|
||||
import { getDockerDesktopPath } from './os';
|
||||
|
||||
/**
|
||||
* Prompts the user to login to Docker Desktop.
|
||||
*/
|
||||
export async function promptUnauthenticatedDesktop(): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
'Docker is not running. To get help with your Dockerfile, sign in to Docker Desktop.',
|
||||
"Don't show again",
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
await disableDockerEngineAvailabilityPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to open Docker Desktop.
|
||||
*/
|
||||
export async function promptOpenDockerDesktop(): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
'Docker is not running. To get help with your Dockerfile, start Docker.',
|
||||
"Don't show again",
|
||||
'Open Docker Desktop',
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
await disableDockerEngineAvailabilityPrompt();
|
||||
} else if (response === 'Open Docker Desktop') {
|
||||
const dockerDesktopPath = getDockerDesktopPath();
|
||||
if (process.platform === 'darwin') {
|
||||
spawn('open', [dockerDesktopPath]).on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to open Docker Desktop: open ${dockerDesktopPath}`,
|
||||
{ modal: true },
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
spawn(dockerDesktopPath).on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to open Docker Desktop: ${dockerDesktopPath}`,
|
||||
{ modal: true },
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to install Docker Desktop by navigating to the
|
||||
* website.
|
||||
*/
|
||||
export async function promptInstallDesktop(
|
||||
message: string = 'Docker is not running. To get help with your Dockerfile, install Docker.',
|
||||
): Promise<void> {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
message,
|
||||
"Don't show again",
|
||||
'Install Docker Desktop',
|
||||
);
|
||||
if (response === "Don't show again") {
|
||||
await disableDockerEngineAvailabilityPrompt();
|
||||
} else if (response === 'Install Docker Desktop') {
|
||||
vscode.env.openExternal(
|
||||
vscode.Uri.parse('https://docs.docker.com/install/'),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import * as vscode from 'vscode';
|
||||
|
||||
type DockerExtensionSettings =
|
||||
| 'dockerEngineAvailabilityPrompt'
|
||||
| 'enableComposeLanguageServer'
|
||||
| 'enableBuildDebugging';
|
||||
|
||||
/**
|
||||
* Retrieves the value of a specified setting from the Docker extension's configuration.
|
||||
*
|
||||
* @param setting - The name of the setting to retrieve.
|
||||
* @returns The value of the specified setting, or `undefined` if the setting is not found.
|
||||
*/
|
||||
export function getExtensionSetting<T>(setting: DockerExtensionSettings) {
|
||||
return vscode.workspace.getConfiguration('docker.extension').get<T>(setting);
|
||||
}
|
||||
|
||||
export function inspectExtensionSetting(setting: DockerExtensionSettings) {
|
||||
return vscode.workspace.getConfiguration('docker.extension').inspect(setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value of a specified setting in the Docker extension's configuration.
|
||||
*
|
||||
* @param setting - The name of the setting to update.
|
||||
* @param value - The new value to set for the specified setting.
|
||||
*/
|
||||
async function setExtensionSetting(
|
||||
setting: string,
|
||||
value: string | boolean,
|
||||
configurationTarget: vscode.ConfigurationTarget = vscode.ConfigurationTarget
|
||||
.Global,
|
||||
): Promise<void> {
|
||||
return vscode.workspace
|
||||
.getConfiguration('docker.extension')
|
||||
.update(setting, value, configurationTarget);
|
||||
}
|
||||
|
||||
export async function disableDockerEngineAvailabilityPrompt(): Promise<void> {
|
||||
return setExtensionSetting('dockerEngineAvailabilityPrompt', false);
|
||||
}
|
||||
|
||||
export async function disableEnableComposeLanguageServer(): Promise<void> {
|
||||
return setExtensionSetting('enableComposeLanguageServer', false);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Spawns a Docker command as a child process and handles its execution.
|
||||
*
|
||||
* @param command - The Docker command to execute (e.g., "run", "build").
|
||||
* @param args - An optional array of arguments to pass to the Docker command.
|
||||
* @param processEvents - An object containing optional callback functions for handling process events:
|
||||
* - onExit: Invoked when the process exits with the exit code.
|
||||
* - onError: Invoked when an error occurs during process execution.
|
||||
* - onStdout: Invoked when there is data written to the standard output stream.
|
||||
* - onStderr: Invoked when there is data written to the standard error stream.
|
||||
* @returns A promise that resolves to `true` if the command exits with a code of 0, or `false` otherwise.
|
||||
*/
|
||||
import { spawn } from 'child_process';
|
||||
import { promptInstallDesktop } from './prompt';
|
||||
import { getExtensionSetting } from './settings';
|
||||
|
||||
export async function spawnDockerCommand(
|
||||
command: string,
|
||||
args: string[] = [],
|
||||
message?: string,
|
||||
processEvents: {
|
||||
onExit?: (code: number | null) => void;
|
||||
onError?: (error: Error) => void;
|
||||
onStderr?: (chunk: any) => void;
|
||||
onStdout?: (chunk: any) => void;
|
||||
} = {},
|
||||
) {
|
||||
return await new Promise<boolean>((resolve) => {
|
||||
const { onExit, onError, onStdout, onStderr } = processEvents;
|
||||
const process = spawn('docker', [command, ...args]);
|
||||
process.on('error', (error) => {
|
||||
if (onError) {
|
||||
onError(error);
|
||||
}
|
||||
resolve(false);
|
||||
});
|
||||
process.on('exit', (code) => {
|
||||
if (onExit) {
|
||||
onExit(code);
|
||||
}
|
||||
resolve(code === 0);
|
||||
});
|
||||
|
||||
process.stderr.on('data', (chunk: string) => {
|
||||
if (
|
||||
chunk.includes('docker: unknown command') &&
|
||||
getExtensionSetting('dockerEngineAvailabilityPrompt')
|
||||
) {
|
||||
promptInstallDesktop(message);
|
||||
}
|
||||
if (onStderr) {
|
||||
onStderr(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
if (onStdout) {
|
||||
process.stdout.on('data', (chunk) => {
|
||||
onStdout(chunk);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
target "a" {
|
||||
args = {
|
||||
var = "value"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extensions.ignoreRecommendations": true,
|
||||
"git.autoRepositoryDetection": false,
|
||||
"telemetry.telemetryLevel": "off",
|
||||
"workbench.editor.enablePreview": false,
|
||||
"workbench.secondarySideBar.defaultVisibility": "hidden",
|
||||
"workbench.startupEditor": "none"
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
ARG FOO="init"
|
||||
ARG AAA="init"
|
||||
|
||||
FROM busybox AS build1
|
||||
RUN echo hello > /hello
|
||||
|
||||
FROM busybox AS build2
|
||||
ARG FOO
|
||||
ARG AAA
|
||||
RUN echo hi > /hi && cat /fail
|
||||
|
||||
FROM scratch
|
||||
COPY --from=build1 /hello /
|
||||
RUN cat fail > /
|
||||
COPY --from=build2 /hi /
|
|
@ -5,10 +5,13 @@
|
|||
"lib": ["ES2022"],
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"skipLibCheck": true,
|
||||
"strict": true /* enable all strict type-checking options */
|
||||
/* Additional Checks */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "src/ui-test/resources/**", ".test-extensions"],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
|
@ -12,11 +12,15 @@ const extensionConfig = {
|
|||
target: 'node', // VS Code extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
|
||||
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
|
||||
|
||||
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
entry: {
|
||||
'./extension': './src/extension.ts',
|
||||
'./dockerfile-language-server-nodejs/lib/server':
|
||||
'./node_modules/dockerfile-language-server-nodejs/lib/server.js',
|
||||
}, // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
output: {
|
||||
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'extension.js',
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
},
|
||||
stats: {
|
||||
|
@ -47,6 +51,11 @@ const extensionConfig = {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Unpack UMD module headers used in some modules since webpack doesn't handle them.
|
||||
test: /dockerfile-language-service|vscode-languageserver-types/,
|
||||
use: { loader: 'umd-compat-loader' },
|
||||
},
|
||||
],
|
||||
},
|
||||
devtool: 'nosources-source-map',
|
||||
|
|