From 911755bf4981a3137f2401b90774179ab3bfcc2e Mon Sep 17 00:00:00 2001
From: libmartinito <lib.martinito@pm.me>
Date: Fri, 28 Jun 2024 23:45:17 +0800
Subject: [PATCH] CC-1333 Add repository aware caching

---
 dockerfiles/bun-1.1.Dockerfile     |  9 ++++++---
 dockerfiles/dotnet-6.0.Dockerfile  |  8 ++++++--
 dockerfiles/dotnet-8.0.Dockerfile  |  8 ++++++--
 dockerfiles/go-1.19.Dockerfile     |  7 ++++++-
 dockerfiles/go-1.21.Dockerfile     |  7 ++++++-
 dockerfiles/go-1.22.Dockerfile     |  7 ++++++-
 dockerfiles/haskell-9.4.Dockerfile | 10 ++++++----
 dockerfiles/java-21.Dockerfile     |  8 ++++++--
 dockerfiles/nodejs-21.Dockerfile   |  8 ++++++--
 dockerfiles/python-3.11.Dockerfile |  9 ++++++---
 dockerfiles/python-3.12.Dockerfile |  8 ++++++--
 dockerfiles/ruby-3.3.Dockerfile    |  8 ++++++--
 dockerfiles/rust-1.70.Dockerfile   |  8 ++++++--
 dockerfiles/rust-1.76.Dockerfile   |  8 ++++++--
 14 files changed, 84 insertions(+), 29 deletions(-)

diff --git a/dockerfiles/bun-1.1.Dockerfile b/dockerfiles/bun-1.1.Dockerfile
index e7c66e3..f99f8d7 100644
--- a/dockerfiles/bun-1.1.Dockerfile
+++ b/dockerfiles/bun-1.1.Dockerfile
@@ -1,11 +1,12 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM oven/bun:1.1.4-alpine
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="package.json,bun.lockb"
 
 WORKDIR /app
 
-COPY package.json ./
-COPY bun.lockb ./
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # For reproducible builds.
 # This will install the exact versions of each package specified in the lockfile.
@@ -14,4 +15,6 @@ RUN bun install --frozen-lockfile
 
 RUN mkdir -p /app-cached
 # If the node_modules directory exists, move it to /app-cached
-RUN if [ -d "/app/node_modules" ]; then mv /app/node_modules /app-cached; fi
\ No newline at end of file
+RUN if [ -d "/app/node_modules" ]; then mv /app/node_modules /app-cached; fi
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/dotnet-6.0.Dockerfile b/dockerfiles/dotnet-6.0.Dockerfile
index 2349e09..05facb3 100644
--- a/dockerfiles/dotnet-6.0.Dockerfile
+++ b/dockerfiles/dotnet-6.0.Dockerfile
@@ -1,12 +1,13 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim
 
-COPY codecrafters-http-server.csproj /app/codecrafters-http-server.csproj
-COPY codecrafters-http-server.sln /app/codecrafters-http-server.sln
 
 RUN mkdir /app/src
 RUN (echo 'System.Console.WriteLine("If you are seeing this, there is something wrong with our caching mechanism! Please contact us at hello@codecrafters.io.");' > /app/src/Program.cs) > /dev/null
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # This saves nuget packages to ~/.nuget
 RUN dotnet build --configuration Release .
@@ -22,3 +23,6 @@ RUN echo "cd \${CODECRAFTERS_SUBMISSION_DIR} && dotnet build --configuration Rel
 RUN chmod +x /codecrafters-precompile.sh
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="codecrafters-http-server.csproj,codecrafters-http-server.sln"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/dotnet-8.0.Dockerfile b/dockerfiles/dotnet-8.0.Dockerfile
index c6de5ca..856f625 100644
--- a/dockerfiles/dotnet-8.0.Dockerfile
+++ b/dockerfiles/dotnet-8.0.Dockerfile
@@ -1,12 +1,13 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine
 
-COPY codecrafters-http-server.csproj /app/codecrafters-http-server.csproj
-COPY codecrafters-http-server.sln /app/codecrafters-http-server.sln
 
 RUN mkdir /app/src
 RUN (echo 'System.Console.WriteLine("If you are seeing this, there is something wrong with our caching mechanism! Please contact us at hello@codecrafters.io.");' > /app/src/Program.cs) > /dev/null
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # This saves nuget packages to ~/.nuget
 RUN dotnet build --configuration Release .
@@ -22,3 +23,6 @@ RUN echo "cd \${CODECRAFTERS_SUBMISSION_DIR} && dotnet build --configuration Rel
 RUN chmod +x /codecrafters-precompile.sh
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="codecrafters-http-server.csproj,codecrafters-http-server.sln"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/go-1.19.Dockerfile b/dockerfiles/go-1.19.Dockerfile
index 23ced9c..145398d 100644
--- a/dockerfiles/go-1.19.Dockerfile
+++ b/dockerfiles/go-1.19.Dockerfile
@@ -1,9 +1,14 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM golang:1.19-alpine
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="go.mod,go.sum"
 
 WORKDIR /app
 
