Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,12 @@ A pre-configured development environment that includes all tools, extensions, an
### Languages & Runtimes

- Node.js (LTS)
- Python 3.11
- PowerShell 7.x

### CLI Tools

- Git
- GitHub CLI (`gh`)
- Azure CLI (`az`)

### Code Quality

Expand Down Expand Up @@ -93,9 +91,12 @@ gitleaks detect --source . --verbose

## Troubleshooting

**Container won't build**: Ensure Docker Desktop is running and you have sufficient disk space (5GB+).
1. **Container won't build**: Ensure Docker Desktop is running and you have sufficient disk space (5GB+).

**Extensions not loading**: Reload the window (`F1` → **Developer: Reload Window**).
2. **Extensions not loading**: Reload the window (`F1` → **Developer: Reload Window**).

3. **HTTP/TLS errors during build**: Machines with corporate firewalls performing TLS inspection should ensure they are using the default `desktop-linux` builder, which honors OS root certificate trust stores.
You can change the active builder back to `desktop-linux` by running `docker buildx use desktop-linux`.

For more help, see [SUPPORT.md](../SUPPORT.md).

Expand Down
36 changes: 31 additions & 5 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
{
"name": "HVE Core - Markdown Editing",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
// Rename the mount to /workspace for a predictable workspace paths in our scripts.
// The source path might also contain special characters, so it needs escaped double quotes.
"workspaceMount": "\"source=${localWorkspaceFolder}\",target=/workspace,type=bind",
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workspaceMount includes literal quotes around the source= value. Docker’s --mount parser treats those quotes as part of the path, which can cause the bind mount to fail and prevent the devcontainer from starting. Consider removing the embedded quotes and relying on the mount string being passed as a single argument (spaces in paths are already handled).

Suggested change
"workspaceMount": "\"source=${localWorkspaceFolder}\",target=/workspace,type=bind",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",

Copilot uses AI. Check for mistakes.
"workspaceFolder": "/workspace",
"mounts": [
// Put GitHub local user data in a volume
{
"type": "volume",
"source": "${devcontainerId}-userconfig",
"target": "/home/vscode/.config"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this just be the /home/vscode/.config/gh folder?

},
// Put node modules into volume for better performance
{
"type": "volume",
"source": "${devcontainerId}-nodemodules",
"target": "/workspace/node_modules"
}
],
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.11"
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/powershell:1": {}
},
"customizations": {
Expand All @@ -23,9 +37,21 @@
"bierner.markdown-mermaid",
"bpruitt-goddard.mermaid-markdown-syntax-highlighting",
"github.vscode-pull-request-github"
]
],
"settings": {
// Prevent extensions from stealing focus, see microsoft/vscode#205225
"workbench.view.showQuietly": {
"workbench.panel.output": true
}
}
}
},
// This is to ensure support for config includes is properly handled, see microsoft/vscode-remote-release#2084
"initializeCommand": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initializeCommand is exporting every global config key, not just identity fields but you only need: user.name, user.email, user.signingkey, commit.gpgsign, right?

"extractGitGlobals": "(git config -l --global --include || true) > .gitconfig.global",
"extractGitLocals": "(git config -l --local --include || true) > .gitconfig.local"
},
"postAttachCommand": "/bin/bash .devcontainer/scripts/post-attach.sh",
"onCreateCommand": "bash .devcontainer/scripts/on-create.sh",
"postCreateCommand": "bash .devcontainer/scripts/post-create.sh",
"remoteUser": "vscode"
Expand Down
28 changes: 28 additions & 0 deletions .devcontainer/scripts/post-attach.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you set the SPDX and license header?

# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: MIT

set -euo pipefail

Comment on lines +1 to +3
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script doesn’t follow the structure used by the other devcontainer scripts in this repo (header comment + main() entrypoint). For consistency and easier maintenance, consider adding the standard header and wrapping execution in a main() function called at the end (see .devcontainer/scripts/on-create.sh).

