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
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.git
**/node_modules
**/obj
**/bin
**/dist
TestResults
artifacts
*.tar
.copilot
.buildkit-cache
scratch
47 changes: 40 additions & 7 deletions .github/workflows/Build-Test-And-Deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ jobs:
build-and-test:
runs-on: ubuntu-latest
environment: "BuildAndUploadImage"
permissions:
actions: write # required for docker/build-push-action GHA cache writes
Comment thread
BenjaminMichaelis marked this conversation as resolved.
contents: read

steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -49,6 +52,35 @@ jobs:

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
id: setup-buildx

- name: Cache Docker build mounts (main)
if: github.ref == 'refs/heads/main'
uses: actions/cache@v5
id: cache-mounts-main
with:
path: .buildkit-cache
key: buildkit-cache-${{ hashFiles('Dockerfile', 'Directory.Packages.props', 'NuGet.config', 'src/**/package-lock.json') }}
restore-keys: |
buildkit-cache-

- name: Restore Docker build mounts (PR)
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
uses: actions/cache/restore@v5
id: cache-mounts-pr
with:
path: .buildkit-cache
key: buildkit-cache-${{ hashFiles('Dockerfile', 'Directory.Packages.props', 'NuGet.config', 'src/**/package-lock.json') }}
restore-keys: |
buildkit-cache-

- name: Inject Docker cache mounts
uses: reproducible-containers/buildkit-cache-dance@v3
with:
builder: ${{ steps.setup-buildx.outputs.name }}
cache-dir: .buildkit-cache
dockerfile: Dockerfile
skip-extraction: ${{ github.ref != 'refs/heads/main' || steps.cache-mounts-main.outputs.cache-hit == 'true' }}

# Build but no push with a PR
- name: Docker build (no push)
Expand All @@ -58,21 +90,22 @@ jobs:
push: false
tags: temp-pr-validation
file: ./Dockerfile
cache-from: type=gha,scope=try-main

# Only build for dev registry — prod gets the image via az acr import in deploy-production
# Only build for dev registry — prod gets the image via az acr import in deploy-production
- name: Build Container Image
if: github.event_name != 'pull_request_target' && github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main'
uses: docker/build-push-action@v7
with:
tags: ${{ vars.DEVCONTAINER_REGISTRY }}/try:${{ github.sha }},${{ vars.DEVCONTAINER_REGISTRY }}/try:latest
file: ./Dockerfile
context: .
outputs: type=docker,dest=${{ github.workspace }}/tryimage.tar
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from: type=gha,scope=try-main
cache-to: type=gha,mode=max,scope=try-main

- name: Upload artifact
if: github.event_name != 'pull_request_target' && github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v7.0.1
with:
name: tryimage
Expand Down Expand Up @@ -138,7 +171,7 @@ jobs:
artifact-name: 'integration-test-playlists'

deploy-development:
if: github.event_name != 'pull_request_target' && github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: [build-and-test, build-and-test-windows, integration-tests]
concurrency:
Expand Down Expand Up @@ -189,7 +222,7 @@ jobs:
--image "${{ vars.DEVCONTAINER_REGISTRY }}/try:${{ github.sha }}"

deploy-production:
if: github.event_name != 'pull_request_target' && github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: deploy-development
concurrency:
Expand Down
59 changes: 41 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,50 @@
# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/sdk:10.0-azurelinux3.0 AS build-env
WORKDIR /App

# Copy everything
COPY . ./

# Make sure we run bash
CMD ["bash"]

# Make sure we get all the updates and tools we need to build
RUN tdnf install gawk -y
# This is Node v16. For 18, use nodejs18.
RUN tdnf install nodejs -y
RUN tdnf install npm -y
RUN tdnf clean all
# Install all required build tools in a single layer (rarely changes — stays cached)
# This is Node v16. For 18, use nodejs18.
RUN --mount=type=cache,id=try-tdnf,target=/var/cache/tdnf,sharing=locked \
tdnf install -y gawk nodejs npm

# Copy only the files needed to restore dependencies.
# These layers are cached until a manifest file changes, so routine source edits
# don't re-run the expensive restore steps below.
COPY NuGet.config global.json Directory.Build.props Directory.Build.targets Directory.Packages.props TryDotNet.sln ./
COPY eng/ ./eng/

# .csproj files — one COPY per project to preserve directory structure
COPY src/Microsoft.TryDotNet/Microsoft.TryDotNet.csproj src/Microsoft.TryDotNet/
COPY src/Microsoft.TryDotNet.FileIntegration.Tests/Microsoft.TryDotNet.FileIntegration.Tests.csproj src/Microsoft.TryDotNet.FileIntegration.Tests/
COPY src/Microsoft.TryDotNet.IntegrationTests/Microsoft.TryDotNet.IntegrationTests.csproj src/Microsoft.TryDotNet.IntegrationTests/
COPY src/Microsoft.TryDotNet.SimulatorGenerator/Microsoft.TryDotNet.SimulatorGenerator.csproj src/Microsoft.TryDotNet.SimulatorGenerator/
COPY src/Microsoft.TryDotNet.Tests/Microsoft.TryDotNet.Tests.csproj src/Microsoft.TryDotNet.Tests/
COPY src/Microsoft.TryDotNet.WasmRunner/Microsoft.TryDotNet.WasmRunner.csproj src/Microsoft.TryDotNet.WasmRunner/

# Build javascript library
RUN /App/build-js.sh
# npm manifests
COPY src/microsoft-trydotnet/package.json src/microsoft-trydotnet/package-lock.json src/microsoft-trydotnet/
COPY src/microsoft-trydotnet-editor/package.json src/microsoft-trydotnet-editor/package-lock.json src/microsoft-trydotnet-editor/
COPY src/microsoft-trydotnet-styles/package.json src/microsoft-trydotnet-styles/package-lock.json src/microsoft-trydotnet-styles/
COPY src/microsoft-learn-mock/package.json src/microsoft-learn-mock/package-lock.json src/microsoft-learn-mock/

# Restore NuGet packages. The cache mount persists the package cache across local
# builds; in CI the layer itself is cached by the GHA cache backend.
RUN --mount=type=cache,id=try-nuget,target=/root/.nuget/packages \
dotnet restore --configfile /App/NuGet.config /App/TryDotNet.sln

# Copy all remaining source (changes frequently — only layers below rebuild on edits)
COPY . ./

# Restore
RUN dotnet restore --configfile /App/NuGet.config /App/TryDotNet.sln
# Build javascript library. The npm cache mount speeds up repeated local builds.
RUN --mount=type=cache,id=try-npm,target=/root/.npm \
/App/build-js.sh

# Build and publish a release
RUN dotnet publish -c Release -o out /App/src/Microsoft.TryDotNet
# Publish only what we deploy
RUN --mount=type=cache,id=try-nuget,target=/root/.nuget/packages \
dotnet publish -c Release --no-restore -o out /App/src/Microsoft.TryDotNet

# Build runtime image
FROM mcr.microsoft.com/dotnet/sdk:10.0-azurelinux3.0
Expand All @@ -31,9 +54,9 @@ WORKDIR /App
# Make sure we run bash
CMD ["bash"]

# Make sure we get all the tools we need
RUN tdnf install procps -y
RUN tdnf clean all
# Install runtime tools in a single layer
RUN --mount=type=cache,id=try-tdnf,target=/var/cache/tdnf,sharing=locked \
tdnf install -y procps

# Copy from build image
COPY --from=build-env /App/out .
Expand Down
Loading