@@ -33,6 +33,25 @@ SHELL := bash
3333 coderd/database/unique_constraint.go \
3434 coderd/database/dbmetrics/querymetrics.go \
3535 coderd/database/dbauthz/dbauthz.go \
36+ coderd/database/dbmock/dbmock.go \
37+ coderd/database/pubsub/psmock/psmock.go \
38+ agent/agentcontainers/acmock/acmock.go \
39+ coderd/httpmw/loggermw/loggermock/loggermock.go \
40+ codersdk/workspacesdk/agentconnmock/agentconnmock.go \
41+ tailnet/tailnettest/coordinatormock.go \
42+ tailnet/tailnettest/coordinateemock.go \
43+ tailnet/tailnettest/workspaceupdatesprovidermock.go \
44+ tailnet/tailnettest/subscriptionmock.go \
45+ enterprise/aibridged/aibridgedmock/clientmock.go \
46+ enterprise/aibridged/aibridgedmock/poolmock.go \
47+ tailnet/proto/tailnet.pb.go \
48+ agent/proto/agent.pb.go \
49+ agent/agentsocket/proto/agentsocket.pb.go \
50+ agent/boundarylogproxy/codec/boundary.pb.go \
51+ provisionersdk/proto/provisioner.pb.go \
52+ provisionerd/proto/provisionerd.pb.go \
53+ vpn/vpn.pb.go \
54+ enterprise/aibridged/proto/aibridged.pb.go \
3655 site/src/api/typesGenerated.ts \
3756 site/e2e/provisionerGenerated.ts \
3857 site/src/api/chatModelOptionsGenerated.json \
@@ -50,6 +69,23 @@ SHELL := bash
5069 codersdk/rbacresources_gen.go \
5170 codersdk/apikey_scopes_gen.go
5271
72+ # atomic_write runs a command, captures stdout into a temp file, and
73+ # atomically replaces $@. An optional second argument is a formatting
74+ # command that receives the temp file path as its argument.
75+ # Usage: $(call atomic_write,GENERATE_CMD[,FORMAT_CMD])
76+ define atomic_write
77+ tmpdir=$$(mktemp -d -p _gen ) && tmpfile=$$(realpath "$$tmpdir") /$(notdir $@ ) && \
78+ $(1 ) > "$$tmpfile" && \
79+ $(if $(2 ) ,$(2 ) "$$tmpfile" &&) \
80+ mv "$$tmpfile" "$@ " && rm -rf "$$tmpdir"
81+ endef
82+
83+ # Shared temp directory for atomic writes. Lives at the project root
84+ # so all targets share the same filesystem, and is gitignored.
85+ # Order-only prerequisite: recipes that need it depend on | _gen
86+ _gen :
87+ mkdir -p _gen
88+
5389# Don't print the commands in the file unless you specify VERBOSE. This is
5490# essentially the same as putting "@" at the start of each line.
5591ifndef VERBOSE
@@ -822,172 +858,150 @@ $(TAILNETTEST_MOCKS): tailnet/coordinator.go tailnet/service.go
822858 touch " $@ "
823859
824860tailnet/proto/tailnet.pb.go : tailnet/proto/tailnet.proto
825- protoc \
861+ ./scripts/atomic_protoc.sh \
826862 --go_out=. \
827863 --go_opt=paths=source_relative \
828864 --go-drpc_out=. \
829865 --go-drpc_opt=paths=source_relative \
830866 ./tailnet/proto/tailnet.proto
831867
832868agent/proto/agent.pb.go : agent/proto/agent.proto
833- protoc \
869+ ./scripts/atomic_protoc.sh \
834870 --go_out=. \
835871 --go_opt=paths=source_relative \
836872 --go-drpc_out=. \
837873 --go-drpc_opt=paths=source_relative \
838874 ./agent/proto/agent.proto
839875
840876agent/agentsocket/proto/agentsocket.pb.go : agent/agentsocket/proto/agentsocket.proto agent/proto/agent.proto
841- protoc \
877+ ./scripts/atomic_protoc.sh \
842878 --go_out=. \
843879 --go_opt=paths=source_relative \
844880 --go-drpc_out=. \
845881 --go-drpc_opt=paths=source_relative \
846882 ./agent/agentsocket/proto/agentsocket.proto
847883
848884provisionersdk/proto/provisioner.pb.go : provisionersdk/proto/provisioner.proto
849- protoc \
885+ ./scripts/atomic_protoc.sh \
850886 --go_out=. \
851887 --go_opt=paths=source_relative \
852888 --go-drpc_out=. \
853889 --go-drpc_opt=paths=source_relative \
854890 ./provisionersdk/proto/provisioner.proto
855891
856892provisionerd/proto/provisionerd.pb.go : provisionerd/proto/provisionerd.proto
857- protoc \
893+ ./scripts/atomic_protoc.sh \
858894 --go_out=. \
859895 --go_opt=paths=source_relative \
860896 --go-drpc_out=. \
861897 --go-drpc_opt=paths=source_relative \
862898 ./provisionerd/proto/provisionerd.proto
863899
864900vpn/vpn.pb.go : vpn/vpn.proto
865- protoc \
901+ ./scripts/atomic_protoc.sh \
866902 --go_out=. \
867903 --go_opt=paths=source_relative \
868904 ./vpn/vpn.proto
869905
870906agent/boundarylogproxy/codec/boundary.pb.go : agent/boundarylogproxy/codec/boundary.proto agent/proto/agent.proto
871- protoc \
907+ ./scripts/atomic_protoc.sh \
872908 --go_out=. \
873909 --go_opt=paths=source_relative \
874910 ./agent/boundarylogproxy/codec/boundary.proto
875911
876912enterprise/aibridged/proto/aibridged.pb.go : enterprise/aibridged/proto/aibridged.proto
877- protoc \
913+ ./scripts/atomic_protoc.sh \
878914 --go_out=. \
879915 --go_opt=paths=source_relative \
880916 --go-drpc_out=. \
881917 --go-drpc_opt=paths=source_relative \
882918 ./enterprise/aibridged/proto/aibridged.proto
883919
884- site/src/api/typesGenerated.ts : site/node_modules/.installed $(wildcard scripts/apitypings/* ) $(shell find ./codersdk $(FIND_EXCLUSIONS ) -type f -name '* .go')
885- # Generate to a temp file, format it, then atomically move to
886- # the target so that an interrupt never leaves a partial or
887- # unformatted file in the working tree.
888- tmpfile=$$(mktemp -d ) /$(notdir $@ ) && \
889- go run -C ./scripts/apitypings main.go > " $$ tmpfile" && \
890- ./scripts/biome_format.sh " $$ tmpfile" && \
891- mv " $$ tmpfile" " $@ "
920+ site/src/api/typesGenerated.ts : site/node_modules/.installed $(wildcard scripts/apitypings/* ) $(shell find ./codersdk $(FIND_EXCLUSIONS ) -type f -name '* .go') | _gen
921+ $(call atomic_write,go run -C ./scripts/apitypings main.go,./scripts/biome_format.sh)
892922
893923site/e2e/provisionerGenerated.ts : site/node_modules/.installed provisionerd/proto/provisionerd.pb.go provisionersdk/proto/provisioner.pb.go
894924 (cd site/ && pnpm run gen:provisioner)
895925 touch " $@ "
896926
897- site/src/theme/icons.json : site/node_modules/.installed $(wildcard scripts/gensite/* ) $(wildcard site/static/icon/* )
898- tmpfile =$$(mktemp -d ) /$(notdir $@ ) && \
927+ site/src/theme/icons.json : site/node_modules/.installed $(wildcard scripts/gensite/* ) $(wildcard site/static/icon/* ) | _gen
928+ tmpdir =$$(mktemp -d -p _gen ) && tmpfile= $$( realpath "$$tmpdir" ) /$(notdir $@ ) && \
899929 go run ./scripts/gensite/ -icons " $$ tmpfile" && \
900930 ./scripts/biome_format.sh " $$ tmpfile" && \
901- mv " $$ tmpfile" " $@ "
931+ mv " $$ tmpfile" " $@ " && rm -rf " $$ tmpdir "
902932
903- examples/examples.gen.json : scripts/examplegen/main.go examples/examples.go $(shell find ./examples/templates)
904- go run ./scripts/examplegen/main.go > " $@ .tmp " && mv " $@ .tmp " " $@ "
933+ examples/examples.gen.json : scripts/examplegen/main.go examples/examples.go $(shell find ./examples/templates) | _gen
934+ $( call atomic_write, go run ./scripts/examplegen/main.go)
905935
906- coderd/rbac/object_gen.go : scripts/typegen/rbacobject.gotmpl scripts/typegen/main.go coderd/rbac/object.go coderd/rbac/policy/policy.go
907- tempdir=$(shell mktemp -d /tmp/typegen_rbac_object.XXXXXX)
908- go run ./scripts/typegen/main.go rbac object > " $$ tempdir/object_gen.go"
909- mv -v " $$ tempdir/object_gen.go" coderd/rbac/object_gen.go
910- rmdir -v " $$ tempdir"
936+ coderd/rbac/object_gen.go : scripts/typegen/rbacobject.gotmpl scripts/typegen/main.go coderd/rbac/object.go coderd/rbac/policy/policy.go | _gen
937+ $(call atomic_write,go run ./scripts/typegen/main.go rbac object)
911938 touch " $@ "
912939
913940# NOTE: depends on object_gen.go because `go run` compiles
914941# coderd/rbac which includes it.
915942coderd/rbac/scopes_constants_gen.go : scripts/typegen/scopenames.gotmpl scripts/typegen/main.go coderd/rbac/policy/policy.go \
916- coderd/rbac/object_gen.go
917- # Generate typed low-level ScopeName constants from RBACPermissions
918- # Write to a temp file first to avoid truncating the package during build
919- # since the generator imports the rbac package.
920- tempfile=$(shell mktemp /tmp/scopes_constants_gen.XXXXXX)
921- go run ./scripts/typegen/main.go rbac scopenames > " $$ tempfile"
922- mv -v " $$ tempfile" coderd/rbac/scopes_constants_gen.go
943+ coderd/rbac/object_gen.go | _gen
944+ # Write to a temp file first to avoid truncating the package
945+ # during build since the generator imports the rbac package.
946+ $(call atomic_write,go run ./scripts/typegen/main.go rbac scopenames)
923947 touch " $@ "
924948
925949# NOTE: depends on object_gen.go and scopes_constants_gen.go because
926950# `go run` compiles coderd/rbac which includes both.
927951codersdk/rbacresources_gen.go : scripts/typegen/codersdk.gotmpl scripts/typegen/main.go coderd/rbac/object.go coderd/rbac/policy/policy.go \
928- coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go
929- # Do no overwrite codersdk/rbacresources_gen.go directly, as it would make the file empty, breaking
930- # the `codersdk` package and any parallel build targets.
931- go run scripts/typegen/main.go rbac codersdk > /tmp/rbacresources_gen.go
932- mv /tmp/rbacresources_gen.go codersdk/rbacresources_gen.go
952+ coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go | _gen
953+ # Write to a temp file to avoid truncating the target, which
954+ # would break the codersdk package and any parallel build targets.
955+ $(call atomic_write,go run scripts/typegen/main.go rbac codersdk)
933956 touch " $@ "
934957
935958# NOTE: depends on object_gen.go and scopes_constants_gen.go because
936959# `go run` compiles coderd/rbac which includes both.
937960codersdk/apikey_scopes_gen.go : scripts/apikeyscopesgen/main.go coderd/rbac/scopes_catalog.go coderd/rbac/scopes.go \
938- coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go
961+ coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go | _gen
939962 # Generate SDK constants for external API key scopes.
940- go run ./scripts/apikeyscopesgen > /tmp/apikey_scopes_gen.go
941- mv /tmp/apikey_scopes_gen.go codersdk/apikey_scopes_gen.go
963+ $(call atomic_write,go run ./scripts/apikeyscopesgen)
942964 touch " $@ "
943965
944966# NOTE: depends on object_gen.go and scopes_constants_gen.go because
945967# `go run` compiles coderd/rbac which includes both.
946968site/src/api/rbacresourcesGenerated.ts : site/node_modules/.installed scripts/typegen/codersdk.gotmpl scripts/typegen/main.go coderd/rbac/object.go coderd/rbac/policy/policy.go \
947- coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go
948- tmpfile=$$(mktemp -d ) /$(notdir $@ ) && \
949- go run scripts/typegen/main.go rbac typescript > " $$ tmpfile" && \
950- ./scripts/biome_format.sh " $$ tmpfile" && \
951- mv " $$ tmpfile" " $@ "
969+ coderd/rbac/object_gen.go coderd/rbac/scopes_constants_gen.go | _gen
970+ $(call atomic_write,go run scripts/typegen/main.go rbac typescript,./scripts/biome_format.sh)
952971
953- site/src/api/countriesGenerated.ts : site/node_modules/.installed scripts/typegen/countries.tstmpl scripts/typegen/main.go codersdk/countries.go
954- tmpfile=$$(mktemp -d ) /$(notdir $@ ) && \
955- go run scripts/typegen/main.go countries > " $$ tmpfile" && \
956- ./scripts/biome_format.sh " $$ tmpfile" && \
957- mv " $$ tmpfile" " $@ "
972+ site/src/api/countriesGenerated.ts : site/node_modules/.installed scripts/typegen/countries.tstmpl scripts/typegen/main.go codersdk/countries.go | _gen
973+ $(call atomic_write,go run scripts/typegen/main.go countries,./scripts/biome_format.sh)
958974
959- site/src/api/chatModelOptionsGenerated.json : scripts/modeloptionsgen/main.go codersdk/chats.go
960- tmpfile=$$(mktemp -d ) /$(notdir $@ ) && \
961- go run ./scripts/modeloptionsgen/main.go | tail -n +2 > " $$ tmpfile" && \
962- ./scripts/biome_format.sh " $$ tmpfile" && \
963- mv " $$ tmpfile" " $@ "
975+ site/src/api/chatModelOptionsGenerated.json : scripts/modeloptionsgen/main.go codersdk/chats.go | _gen
976+ $(call atomic_write,go run ./scripts/modeloptionsgen/main.go | tail -n +2,./scripts/biome_format.sh)
964977
965- scripts/metricsdocgen/generated_metrics : $(GO_SRC_FILES )
966- go run ./scripts/metricsdocgen/scanner > $@ .tmp && mv $@ .tmp $@
978+ scripts/metricsdocgen/generated_metrics : $(GO_SRC_FILES ) | _gen
979+ $( call atomic_write, go run ./scripts/metricsdocgen/scanner)
967980
968- docs/admin/integrations/prometheus.md : node_modules/.installed scripts/metricsdocgen/main.go scripts/metricsdocgen/metrics scripts/metricsdocgen/generated_metrics
969- tmpfile =$$(mktemp -d ) /$(notdir $@ ) && cp " $@ " " $$ tmpfile" && \
981+ docs/admin/integrations/prometheus.md : node_modules/.installed scripts/metricsdocgen/main.go scripts/metricsdocgen/metrics scripts/metricsdocgen/generated_metrics | _gen
982+ tmpdir =$$(mktemp -d -p _gen ) && tmpfile= $$( realpath "$$tmpdir" ) /$(notdir $@ ) && cp " $@ " " $$ tmpfile" && \
970983 go run scripts/metricsdocgen/main.go --prometheus-doc-file=" $$ tmpfile" && \
971984 pnpm exec markdownlint-cli2 --fix " $$ tmpfile" && \
972985 pnpm exec markdown-table-formatter " $$ tmpfile" && \
973- mv " $$ tmpfile" " $@ "
986+ mv " $$ tmpfile" " $@ " && rm -rf " $$ tmpdir "
974987
975- docs/reference/cli/index.md : node_modules/.installed scripts/clidocgen/main.go examples/examples.gen.json $(GO_SRC_FILES )
976- tmpdir=$$(mktemp -d ) && \
988+ docs/reference/cli/index.md : node_modules/.installed scripts/clidocgen/main.go examples/examples.gen.json $(GO_SRC_FILES ) | _gen
989+ tmpdir=$$(mktemp -d -p _gen ) && \
990+ tmpdir=$$(realpath "$$tmpdir") && \
977991 mkdir -p " $$ tmpdir/docs/reference/cli" && \
978992 cp docs/manifest.json " $$ tmpdir/docs/manifest.json" && \
979993 CI=true DOCS_DIR=" $$ tmpdir/docs" go run ./scripts/clidocgen && \
980994 pnpm exec markdownlint-cli2 --fix " $$ tmpdir/docs/reference/cli/*.md" && \
981995 pnpm exec markdown-table-formatter " $$ tmpdir/docs/reference/cli/*.md" && \
982- cp " $$ tmpdir/docs/reference/cli/" * .md docs/reference/cli/ && \
996+ for f in " $$ tmpdir/docs/reference/cli/" * .md; do mv " $$ f " " docs/reference/cli/$$ (basename " $$ f " ) " ; done && \
983997 rm -rf " $$ tmpdir"
984998
985- docs/admin/security/audit-logs.md : node_modules/.installed coderd/database/querier.go scripts/auditdocgen/main.go enterprise/audit/table.go coderd/rbac/object_gen.go
986- tmpfile =$$(mktemp -d ) /$(notdir $@ ) && cp " $@ " " $$ tmpfile" && \
999+ docs/admin/security/audit-logs.md : node_modules/.installed coderd/database/querier.go scripts/auditdocgen/main.go enterprise/audit/table.go coderd/rbac/object_gen.go | _gen
1000+ tmpdir =$$(mktemp -d -p _gen ) && tmpfile= $$( realpath "$$tmpdir" ) /$(notdir $@ ) && cp " $@ " " $$ tmpfile" && \
9871001 go run scripts/auditdocgen/main.go --audit-doc-file=" $$ tmpfile" && \
9881002 pnpm exec markdownlint-cli2 --fix " $$ tmpfile" && \
9891003 pnpm exec markdown-table-formatter " $$ tmpfile" && \
990- mv " $$ tmpfile" " $@ "
1004+ mv " $$ tmpfile" " $@ " && rm -rf " $$ tmpdir "
9911005
9921006coderd/apidoc/.gen : \
9931007 node_modules/.installed \
@@ -1002,25 +1016,28 @@ coderd/apidoc/.gen: \
10021016 scripts/apidocgen/generate.sh \
10031017 scripts/apidocgen/swaginit/main.go \
10041018 $(wildcard scripts/apidocgen/postprocess/* ) \
1005- $(wildcard scripts/apidocgen/markdown-template/* )
1006- tmpdir=$$(mktemp -d ) && swagtmp=$$(mktemp -d ) && \
1019+ $(wildcard scripts/apidocgen/markdown-template/* ) | _gen
1020+ tmpdir=$$(mktemp -d -p _gen ) && swagtmp=$$(mktemp -d -p _gen ) && \
1021+ tmpdir=$$(realpath "$$tmpdir") && swagtmp=$$(realpath "$$swagtmp") && \
10071022 mkdir -p " $$ tmpdir/reference/api" && \
10081023 cp docs/manifest.json " $$ tmpdir/manifest.json" && \
10091024 SWAG_OUTPUT_DIR=" $$ swagtmp" APIDOCGEN_DOCS_DIR=" $$ tmpdir" ./scripts/apidocgen/generate.sh && \
10101025 pnpm exec markdownlint-cli2 --fix " $$ tmpdir/reference/api/*.md" && \
10111026 pnpm exec markdown-table-formatter " $$ tmpdir/reference/api/*.md" && \
10121027 ./scripts/biome_format.sh " $$ swagtmp/swagger.json" && \
1013- cp " $$ tmpdir/reference/api/" * .md docs/reference/api/ && \
1014- cp " $$ tmpdir/manifest.json" docs /manifest.json && \
1015- cp " $$ swagtmp/docs.go" coderd/apidoc/docs.go && \
1016- cp " $$ swagtmp/swagger.json" coderd/apidoc/swagger.json && \
1028+ for f in " $$ tmpdir/reference/api/" * .md; do mv " $$ f " " docs/reference/api/$$ (basename " $$ f " ) " ; done && \
1029+ mv " $$ tmpdir/manifest.json" _gen /manifest-staging .json && \
1030+ mv " $$ swagtmp/docs.go" coderd/apidoc/docs.go && \
1031+ mv " $$ swagtmp/swagger.json" coderd/apidoc/swagger.json && \
10171032 rm -rf " $$ tmpdir" " $$ swagtmp"
10181033 touch " $@ "
10191034
1020- docs/manifest.json : site/node_modules/.installed coderd/apidoc/.gen docs/reference/cli/index.md
1021- tmpfile=$$(mktemp -d ) /$(notdir $@ ) && cp " $@ " " $$ tmpfile" && \
1035+ docs/manifest.json : site/node_modules/.installed coderd/apidoc/.gen docs/reference/cli/index.md | _gen
1036+ tmpdir=$$(mktemp -d -p _gen ) && tmpfile=$$(realpath "$$tmpdir") /$(notdir $@ ) && \
1037+ cp _gen/manifest-staging.json " $$ tmpfile" && \
10221038 ./scripts/biome_format.sh " $$ tmpfile" && \
1023- mv " $$ tmpfile" " $@ "
1039+ mv " $$ tmpfile" " $@ " && rm -rf " $$ tmpdir" && \
1040+ rm -f _gen/manifest-staging.json
10241041
10251042coderd/apidoc/swagger.json : site/node_modules/.installed coderd/apidoc/.gen
10261043 touch " $@ "
0 commit comments