Fix the layer cache model behind slow builds

Review the AI's codeEasy10 min

Your task

An assistant's Dockerfile for a Go service copies the whole source tree before go mod download. CI builds went from 40 seconds to 6 minutes, because a one-line change now downloads every module again. To see what each build order costs, the team models Docker's layer cache.

An assistant wrote rebuilt_step_count(steps, changed_files). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • steps: the build steps in order, one string each, as <op>|<argument>. The ops in use are copy and run. The list can be empty.
  • changed_files: the paths that changed since the last build, such as "cmd/server/main.go". The list can be empty.
  • Return how many steps have to run again, an integer.

Rules the tests check:

  • Split each step at its first |. A step with no | is all op, with an empty argument. Ops are case sensitive.
  • A copy step's argument holds patterns separated by single spaces. Ignore empty patterns.
  • A copy step is stale when any of its patterns matches any changed file:
    • . copies the whole build context, so it matches every file.
    • A pattern that ends in / matches every file whose path starts with that pattern.
    • Any other pattern matches only a file with exactly that path. Matching is case sensitive.
  • With no changed files, no step is stale.
  • A step that is not copy, such as run, is never stale on its own.
  • The cache is a chain: each layer is built on the one before it. Find the first stale copy step. That step and every step after it run again, even a copy whose files did not change. Return that count.
  • With no stale copy step, return 0.

Examples

rebuilt_step_count(steps: list[str], changed_files: list[str]) -> int
Example 1
Inputrebuilt_step_count(["copy|.", "run|go mod download", "run|go build"], ["cmd/server/main.go"])
Output3
Example 2
Inputrebuilt_step_count(["copy|go.mod go.sum", "run|go mod download", "copy|.", "run|go build"], ["cmd/server/main.go"])
Output2
Example 3
Inputrebuilt_step_count(["copy|go.mod go.sum", "run|go mod download", "copy|.", "run|go build"], [])
Output0