-COPY go.mod go.sum ./
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 RUN ash -c "set -exo pipefail; go mod graph | awk '{if (\$1 !~ \"@\") {print \$2}}' | xargs -r go get"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/go-1.21.Dockerfile b/dockerfiles/go-1.21.Dockerfile
index d92cb87..c883c1c 100644
--- a/dockerfiles/go-1.21.Dockerfile
+++ b/dockerfiles/go-1.21.Dockerfile
@@ -1,13 +1,18 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM golang:1.21-alpine
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="go.mod,go.sum"
 
 WORKDIR /app
 
-COPY go.mod go.sum ./
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # Starting from Go 1.20, the go standard library is no loger compiled
 # setting the GODEBUG environment to "installgoroot=all" restores the old behavior
 RUN GODEBUG="installgoroot=all" go install std
 
 RUN ash -c "set -exo pipefail; go mod graph | awk '{if (\$1 !~ \"@\") {print \$2}}' | xargs -r go get"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/go-1.22.Dockerfile b/dockerfiles/go-1.22.Dockerfile
index ec4d2bd..85cb5ca 100644
--- a/dockerfiles/go-1.22.Dockerfile
+++ b/dockerfiles/go-1.22.Dockerfile
@@ -1,13 +1,18 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM golang:1.22-alpine
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="go.mod,go.sum"
 
 WORKDIR /app
 
-COPY go.mod go.sum ./
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # Starting from Go 1.20, the go standard library is no loger compiled
 # setting the GODEBUG environment to "installgoroot=all" restores the old behavior
 RUN GODEBUG="installgoroot=all" go install std
 
 RUN ash -c "set -exo pipefail; go mod graph | awk '{if (\$1 !~ \"@\") {print \$2}}' | xargs -r go get"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/haskell-9.4.Dockerfile b/dockerfiles/haskell-9.4.Dockerfile
index 9fd86be..2244b25 100644
--- a/dockerfiles/haskell-9.4.Dockerfile
+++ b/dockerfiles/haskell-9.4.Dockerfile
@@ -1,3 +1,4 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM haskell:9.4.6-buster
 
 WORKDIR /app
@@ -11,13 +12,11 @@ RUN echo "allow-different-user: true" >> /etc/stack/config.yaml
 RUN echo "install-ghc: false" >> /etc/stack/config.yaml
 RUN echo "system-ghc: true" >> /etc/stack/config.yaml
 
-COPY stack.yaml package.yaml stack.yaml.lock /app/
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # Dummy static content to circumvent the /app doesn't exist warning
 RUN mkdir /app/src
-RUN mkdir /app/app
-RUN echo 'main :: IO ()' >> /app/app/Main.hs
-RUN echo 'main = putStrLn "Hello, World!"' >> /app/app/Main.hs
 
 RUN stack build
 RUN stack clean hs-http-server-clone
@@ -30,3 +29,6 @@ RUN echo "cd \${CODECRAFTERS_SUBMISSION_DIR} && cp -r /tmp/.stack-work . && stac
 RUN chmod +x /codecrafters-precompile.sh
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="stack.yaml,package.yaml,stack.yaml.lock"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/java-21.Dockerfile b/dockerfiles/java-21.Dockerfile
index 1472cf7..e72d4da 100644
--- a/dockerfiles/java-21.Dockerfile
+++ b/dockerfiles/java-21.Dockerfile
@@ -1,8 +1,10 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM maven:3.9.5-eclipse-temurin-21-alpine
 
-COPY pom.xml /app/pom.xml
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # Download the dependencies
 RUN mvn -B package -Ddir=/tmp/codecrafters-http-target
@@ -13,4 +15,6 @@ RUN mv /app/target /app-cached # Is this needed?
 
 # Pre-compile steps
 RUN printf "cd \${CODECRAFTERS_SUBMISSION_DIR} && mvn -B package -Ddir=/tmp/codecrafters-http-target && sed -i 's/^\(mvn .*\)/#\1/' ./your_server.sh" > /codecrafters-precompile.sh
-RUN chmod +x /codecrafters-precompile.sh
\ No newline at end of file
+RUN chmod +x /codecrafters-precompile.sh
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/nodejs-21.Dockerfile b/dockerfiles/nodejs-21.Dockerfile
index 435b41e..8f634f5 100644
--- a/dockerfiles/nodejs-21.Dockerfile
+++ b/dockerfiles/nodejs-21.Dockerfile
@@ -1,11 +1,12 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM node:21.7-alpine3.19
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="package.json,package-lock.json"
 
 WORKDIR /app
 