Copilot uses AI. Check for mistakes.
# devcontainers copy your local gitconfig but do not parse conditional includes.
# This re-configures the devcontainer git identities based on the prior exported
# global and local git configurations *after* parsing host includes. See also:
# https://github.com/microsoft/vscode-remote-release/issues/2084#issuecomment-2289987894
copy_user_gitconfig() {
for conf in .gitconfig.global .gitconfig.local; do
if [[ -f "$conf" ]]; then
echo "*** Parsing ${conf##.gitconfig.} Git configuration export"
while IFS='=' read -r key value; do
local key value
case "$key" in
user.name | user.email | user.signingkey | commit.gpgsign)
echo "Set Git config ${key}=${value}"
git config --global "$key" "$value"
Comment on lines +12 to +17
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the while read loop, local key value is declared after the variables are populated and is re-declared on every iteration. Consider declaring the locals once at the start of the function (before the loop) and then only assigning within the loop; this avoids confusing scoping and is more ShellCheck-friendly.

Copilot uses AI. Check for mistakes.
;;
esac
done < "$conf"
rm -f "${conf}"
fi
done
}

# Main execution path

copy_user_gitconfig
29 changes: 28 additions & 1 deletion .devcontainer/scripts/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,37 @@

set -euo pipefail

main() {
# Volume ownership is not set automatically due to a bug:
# https://github.com/microsoft/vscode-remote-release/issues/9931
#
# IMPORTANT: workaround requires Docker base image to have password-less sudo.
fix_volume_ownership() {
local volume_path="$1"

if [[ ! -d "$volume_path" ]]; then
echo "ERROR: the volume path provided '$volume_path' does not exist."
exit 1
fi

echo "Setting volume ownership for $volume_path"
Comment on lines +20 to +22
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The volume ownership workaround uses sudo chown without -R and without non-interactive mode. If the volume already contains root-owned files, ownership may remain incorrect; and if sudo ever prompts, postCreateCommand can hang. Consider using recursive ownership and sudo -n (fail fast) for this step.

Copilot uses AI. Check for mistakes.
sudo chown "$USER:$USER" "$volume_path"
}

fix_volume_ownerships() {
echo "Applying volume ownership workaround (see microsoft/vscode-remote-release#9931)..."
fix_volume_ownership "/home/${USER}/.config"
fix_volume_ownership "/workspace/node_modules"
}

npm_install() {
echo "Installing NPM dependencies..."
Comment on lines +30 to 33
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script switches from npm ci to npm install. Since the repo includes a package-lock.json, npm ci is the reproducible and typically faster choice for container provisioning; npm install may modify the lockfile and produce non-deterministic installs. Consider using npm ci here.

Copilot uses AI. Check for mistakes.
npm ci
echo "NPM dependencies installed successfully"
}

main() {
fix_volume_ownerships
npm_install
}

main "$@"
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/.git/
**/node_modules/
10 changes: 9 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
# Set the default behavior, in case core.autocrlf has not been set.
* text=auto

# Declare files that will always have LF line endings on checkout.
# Declare files that must have specific line endings on checkout.
## Windows scripts - must be CRLF
*.ps1 text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf

Comment on lines +6 to +9
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting *.ps1 to eol=crlf will break direct execution on Linux/macOS when scripts rely on their #!/usr/bin/env pwsh shebang (the \r yields /usr/bin/env^M: bad interpreter). Repo docs show running these scripts as ./scripts/.../*.ps1. Consider removing the forced CRLF for *.ps1 (or switching to eol=lf) to keep cross-platform executability.

Suggested change
*.ps1 text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf
*.bat text eol=crlf
*.cmd text eol=crlf
## Cross-platform PowerShell scripts - use LF for shebang compatibility
*.ps1 text eol=lf

Copilot uses AI. Check for mistakes.
## Linux scripts - must be LF
*.sh text eol=lf
*.Dockerfile text eol=lf
Dockerfile* text eol=lf

# Denote all files that are truly binary and should not be modified.
*.docx binary
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,7 @@ pr-reference.xml
.mcp/*-local.json
.mcp/*.local.json
.mcp/.env

# devcontainer
/.gitconfig.global
/.gitconfig.local
Loading