Compare commits
256 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 |
|
@ -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.
|
|
@ -1,14 +1,70 @@
|
|||
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:
|
||||
test:
|
||||
test-latest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
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'
|
||||
|
||||
- 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:
|
||||
|
@ -16,7 +72,7 @@ jobs:
|
|||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22.x"
|
||||
node-version: '22.x'
|
||||
|
||||
- run: npm install
|
||||
|
||||
|
@ -24,47 +80,49 @@ jobs:
|
|||
|
||||
- run: xvfb-run --auto-servernum --server-args='-screen 0 1920x1080x24' npm test
|
||||
|
||||
build:
|
||||
- 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
|
||||
- test-latest
|
||||
- test-release
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [linux, windows, darwin]
|
||||
arch: [amd64, arm64]
|
||||
os: [alpine, linux, win32, darwin]
|
||||
nodearch: [x64, arm64]
|
||||
include:
|
||||
- arch: amd64
|
||||
nodearch: x64
|
||||
- arch: arm64
|
||||
nodearch: arm64
|
||||
- os: windows
|
||||
- os: win32
|
||||
nodeos: win32
|
||||
ext: .exe
|
||||
- os: darwin
|
||||
nodeos: darwin
|
||||
ext: ""
|
||||
ext: ''
|
||||
- os: linux
|
||||
nodeos: linux
|
||||
ext: ""
|
||||
ext: ''
|
||||
- os: alpine
|
||||
nodeos: linux
|
||||
ext: ''
|
||||
|
||||
steps:
|
||||
- name: actions/checkout@v4 (docker/vscode-extension)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: vscode-extension
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22.x"
|
||||
node-version: '22.x'
|
||||
|
||||
- working-directory: vscode-extension
|
||||
run: |
|
||||
npm install
|
||||
- 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"
|
||||
|
@ -72,44 +130,113 @@ jobs:
|
|||
SHA=$(git rev-parse --short HEAD)
|
||||
echo "SHA=$SHA" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- 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 }}
|
|
@ -7,9 +7,7 @@ node_modules
|
|||
out
|
||||
bin
|
||||
.vscode-test/
|
||||
.test-extensions
|
||||
syntaxes/
|
||||
|
||||
.github/workflows/build.yml
|
||||
|
||||
|
||||
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"
|
||||
},
|
||||
|
|
|
@ -7,6 +7,7 @@ out/**
|
|||
resources/readme/**
|
||||
src/**
|
||||
test/**
|
||||
misc/**
|
||||
.gitignore
|
||||
.yarnrc
|
||||
webpack.config.js
|
||||
|
|
461
CHANGELOG.md
|
@ -2,6 +2,444 @@
|
|||
|
||||
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
|
||||
|
@ -65,7 +503,28 @@ All notable changes to the Docker DX extension will be documented in this file.
|
|||
- error reporting
|
||||
- Compose outline support
|
||||
|
||||
[Unreleased]: https://github.com/docker/vscode-extension/compare/v0.4.1...main
|
||||
[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,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.
|
55
README.md
|
@ -5,21 +5,22 @@ The **Docker DX (Developer Experience)** Visual Studio Code extension enhances y
|
|||
## 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.
|
||||
|
||||
|
@ -29,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.
|
||||
|
@ -45,20 +56,25 @@ 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 develop this extension, you should first make sure you have the following extensions installed:
|
||||
|
||||
- [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
|
||||
|
@ -72,6 +88,29 @@ To debug the VS Code extension, clone this repository and then run `npm install`
|
|||
|
||||
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.
|
||||
|
|
|
@ -47,6 +47,25 @@ async function downloadSyntaxesFile() {
|
|||
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(
|
||||
|
@ -55,13 +74,13 @@ async function downloadLanguageServerBinary() {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const platform = process.platform;
|
||||
const arch = process.arch === 'x64' ? 'amd64' : 'arm64';
|
||||
const suffix = platform === 'win32' ? '.exe' : '';
|
||||
const version = '0.2.0';
|
||||
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}${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);
|
||||
}
|
||||
|
|
|
@ -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 @@
|
|||
{}
|
173
package.json
|
@ -2,8 +2,8 @@
|
|||
"name": "docker",
|
||||
"displayName": "Docker DX",
|
||||
"description": "Edit smarter, ship faster with an enhanced Docker-development experience",
|
||||
"version": "0.4.1",
|
||||
"icon": "resources/docker-logo-vertical-blue.png",
|
||||
"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,7 +48,8 @@
|
|||
"filenames": [
|
||||
"docker-bake.hcl",
|
||||
"docker-bake.override.hcl"
|
||||
]
|
||||
],
|
||||
"configuration": "./configs/dockerbake-language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
|
@ -59,18 +63,113 @@
|
|||
"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.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",
|
||||
|
@ -80,7 +179,11 @@
|
|||
"error",
|
||||
"off"
|
||||
],
|
||||
"default": "all"
|
||||
"default": "all",
|
||||
"tags": [
|
||||
"telemetry",
|
||||
"usesOnlineServices"
|
||||
]
|
||||
},
|
||||
"docker.lsp.debugServerPort": {
|
||||
"type": [
|
||||
|
@ -94,7 +197,42 @@
|
|||
"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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +254,9 @@
|
|||
"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": {
|
||||
|
@ -135,7 +275,8 @@
|
|||
"prettier": "^3.5.3",
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vscode-extension-tester": "^8.13.0",
|
||||
"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,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
353
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,59 +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');
|
||||
recordVersionTelemetry(configValue, 'force');
|
||||
activateExtension(ctx);
|
||||
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';
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
@ -181,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),
|
||||
|
@ -195,10 +290,16 @@ function listenForConfigurationChanges(ctx: vscode.ExtensionContext) {
|
|||
);
|
||||
}
|
||||
|
||||
function recordVersionTelemetry(
|
||||
featureFlag: string | undefined,
|
||||
featureFlagValue: string,
|
||||
) {
|
||||
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) => {
|
||||
|
@ -209,25 +310,31 @@ function recordVersionTelemetry(
|
|||
});
|
||||
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();
|
||||
|
@ -235,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(' ');
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
import {
|
||||
BottomBarPanel,
|
||||
EditorView,
|
||||
MarkerType,
|
||||
ProblemsView,
|
||||
VSBrowser,
|
||||
} from 'vscode-extension-tester';
|
||||
import * as path from 'path';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('Docker Bake', function () {
|
||||
let bottomBar: BottomBarPanel;
|
||||
|
||||
before(async function () {
|
||||
bottomBar = new BottomBarPanel();
|
||||
await bottomBar.toggle(true);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await bottomBar.toggle(false);
|
||||
});
|
||||
|
||||
describe('Problems', function () {
|
||||
let view: ProblemsView;
|
||||
|
||||
async function problemsExist(view: ProblemsView) {
|
||||
const markers = await view.getAllVisibleMarkers(MarkerType.Any);
|
||||
return markers.length > 0;
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
|
||||
view = await bottomBar.openProblemsView();
|
||||
|
||||
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-language-server",
|
||||
);
|
||||
});
|
||||
|
||||
it('Bake file has no warnings', async function () {
|
||||
const warnings = await view.getAllVisibleMarkers(MarkerType.Warning);
|
||||
expect(warnings).is.empty;
|
||||
});
|
||||
});
|
||||
});
|
|
@ -10,12 +10,21 @@ import * as fs from 'fs';
|
|||
import * as path from 'path';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('Dockerfile', function () {
|
||||
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 () {
|
||||
|
@ -24,18 +33,11 @@ describe('Dockerfile', function () {
|
|||
|
||||
describe('Problems', function () {
|
||||
let editorView: EditorView;
|
||||
let view: ProblemsView;
|
||||
|
||||
async function problemsExist(view: ProblemsView) {
|
||||
const markers = await view.getAllVisibleMarkers(MarkerType.Any);
|
||||
return markers.length > 0;
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
|
||||
editorView = new EditorView();
|
||||
view = await bottomBar.openProblemsView();
|
||||
|
||||
const dockerfilePath = path.join('test', 'resources', 'Dockerfile');
|
||||
fs.writeFileSync(dockerfilePath, 'FROM scratch\nENTRYPOINT ""\n');
|
||||
|
@ -65,7 +67,7 @@ describe('Dockerfile', function () {
|
|||
|
||||
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-language-server',
|
||||
'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)',
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -86,10 +88,43 @@ describe('Dockerfile', function () {
|
|||
|
||||
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-language-server",
|
||||
"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,16 +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 = {
|
||||
dockerfileExperimental: {
|
||||
removeOverlappingIssues: true,
|
||||
dockercomposeExperimental: {
|
||||
composeSupport: extensionConfiguration.get<boolean>(
|
||||
'enableComposeLanguageServer',
|
||||
),
|
||||
},
|
||||
dockerfileExperimental: { removeOverlappingIssues },
|
||||
telemetry: getTelemetryValue(dockerConfiguration.get('telemetry')),
|
||||
};
|
||||
params.capabilities.experimental = {
|
||||
|
@ -37,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,
|
||||
});
|
||||
|
@ -54,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,
|
||||
});
|
||||
|
@ -76,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);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -3,5 +3,6 @@
|
|||
"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 /
|
|
@ -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',
|
||||
|
|