-COPY package.json ./
-COPY package-lock.json ./
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 # If dependencies in the package lock do not match those in package.json, instead of updating the package lock, npm ci will exit with an error. 
 RUN npm ci
@@ -13,3 +14,6 @@ RUN npm ci
 RUN mkdir -p /app-cached
 # If the node_modules directory exists, move it to /app-cached
 RUN if [ -d "/app/node_modules" ]; then mv /app/node_modules /app-cached; fi
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/python-3.11.Dockerfile b/dockerfiles/python-3.11.Dockerfile
index f24b4d0..715148d 100644
--- a/dockerfiles/python-3.11.Dockerfile
+++ b/dockerfiles/python-3.11.Dockerfile
@@ -1,11 +1,12 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM python:3.11-alpine
 
 RUN pip install --no-cache-dir "pipenv>=2023.12.1"
 
-COPY Pipfile /app/Pipfile
-COPY Pipfile.lock /app/Pipfile.lock
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 ENV WORKON_HOME=/venvs
 
@@ -14,4 +15,6 @@ RUN pipenv install
 # Force environment creation
 RUN pipenv run python3 -c "1+1"
 
-ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Pipfile,Pipfile.lock"
\ No newline at end of file
+ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Pipfile,Pipfile.lock"
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/python-3.12.Dockerfile b/dockerfiles/python-3.12.Dockerfile
index 9d4f14c..45c632b 100644
--- a/dockerfiles/python-3.12.Dockerfile
+++ b/dockerfiles/python-3.12.Dockerfile
@@ -1,11 +1,12 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM python:3.12-alpine
 
 RUN pip install --no-cache-dir "pipenv>=2023.12.1"
 
-COPY Pipfile /app/Pipfile
-COPY Pipfile.lock /app/Pipfile.lock
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 
 ENV WORKON_HOME=/venvs
 
@@ -15,3 +16,6 @@ RUN pipenv install
 RUN pipenv run python3 -c "1+1"
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Pipfile,Pipfile.lock"
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/ruby-3.3.Dockerfile b/dockerfiles/ruby-3.3.Dockerfile
index 37ff3fb..c1e53b7 100644
--- a/dockerfiles/ruby-3.3.Dockerfile
+++ b/dockerfiles/ruby-3.3.Dockerfile
@@ -1,7 +1,11 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM ruby:3.3-alpine
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Gemfile,Gemfile.lock"
 WORKDIR /app
 
-COPY Gemfile Gemfile.lock ./
-RUN bundle install --verbose
\ No newline at end of file
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
+RUN bundle install --verbose
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/rust-1.70.Dockerfile b/dockerfiles/rust-1.70.Dockerfile
index a94042d..8e2c4b8 100644
--- a/dockerfiles/rust-1.70.Dockerfile
+++ b/dockerfiles/rust-1.70.Dockerfile
@@ -1,12 +1,13 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM rust:1.70-buster
 
-COPY Cargo.toml /app/Cargo.toml
-COPY Cargo.lock /app/Cargo.lock
 
 RUN mkdir /app/src
 RUN echo 'fn main() { println!("Hello World!"); }' > /app/src/main.rs
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 RUN cargo build --release --target-dir=/tmp/codecrafters-http-server-target
 
 RUN cargo clean -p http-server-starter-rust --release --target-dir=/tmp/codecrafters-http-server-target
@@ -18,3 +19,6 @@ RUN chmod +x /codecrafters-precompile.sh
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Cargo.toml,Cargo.lock"
 
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app
diff --git a/dockerfiles/rust-1.76.Dockerfile b/dockerfiles/rust-1.76.Dockerfile
index 784fd0d..f2b3bc3 100644
--- a/dockerfiles/rust-1.76.Dockerfile
+++ b/dockerfiles/rust-1.76.Dockerfile
@@ -1,12 +1,13 @@
+# syntax=docker/dockerfile:1.7-labs
 FROM rust:1.76-buster
 
-COPY Cargo.toml /app/Cargo.toml
-COPY Cargo.lock /app/Cargo.lock
 
 RUN mkdir /app/src
 RUN echo 'fn main() { println!("Hello World!"); }' > /app/src/main.rs
 
 WORKDIR /app
+# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses
+COPY --exclude=.git --exclude=README.md . /app
 RUN cargo build --release --target-dir=/tmp/codecrafters-http-server-target
 
 RUN cargo clean -p http-server-starter-rust --release --target-dir=/tmp/codecrafters-http-server-target
@@ -18,3 +19,6 @@ RUN chmod +x /codecrafters-precompile.sh
 
 ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="Cargo.toml,Cargo.lock"
 
+
+# Once the heave steps are done, we can copy all files back
+COPY . /app