Skip to content
Merged
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
14 changes: 13 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"*.meta",
"Samples~/**",
"package-lock.json",
"**/packages-lock.json",
"Library/**",
"Temp/**",
"Logs/**",
Expand All @@ -38,6 +39,7 @@
"words": [
"DxMessaging",
"dxmessaging",
"metas",
"mtimes",
"nofilter",
"relitigate",
Expand Down Expand Up @@ -244,6 +246,7 @@
"Ldstr",
"materialised",
"misaligning",
"monomorphization",
"normalise",
"Normalise",
"normalises",
Expand All @@ -258,7 +261,16 @@
"unmatch",
"unstubbed",
"unparseable",
"entrancy"
"entrancy",
"devirtualization",
"SIGSEGV",
"devirtualize",
"unityci",
"cicd",
"integ",
"Integ",
"jlumbroso",
"kubepods"
],
"ignoreRegExpList": [
"/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g",
Expand Down
132 changes: 103 additions & 29 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# syntax=docker/dockerfile:1.4

# DxMessaging Development Container
# Base image: .NET 9.0 on Debian Bookworm
# Note: .NET 10 SDK is installed alongside .NET 9 to support C# Dev Kit.
# Note: docker-outside-of-docker (DooD) is enabled via devcontainer feature so
# Phase 2+ can spawn ephemeral unityci/editor containers from inside.
FROM mcr.microsoft.com/devcontainers/dotnet:1-9.0-bookworm

# Build argument for target architecture (amd64 or arm64)
Expand All @@ -9,6 +14,8 @@ ARG TARGETARCH=amd64
LABEL org.opencontainers.image.source="https://github.com/wallstop/DxMessaging"
LABEL org.opencontainers.image.description="DxMessaging development container"
LABEL org.opencontainers.image.licenses="MIT"
LABEL unity.support="docker-outside-of-docker"
LABEL unity.note="Unity tests spawn ephemeral unityci/editor containers via DooD"

# Environment variables
ENV DEBIAN_FRONTEND=noninteractive
Expand All @@ -19,30 +26,57 @@ ENV DOTNET_NOLOGO=1
# Fix expired Yarn GPG key issue
# The base image includes the Yarn repository which has an expired signing key.
# Remove it since this project doesn't require Yarn.
# This must run BEFORE the first apt-get update so feature installation does
# not fail on the expired signature.
# ------------------------------------------------------------------------------
RUN rm -f /etc/apt/sources.list.d/yarn.list \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/sources.list.d/yarn.list \
&& rm -f /usr/share/keyrings/yarn-keyring.gpg \
&& rm -f /etc/apt/keyrings/yarn.gpg
&& rm -f /etc/apt/keyrings/yarn.gpg \
&& rm -f /usr/share/keyrings/yarn.gpg \
&& rm -f /etc/apt/trusted.gpg.d/yarn.gpg \
&& find /etc/apt/sources.list.d/ -name "*yarn*" -delete || true

# Install essential APT packages
RUN apt-get update && apt-get install -y --no-install-recommends \
ripgrep \
jq \
htop \
ncdu \
tree \
tldr \
silversearcher-ag \
moreutils \
unzip \
wget \
ca-certificates \
shellcheck \
curl \
gnupg \
apt-transport-https \
software-properties-common \
&& rm -rf /var/lib/apt/lists/*
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y --no-install-recommends \
ripgrep \
jq \
htop \
ncdu \
tree \
tldr \
silversearcher-ag \
moreutils \
unzip \
wget \
ca-certificates \
shellcheck \
curl \
gnupg \
apt-transport-https \
software-properties-common \
&& apt-get autoremove -y

# ------------------------------------------------------------------------------
# Install .NET 10 SDK side-by-side (required by C# Dev Kit extension)
# Unity is targeting .NET Standard 2.1 / .NET 9, so .NET 9 SDK remains primary.
# We install .NET 10 SDK + runtime via the official dotnet-install.sh into a
# shared location so both vscode and root see it on PATH.
# ------------------------------------------------------------------------------
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=tmpfs,target=/tmp \
apt-get update \
&& apt-get -y install --no-install-recommends \
wget \
ca-certificates \
&& wget https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh \
&& chmod +x /tmp/dotnet-install.sh \
&& /tmp/dotnet-install.sh --channel 10.0 --install-dir /usr/share/dotnet \
&& apt-get autoremove -y

# Create a temporary directory for downloads
WORKDIR /tmp/tools
Expand Down Expand Up @@ -301,43 +335,51 @@ RUN set -eux; \
# Install PowerShell
# https://docs.microsoft.com/en-us/powershell/scripting/install/install-debian
# ------------------------------------------------------------------------------
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
set -eux; \
wget -q https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb; \
dpkg -i packages-microsoft-prod.deb; \
rm packages-microsoft-prod.deb; \
apt-get update; \
apt-get install -y powershell; \
rm -rf /var/lib/apt/lists/*; \
apt-get autoremove -y; \
pwsh --version

# ------------------------------------------------------------------------------
# Install Git LFS
# ------------------------------------------------------------------------------
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
set -eux; \
apt-get update; \
apt-get install -y git-lfs; \
git lfs install; \
rm -rf /var/lib/apt/lists/*; \
git lfs install --system; \
apt-get autoremove -y; \
git lfs version

# ------------------------------------------------------------------------------
# Install Python3, pip, and venv
# ------------------------------------------------------------------------------
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
set -eux; \
apt-get update; \
apt-get install -y python3 python3-pip python3-venv; \
rm -rf /var/lib/apt/lists/*; \
apt-get autoremove -y; \
python3 --version; \
pip3 --version

# ------------------------------------------------------------------------------
# Install Node.js LTS via NodeSource
# https://github.com/nodesource/distributions
# ------------------------------------------------------------------------------
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
set -eux; \
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -; \
apt-get install -y nodejs; \
rm -rf /var/lib/apt/lists/*; \
apt-get autoremove -y; \
node --version; \
npm --version

Expand All @@ -354,6 +396,38 @@ RUN pip3 install --no-cache-dir yamllint --break-system-packages && yamllint --v
# ------------------------------------------------------------------------------
RUN pip3 install --no-cache-dir pre-commit --break-system-packages && pre-commit --version

# ------------------------------------------------------------------------------
# Configure Git Defaults for Unity-style Repositories
# ------------------------------------------------------------------------------
# Optimize git for Unity projects with large binary assets and Windows path
# lengths. These mirror the Shiro reference container.
# ------------------------------------------------------------------------------
RUN git config --system core.longpaths true \
&& git config --system core.preloadindex true \
&& git config --system gc.auto 256 \
&& git config --system lfs.concurrenttransfers 10 \
&& git config --system pack.windowMemory 256m \
&& git config --system pack.deltaCacheSize 128m

# ------------------------------------------------------------------------------
# Pre-create volume mount targets with vscode:vscode ownership
# ------------------------------------------------------------------------------
# Docker named volumes copy permissions/contents from the image ONLY on first
# attach (when the volume is empty). Pre-creating these directories with the
# correct ownership ensures the vscode user owns them on first run; rebuilds
# of an existing volume are repaired by post-create.sh / post-start.sh.
#
# Targets here MUST stay aligned with cache-contract.sh (4 entries).
# ------------------------------------------------------------------------------
RUN mkdir -p /home/vscode/.nuget \
&& mkdir -p /home/vscode/.dotnet/tools \
&& mkdir -p /home/vscode/.local/share/powershell \
&& mkdir -p /home/vscode/.cache/pip \
&& chown -R vscode:vscode /home/vscode/.nuget \
&& chown -R vscode:vscode /home/vscode/.dotnet \
&& chown -R vscode:vscode /home/vscode/.local \
&& chown -R vscode:vscode /home/vscode/.cache

# ------------------------------------------------------------------------------
# Configure shell aliases for bash
# ------------------------------------------------------------------------------
Expand Down
79 changes: 79 additions & 0 deletions .devcontainer/cache-contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
# shellcheck shell=bash

# Shared devcontainer cache mount contract.
# Keep these arrays aligned by index: source[i] mounts to target[i].
#
# Entries:
# 1. dxm-nuget-cache -> NuGet package cache for .NET restore
# 2. dxm-dotnet-tools -> Global dotnet tools (csharpier, etc.)
# 3. dxm-powershell-modules -> PowerShell module cache
# 4. dxm-python-cache -> pip wheel/download cache
#
# Unity Library caches are owned by scripts/unity/run-tests.sh and
# scripts/unity/run-tests.ps1 because they must be keyed by Unity image tag and
# test mode. Do not add a static .unity-test-project/Library mount here.

# Re-source guard: this file is sourced by post-create.sh, post-start.sh,
# validate-caching.sh, and (in Phase 4) the contract test harness. Multiple
# sources in the same shell would otherwise re-declare the readonly arrays
# and abort under `set -e`.
[[ "${_DXM_CACHE_CONTRACT_LOADED:-}" == "1" ]] && return 0
_DXM_CACHE_CONTRACT_LOADED=1

readonly CACHE_MOUNT_SOURCES=(
"dxm-nuget-cache"
"dxm-dotnet-tools"
"dxm-powershell-modules"
"dxm-python-cache"
)

readonly CACHE_MOUNT_TARGETS=(
"/home/vscode/.nuget"
"/home/vscode/.dotnet/tools"
"/home/vscode/.local/share/powershell"
"/home/vscode/.cache/pip"
)

cache_contract_validate_shape() {
if [[ "${#CACHE_MOUNT_SOURCES[@]}" -eq 0 ]] \
|| [[ "${#CACHE_MOUNT_TARGETS[@]}" -eq 0 ]] \
|| [[ "${#CACHE_MOUNT_SOURCES[@]}" -ne "${#CACHE_MOUNT_TARGETS[@]}" ]]; then
return 1
fi

return 0
}

cache_contract_get_owner_uid() {
local target="$1"
local owner_uid

if owner_uid="$(stat -c %u "$target" 2>/dev/null)" && [[ "$owner_uid" =~ ^[0-9]+$ ]]; then
echo "$owner_uid"
return 0
fi

if owner_uid="$(stat -f %u "$target" 2>/dev/null)" && [[ "$owner_uid" =~ ^[0-9]+$ ]]; then
echo "$owner_uid"
return 0
fi

return 1
}

cache_contract_is_container_runtime() {
if [[ -f "/.dockerenv" ]]; then
return 0
fi

if [[ "${DEVCONTAINER:-}" == "true" ]] || [[ "${REMOTE_CONTAINERS:-}" == "true" ]]; then
return 0
fi

if grep -qaE '(docker|containerd|kubepods)' /proc/1/cgroup 2>/dev/null; then
return 0
fi

return 1
}
5 changes: 5 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:dbf431d6b42d55cde50fa1df75c7f7c3999a90cde6d73f7a7071174b3c3d0cc4",
"integrity": "sha256:dbf431d6b42d55cde50fa1df75c7f7c3999a90cde6d73f7a7071174b3c3d0cc4"
},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"version": "1.9.1",
"resolved": "ghcr.io/devcontainers/features/docker-outside-of-docker@sha256:dc89605f01ff2f24252c61f7c8ba2a58ccdbc14f2ebf87a7952d9e2b89834850",
"integrity": "sha256:dc89605f01ff2f24252c61f7c8ba2a58ccdbc14f2ebf87a7952d9e2b89834850"
},
"ghcr.io/devcontainers/features/github-cli:1": {
"version": "1.1.0",
"resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671",
Expand Down
Loading
Loading