Clean up build tooling and Dockerfile
- Dockerfile cross-compiles Go for the target platform (amd64/arm64 without emulation), uses templ pinned in go.mod, runs as uid 1000 on alpine and lets FRONTEND_IMAGE pin the frontend version - justfile: tools via go tool, `test` (unit) and `test-integration` (uses the active docker context), no hardcoded paths, no tailwind or frontend recipes - Removed app.yaml, init.sh, tailwind.config.js and the tracked .idea folder
This commit is contained in:
1 parent
7b144ae419
commit
59dfff38bc
13 files changed
+58
-304
No files matched your search
+3
-9
@@ -14,18 +14,12 @@ compose.yaml
|
|||||||
*.pprof
|
*.pprof
|
||||||
main
|
main
|
||||||
conf.yaml
|
conf.yaml
|
||||||
output.css
|
|
||||||
tailwindcss
|
|
||||||
.env
|
.env
|
||||||
|
|
||||||
# Node.js (frontend build artifacts)
|
# Test files and fixtures
|
||||||
node_modules
|
|
||||||
package.json
|
|
||||||
package-lock.json
|
|
||||||
|
|
||||||
# Test files
|
|
||||||
*_test.go
|
*_test.go
|
||||||
integration_test.go
|
internal/testutil
|
||||||
|
*_dump.sql
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -3,13 +3,8 @@ tmp
|
|||||||
.idea
|
.idea
|
||||||
*templ.go
|
*templ.go
|
||||||
conf.yaml
|
conf.yaml
|
||||||
output.css
|
|
||||||
compose.yaml
|
compose.yaml
|
||||||
tailwindcss
|
|
||||||
.env
|
.env
|
||||||
node_modules
|
|
||||||
package.json
|
|
||||||
package-lock.json
|
|
||||||
cpu.pprof
|
cpu.pprof
|
||||||
main
|
main
|
||||||
|
|
||||||
|
|||||||
Generated
-8
@@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
Generated
-16
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module version="4">
|
|
||||||
<component name="Go" enabled="true">
|
|
||||||
<buildTags>
|
|
||||||
<option name="customFlags">
|
|
||||||
<array>
|
|
||||||
<option value="prod" />
|
|
||||||
</array>
|
|
||||||
</option>
|
|
||||||
</buildTags>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
Generated
-5
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
||||||
Generated
-36
@@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
|
||||||
<data-source source="LOCAL" name="music_prod@192.168.86.100" uuid="e63caf71-2b1a-400d-9cc4-4b87b1f9b807">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://192.168.86.100:5432/music_prod</jdbc-url>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="music_test@192.168.86.100" uuid="d063e147-d7f0-48db-9f04-57a108261ef1">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://192.168.86.100:5432/music_test</jdbc-url>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="music_test@ssh.sanplex.xyz" uuid="a9cf3eb8-abc2-479b-9f27-12b4cbbfc321">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://ssh.sanplex.xyz:9432/music_test</jdbc-url>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="music_prod@ssh.sanplex.xyz" uuid="20917ace-4e9a-4273-bdb7-13ebc774cbba">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://ssh.sanplex.xyz:9432/music_prod</jdbc-url>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="music_test2@localhost" uuid="a423ab0a-55b0-42e1-8070-25d8ef34bfac">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://localhost:5432/music_test2</jdbc-url>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
</data-source>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-8
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/MusicServer.iml" filepath="$PROJECT_DIR$/.idea/MusicServer.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
+28
-25
@@ -1,36 +1,39 @@
|
|||||||
# Stage 1: Build backend
|
# The frontend is built and published separately; override to pin a version.
|
||||||
FROM golang:1.25-alpine as build_go
|
ARG FRONTEND_IMAGE=gitea.sanplex.xyz/sansan/musicfrontend:latest
|
||||||
RUN apk add --no-cache curl
|
|
||||||
|
# Stage 1: Build the backend on the build machine and cross-compile for the target platform,
|
||||||
|
# so multi-platform builds need no emulation.
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS build
|
||||||
|
ARG TARGETOS TARGETARCH
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
COPY cmd/ ./cmd/
|
COPY cmd/ ./cmd/
|
||||||
COPY internal/ ./internal/
|
COPY internal/ ./internal/
|
||||||
RUN find . -name "*_test.go" -delete && \
|
RUN go tool templ generate
|
||||||
find . -name "integration_test.go" -delete
|
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
|
||||||
RUN go install github.com/a-h/templ/cmd/templ@latest
|
go build -trimpath -ldflags="-s -w" -tags timetzdata -o main ./cmd
|
||||||
RUN templ generate
|
|
||||||
RUN go build -o main cmd/main.go
|
|
||||||
|
|
||||||
# Stage 2: Final image
|
# Stage 2: Frontend static files (the same for every platform)
|
||||||
FROM golang:1.25-alpine
|
FROM --platform=$BUILDPLATFORM ${FRONTEND_IMAGE} AS frontend
|
||||||
|
# Empty API_HOSTNAME makes the frontend use relative paths
|
||||||
|
RUN echo "window.__RUNTIME_CONFIG__ = { API_HOSTNAME: '' };" > /usr/share/nginx/html/config.js
|
||||||
|
|
||||||
|
# Stage 3: Final image. No RUN steps here, so no emulation is needed for other architectures.
|
||||||
|
FROM alpine:3.22
|
||||||
|
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/main .
|
||||||
|
COPY --from=frontend /usr/share/nginx/html /frontend
|
||||||
|
COPY ./songs/ ./songs/
|
||||||
|
|
||||||
|
# The music volume must be readable by uid 1000, and writable for the .id file cleanup during sync.
|
||||||
|
USER 1000:1000
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
VOLUME /sorted
|
VOLUME /sorted
|
||||||
VOLUME /characters
|
VOLUME /characters
|
||||||
|
|
||||||
COPY --from=build_go /app/main .
|
# Required: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_NAME, MUSIC_PATH, CHARACTERS_PATH
|
||||||
COPY --from=gitea.sanplex.xyz/sansan/musicfrontend:latest /usr/share/nginx/html /frontend
|
ENV PORT=8080
|
||||||
# Generate config.js with empty API_HOSTNAME (relative paths)
|
|
||||||
RUN echo "window.__RUNTIME_CONFIG__ = { API_HOSTNAME: '' };" > /frontend/config.js
|
|
||||||
COPY ./songs/ ./songs/
|
|
||||||
|
|
||||||
ENV PORT 8080
|
CMD ["./main"]
|
||||||
ENV DB_HOST ""
|
|
||||||
ENV DB_PORT ""
|
|
||||||
ENV DB_USERNAME ""
|
|
||||||
ENV DB_PASSWORD ""
|
|
||||||
ENV DB_NAME ""
|
|
||||||
ENV MUSIC_PATH ""
|
|
||||||
ENV CHARACTERS_PATH ""
|
|
||||||
|
|
||||||
CMD ./main
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
application: musicserver
|
|
||||||
version: 2.2.0
|
|
||||||
runtime: go115
|
|
||||||
api_version: go1
|
|
||||||
|
|
||||||
handlers:
|
|
||||||
- url: /.*
|
|
||||||
script: _go_app
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
|
|
||||||
#envsubst < ./frontend/src/arne.js
|
|
||||||
|
|
||||||
sed -i 's^$HOSTNAME^'"$HOSTNAME"'^g' ./frontend/src/arne.js
|
|
||||||
|
|
||||||
cat ./frontend/src/arne.js
|
|
||||||
|
|
||||||
cd ./frontend/
|
|
||||||
|
|
||||||
npm install
|
|
||||||
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
./MusicServer
|
|
||||||
@@ -1,104 +1,50 @@
|
|||||||
set dotenv-load
|
set dotenv-load
|
||||||
|
|
||||||
# Build the application
|
# Build and run the unit tests
|
||||||
all: build test
|
all: build test
|
||||||
|
|
||||||
templ-install:
|
# Generate templ components (version pinned in go.mod)
|
||||||
@if ! command -v templ > /dev/null; then \
|
templ-build:
|
||||||
read -p "Go's 'templ' is not installed on your machine. Do you want to install it? [Y/n] " choice; \
|
|
||||||
if [ "$$choice" != "n" ] && [ "$$choice" != "N" ]; then \
|
|
||||||
go install github.com/a-h/templ/cmd/templ@latest; \
|
|
||||||
if [ ! -x "$$(command -v templ)" ]; then \
|
|
||||||
echo "templ installation failed. Exiting..."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
else \
|
|
||||||
echo "You chose not to install templ. Exiting..."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
templ-build: templ-install
|
|
||||||
@echo "Building templ..."
|
@echo "Building templ..."
|
||||||
@templ generate
|
@go tool templ generate
|
||||||
|
|
||||||
tailwind-macos:
|
|
||||||
@if [ ! -f tailwindcss ]; then curl -sL https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64 -o tailwindcss; fi
|
|
||||||
@chmod +x tailwindcss
|
|
||||||
|
|
||||||
tailwind-linux:
|
|
||||||
@if [ ! -f tailwindcss ]; then curl -sL https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 -o tailwindcss; fi
|
|
||||||
@chmod +x tailwindcss
|
|
||||||
|
|
||||||
tailwind-build:
|
|
||||||
@echo "Building tailwind..."
|
|
||||||
@./tailwindcss -i cmd/web/assets/css/input.css -o cmd/web/assets/css/output.css
|
|
||||||
|
|
||||||
sqlc-generate:
|
sqlc-generate:
|
||||||
@echo "Generating sqlc schema..."
|
@echo "Generating sqlc code..."
|
||||||
@sqlc generate
|
@sqlc generate
|
||||||
|
|
||||||
migrate-create name:
|
migrate-create name:
|
||||||
@migrate create -ext sql -dir internal/db/migrations -seq {{name}}
|
@migrate create -ext sql -dir internal/db/migrations -seq {{name}}
|
||||||
|
|
||||||
swag-install:
|
# Generate OpenAPI docs (version pinned in go.mod)
|
||||||
@if ! command -v swag > /dev/null; then \
|
swag-generate:
|
||||||
read -p "Swag is not installed on your machine. Do you want to install it? [Y/n] " choice; \
|
|
||||||
if [ "$$choice" != "n" ] && [ "$$choice" != "N" ]; then \
|
|
||||||
go install github.com/swaggo/swag/cmd/swag@latest; \
|
|
||||||
if [ ! -x "$$(command -v swag)" ]; then \
|
|
||||||
echo "swag installation failed. Exiting..."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
else \
|
|
||||||
echo "You chose not to install swag. Exiting..."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
swag-generate: swag-install
|
|
||||||
@echo "Generating OpenAPI docs..."
|
@echo "Generating OpenAPI docs..."
|
||||||
@swag init -g internal/server/routes.go -o cmd/docs
|
@go tool swag init -g internal/server/routes.go -o cmd/docs --parseInternal
|
||||||
|
|
||||||
frontend-install:
|
|
||||||
@if ! command -v npm > /dev/null; then \
|
|
||||||
echo "npm is not installed on your machine. Please install Node.js first."; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
@cd cmd/frontend && npm install
|
|
||||||
|
|
||||||
frontend-build: frontend-install
|
|
||||||
@echo "Building frontend..."
|
|
||||||
@cd cmd/frontend && npm run build
|
|
||||||
|
|
||||||
[no-cd]
|
|
||||||
build: sqlc-generate templ-build swag-generate
|
build: sqlc-generate templ-build swag-generate
|
||||||
@echo "Building..."
|
@echo "Building..."
|
||||||
@go build -o main cmd/main.go
|
@go build -o main cmd/main.go
|
||||||
|
|
||||||
run:
|
run: templ-build
|
||||||
@templ generate
|
|
||||||
@go run cmd/main.go
|
@go run cmd/main.go
|
||||||
|
|
||||||
build-run: build
|
build-run: build
|
||||||
@go run cmd/main.go
|
@./main
|
||||||
|
|
||||||
test: build
|
# Unit tests: no database or Docker needed
|
||||||
@echo "Starting test database container..."
|
test:
|
||||||
@docker compose -f compose.test.yaml up -d
|
@go test -race ./...
|
||||||
@sleep 10
|
|
||||||
@echo "Running integration tests..."
|
# Integration tests against PostgreSQL in Docker (testcontainers), using the active docker context.
|
||||||
@just test-integration
|
# Pass a pattern to run a subset, e.g. `just test-integration TestSQLDumps`
|
||||||
@echo "Stopping test database container..."
|
test-integration pattern=".":
|
||||||
@just test-integration-down
|
@DOCKER_HOST="${DOCKER_HOST:-$(docker context inspect --format '{{{{.Endpoints.docker.Host}}')}" \
|
||||||
|
go test -tags integration -race -timeout 15m -run '{{pattern}}' ./...
|
||||||
|
|
||||||
# Clean the binary
|
|
||||||
clean:
|
clean:
|
||||||
@echo "Cleaning..."
|
@echo "Cleaning..."
|
||||||
@rm -f main
|
@rm -f main
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
@echo "Building Docker image with docker..."
|
|
||||||
@docker build -t music-server .
|
@docker build -t music-server .
|
||||||
|
|
||||||
docker-run:
|
docker-run:
|
||||||
@@ -107,82 +53,13 @@ docker-run:
|
|||||||
docker-down:
|
docker-down:
|
||||||
@docker compose down
|
@docker compose down
|
||||||
|
|
||||||
# Run integration tests with docker
|
|
||||||
# Starts a test PostgreSQL container, runs tests, then cleans up
|
|
||||||
test-integration:
|
|
||||||
@echo "Cleaning old test database..."
|
|
||||||
@docker compose -f compose.test.yaml down -v
|
|
||||||
@echo "Starting fresh test database container..."
|
|
||||||
@docker compose -f compose.test.yaml up -d
|
|
||||||
@sleep 10
|
|
||||||
@echo "Running integration tests..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net DB_HOST=localhost DB_PORT=5433 DB_USERNAME=testuser DB_PASSWORD=testpass DB_NAME=music_server_test MUSIC_PATH=/Users/sebastian/projects/MusicServer/testMusic CHARACTERS_PATH=/Users/sebastian/projects/MusicServer/testCharacters PORT=8081 LOG_LEVEL=debug LOG_JSON=false go test -v -timeout 30m -p 1 -parallel 1 ./internal/...
|
|
||||||
|
|
||||||
# Alternative: Run integration tests using testcontainers with docker provider
|
|
||||||
test-integration-tc:
|
|
||||||
@echo "Creating test network (if it doesn't exist)..."
|
|
||||||
@docker network inspect testcontainers-test-net > /dev/null 2>&1 || docker network create testcontainers-test-net
|
|
||||||
@echo "Running integration tests with testcontainers (docker provider)..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_PROVIDER=docker TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net go test -v -timeout 30m .
|
|
||||||
|
|
||||||
# Run SQL dump migration tests
|
|
||||||
# Tests that the application can start with each SQL dump and migrations work correctly
|
|
||||||
test-sql-dump:
|
|
||||||
@echo "Creating test network (if it doesn't exist)..."
|
|
||||||
@docker network inspect testcontainers-test-net > /dev/null 2>&1 || docker network create testcontainers-test-net
|
|
||||||
@echo "Running SQL dump migration tests..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_PROVIDER=docker TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net go test -v -timeout 15m -run "TestMusic.*Dump" ./internal/server/
|
|
||||||
|
|
||||||
# Run individual SQL dump tests
|
|
||||||
test-sql-dump-ref:
|
|
||||||
@echo "Creating test network (if it doesn't exist)..."
|
|
||||||
@docker network inspect testcontainers-test-net > /dev/null 2>&1 || docker network create testcontainers-test-net
|
|
||||||
@echo "Running SQL dump migration test for ref dump..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_PROVIDER=docker TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net go test -v -timeout 5m -run "TestMusicRefDump" ./internal/server/
|
|
||||||
|
|
||||||
test-sql-dump-test:
|
|
||||||
@echo "Creating test network (if it doesn't exist)..."
|
|
||||||
@docker network inspect testcontainers-test-net > /dev/null 2>&1 || docker network create testcontainers-test-net
|
|
||||||
@echo "Running SQL dump migration test for test dump..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_PROVIDER=docker TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net go test -v -timeout 5m -run "TestMusicTestDump" ./internal/server/
|
|
||||||
|
|
||||||
test-sql-dump-prod:
|
|
||||||
@echo "Creating test network (if it doesn't exist)..."
|
|
||||||
@docker network inspect testcontainers-test-net > /dev/null 2>&1 || docker network create testcontainers-test-net
|
|
||||||
@echo "Running SQL dump migration test for prod dump..."
|
|
||||||
@DOCKER_HOST=unix:///Users/sebastian/.docker/run/docker.sock TESTCONTAINERS_PROVIDER=docker TESTCONTAINERS_RYUK_CONTAINER_NETWORK=testcontainers-test-net go test -v -timeout 5m -run "TestMusicProdDump" ./internal/server/
|
|
||||||
|
|
||||||
# Stop and remove test database container
|
|
||||||
test-integration-down:
|
|
||||||
@echo "Stopping test database container..."
|
|
||||||
@docker compose -f compose.test.yaml down -v
|
|
||||||
|
|
||||||
# Build and run with Docker Compose
|
|
||||||
build-run-docker:
|
|
||||||
@echo "Building and running with Docker Compose..."
|
|
||||||
@docker compose up --build
|
|
||||||
|
|
||||||
# Shutdown containers
|
|
||||||
stop-docker:
|
|
||||||
@echo "Stopping containers..."
|
|
||||||
@docker compose down
|
|
||||||
|
|
||||||
watch-templ:
|
watch-templ:
|
||||||
templ generate --watch --proxy="http://localhost:8080" --cmd="go run ."
|
@go tool templ generate --watch --proxy="http://localhost:8080" --cmd="go run ./cmd"
|
||||||
|
|
||||||
# Live Reload
|
# Live reload
|
||||||
watch:
|
watch:
|
||||||
@if command -v air > /dev/null; then \
|
@if ! command -v air > /dev/null; then \
|
||||||
air; \
|
echo "air is not installed. Install it with: go install github.com/air-verse/air@latest"; \
|
||||||
echo "Watching...";\
|
exit 1; \
|
||||||
else \
|
|
||||||
read -p "Go's 'air' is not installed on your machine. Do you want to install it? [Y/n] " choice; \
|
|
||||||
if [ "$$choice" != "n" ] && [ "$$choice" != "N" ]; then \
|
|
||||||
go install github.com/air-verse/air@latest; \
|
|
||||||
air; \
|
|
||||||
echo "Watching...";\
|
|
||||||
else \
|
|
||||||
echo "You chose not to install air. Exiting..."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
fi
|
fi
|
||||||
|
@air
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: [
|
|
||||||
"./cmd/web/**/*.html", "./cmd/web/**/*.templ",
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in new issue
Block a user