diff --git a/Makefile b/Makefile index 7bfd7a7b..654cf0e2 100644 --- a/Makefile +++ b/Makefile @@ -1,171 +1,92 @@ -ifneq (,$(wildcard .env)) - include .env -endif - -RAND = $(shell echo $$RANDOM) -PADDING=" " -GREEN = \033[0;32m -YELLOW=\033[1;33m -NC = \033[0m -BLUE=\033[0;34m - -SOURCE ?= go_bindata -DATABASE ?= postgres -VERSION ?= $(shell git describe --tags 2>/dev/null | cut -c 2-) -REPO_OWNER ?= $(shell cd .. && basename "$$(pwd)") - -# ------ App Configuration -ROOT_NETWORK ?= gocanto -ROOT_PATH ?= $(shell pwd) -ROOT_ENV_FILE ?= $(ROOT_PATH)/.env -ROOT_EXAMPLE_ENV_FILE? = $(ROOT_PATH)/.env.example -STORAGE_PATH ?= $(ROOT_PATH)/storage -BIN_PATH ?= $(ROOT_PATH)/bin -BIN_LOGS_PATH ?= $(ROOT_PATH)/bin/storage/logs -APP_PATH ?= $(ROOT_PATH)/ - -# ------ Database Configuration -# --- Docker -DB_DOCKER_SERVICE_NAME ?= postgres -DB_DOCKER_CONTAINER_NAME ?= gocanto-db -# --- Paths -DB_SEEDER_ROOT_PATH ?= $(ROOT_PATH)/database/seeder -DB_INFRA_ROOT_PATH ?= $(ROOT_PATH)/database/infra -DB_INFRA_SSL_PATH ?= $(DB_INFRA_ROOT_PATH)/ssl -DB_INFRA_DATA_PATH ?= $(DB_INFRA_ROOT_PATH)/data -# --- SSL -DB_INFRA_SERVER_CRT ?= $(DB_INFRA_SSL_PATH)/server.crt -DB_INFRA_SERVER_CSR ?= $(DB_INFRA_SSL_PATH)/server.csr -DB_INFRA_SERVER_KEY ?= $(DB_INFRA_SSL_PATH)/server.key -# --- Migrations -DB_MIGRATE_PATH ?= $(DB_INFRA_ROOT_PATH)/migrations -DB_MIGRATE_VOL_MAP ?= $(DB_MIGRATE_PATH):$(DB_MIGRATE_PATH) - -.PHONY: fresh audit watch format -.PHONY: build\:app build\:app\:linux build\:release build\:run build\:fresh -.PHONY: env\:init -.PHONY: db\:local db\:up db\:ping db\:bash db\:fresh db\:logs -.PHONY: db\:delete db\:secure db\:secure\:show db\:chmod db\:seed -.PHONY: migrate\:up migrate\:down migrate\:create db\:migrate\:force -.PHONY: logs\:fresh logs\:bin\:fresh - -format: - gofmt -w -s . - -fresh: - rm -rf $(DB_INFRA_DATA_PATH) && \ - docker compose down --remove-orphans && \ - docker container prune -f && \ - docker image prune -f && \ - docker volume prune -f && \ - docker network prune -f && \ - docker ps - -audit: - $(call external_deps,'.') - $(call external_deps,'./bin/...') - $(call external_deps,'./app/...') - $(call external_deps,'./database/...') - $(call external_deps,'./docs/...') - -watch: - # --- Works with (air). - # https://github.com/air-verse/air - cd $(APP_PATH) && air - -build\:fresh: - make build:app && make build:run - -build\:app: - cp $(ROOT_PATH)/.env.production $(BIN_PATH)/.env && \ - make logs:bin:fresh && \ - rm -f $(ROOT_PATH)/bin/app && \ - CGO_ENABLED=0 go build -a -ldflags='-X main.Version=$(VERSION)' -o "$(ROOT_PATH)/bin/app" -tags '$(DATABASE) $(SOURCE)' $(APP_PATH) - -build\:app\:linux: - make logs:bin:fresh && \ - cd $(APP_PATH) && \ - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o "$(ROOT_PATH)/bin/app_linux" -ldflags='-X main.Version=$(VERSION) -extldflags "-static"' -tags '$(DATABASE) $(SOURCE)' $(APP_PATH) - -build\:run: - cd $(BIN_PATH) && ./app - -build\:release: - git tag v$(V) - @read -p "Press enter to confirm and push to origin ..." && git push origin v$(V) - -env\:init: - rm -f $(ROOT_ENV_FILE) && cp $(ROOT_EXAMPLE_ENV_FILE) $(ROOT_ENV_FILE) - -db\:local: - # --- Works with your local PG installation. - cd $(EN_DB_BIN_DIR) && \ - ./psql -h $(ENV_DB_HOST) -U $(ENV_DB_USER_NAME) -d $(ENV_DB_DATABASE_NAME) -p $(ENV_DB_PORT) - -db\:seed: - go run $(DB_SEEDER_ROOT_PATH)/main.go - -db\:up: - docker compose up $(DB_DOCKER_SERVICE_NAME) -d && \ - make db:logs - -db\:ping: - docker port $(DB_DOCKER_CONTAINER_NAME) - -db\:bash: - docker exec -it $(DB_DOCKER_CONTAINER_NAME) bash - -db\:fresh: - make db:delete && make db:up - -db\:logs: - docker logs -f $(DB_DOCKER_CONTAINER_NAME) - -db\:delete: - docker compose down $(DB_DOCKER_SERVICE_NAME) --remove-orphans && \ - rm -rf $(DB_INFRA_DATA_PATH) && \ - docker ps - -db\:secure: - make fresh && \ - rm -rf $(DB_INFRA_SERVER_CRT) && rm -rf $(DB_INFRA_SERVER_CSR) && rm -rf $(DB_INFRA_SERVER_KEY) && \ - openssl genpkey -algorithm RSA -out $(DB_INFRA_SERVER_KEY) && \ - openssl req -new -key $(DB_INFRA_SERVER_KEY) -out $(DB_INFRA_SERVER_CSR) && \ - openssl x509 -req -days 365 -in $(DB_INFRA_SERVER_CSR) -signkey $(DB_INFRA_SERVER_KEY) -out $(DB_INFRA_SERVER_CRT) && \ - make db:secure:permissions - -db\:chmod: - chmod 600 $(DB_INFRA_SERVER_KEY) && chmod 600 $(DB_INFRA_SERVER_CRT) - -db\:secure\:show: - docker exec -it $(DB_DOCKER_CONTAINER_NAME) ls -l /etc/ssl/private/server.key && \ - docker exec -it $(DB_DOCKER_CONTAINER_NAME) ls -l /etc/ssl/certs/server.crt - -migrate\:up: - @echo "\n${BLUE}${PADDING}--- Running DB Migrations ---\n${NC}" - @docker run -v $(DB_MIGRATE_VOL_MAP) --network ${ROOT_NETWORK} migrate/migrate -verbose -path=$(DB_MIGRATE_PATH) -database $(ENV_DB_URL) up - @echo "\n${GREEN}${PADDING}--- Done Running DB Migrations ---\n${NC}" - -migrate\:down: - @echo "\n${BLUE}${PADDING}--- Running DB Migrations ---\n${NC}" - @docker run -v $(DB_MIGRATE_VOL_MAP) --network ${ROOT_NETWORK} migrate/migrate -verbose -path=$(DB_MIGRATE_PATH) -database $(ENV_DB_URL) down 1 - @echo "\n${GREEN}${PADDING}--- Done Running DB Migrations ---\n${NC}" - -migrate\:create: - docker run -v $(DB_MIGRATE_VOL_MAP) --network ${ROOT_NETWORK} migrate/migrate create -ext sql -dir $(DB_MIGRATE_PATH) -seq $(name) - -migrate\:up\:force: - #migrate -path PATH_TO_YOUR_MIGRATIONS -database YOUR_DATABASE_URL force VERSION - docker run -v $(DB_MIGRATE_VOL_MAP) --network ${ROOT_NETWORK} migrate/migrate migrate -path $(DB_MIGRATE_PATH) -database $(ENV_DB_URL) force $(version) - -logs\:fresh: - find $(STORAGE_PATH)/logs -maxdepth 1 -type f -not -name ".gitkeep" -delete - -logs\:bin\:fresh: - @rm -rf "$(BIN_LOGS_PATH)" - @mkdir -m 777 $(BIN_LOGS_PATH) - @touch $(BIN_LOGS_PATH)/.gitkeep - -define external_deps - @echo '-- $(1)'; go list -f '{{join .Deps "\n"}}' $(1) | grep -v github.com/$(REPO_OWNER)/blog | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' -endef +.PHONY: help + +# -------------------------------------------------------------------------------------------------------------------- # +# -------------------------------------------------------------------------------------------------------------------- # + +SHELL := /bin/bash + +# -------------------------------------------------------------------------------------------------------------------- # +# -------------------------------------------------------------------------------------------------------------------- # + +NC := \033[0m +BOLD := \033[1m +CYAN := \033[36m +WHITE := \033[37m +GREEN := \033[0;32m +BLUE := \033[0;34m +RED := \033[0;31m +YELLOW := \033[1;33m + +# -------------------------------------------------------------------------------------------------------------------- # +# -------------------------------------------------------------------------------------------------------------------- # + +ROOT_NETWORK := gocanto +DATABASE := postgres +SOURCE := go_bindata +ROOT_PATH := $(shell pwd) +APP_PATH := $(ROOT_PATH)/ +STORAGE_PATH := $(ROOT_PATH)/storage +BIN_PATH := $(ROOT_PATH)/bin +BIN_LOGS_PATH := $(ROOT_PATH)/bin/storage/logs +REPO_OWNER := $(shell cd .. && basename "$$(pwd)") +VERSION := $(shell git describe --tags 2>/dev/null | cut -c 2-) + +# -------------------------------------------------------------------------------------------------------------------- # +# -------------------------------------------------------------------------------------------------------------------- # + +include ./config/makefile/helpers.mk +include ./config/makefile/env.mk + +include ./config/makefile/db.mk +include ./config/makefile/app.mk +include ./config/makefile/logs.mk +include ./config/makefile/build.mk + +# -------------------------------------------------------------------------------------------------------------------- # +# -------------------------------------------------------------------------------------------------------------------- # + +help: + @printf "$(BOLD)$(CYAN)Makefile Commands:$(NC)\n" + @printf "$(WHITE)Usage:$(NC) make $(BOLD)$(YELLOW)$(NC)\n\n" + + @printf "$(BOLD)$(BLUE)General Commands:$(NC)\n" + @printf " $(BOLD)$(GREEN)fresh$(NC) : Clean and reset various project components (logs, build, etc.).\n" + @printf " $(BOLD)$(GREEN)audit$(NC) : Run code audits and checks.\n" + @printf " $(BOLD)$(GREEN)watch$(NC) : Start a file watcher process.\n" + @printf " $(BOLD)$(GREEN)format$(NC) : Automatically format code.\n\n" + + @printf "$(BOLD)$(BLUE)Build Commands:$(NC)\n" + @printf " $(BOLD)$(GREEN)build:app$(NC) : Build the main application executable.\n" + @printf " $(BOLD)$(GREEN)build:app:linux$(NC) : Build the application specifically for Linux.\n" + @printf " $(BOLD)$(GREEN)build:release$(NC) : Build a release version of the application.\n" + @printf " $(BOLD)$(GREEN)build:run$(NC) : Build and run the application.\n" + @printf " $(BOLD)$(GREEN)build:fresh$(NC) : Build and run a freshly instance of the application.\n" + @printf " $(BOLD)$(GREEN)build:flush$(NC) : Clean build artifacts and then build the application.\n\n" + + @printf "$(BOLD)$(BLUE)Database Commands:$(NC)\n" + @printf " $(BOLD)$(GREEN)db:local$(NC) : Set up or manage the local database environment.\n" + @printf " $(BOLD)$(GREEN)db:up$(NC) : Start the database service or container.\n" + @printf " $(BOLD)$(GREEN)db:ping$(NC) : Check the database connection.\n" + @printf " $(BOLD)$(GREEN)db:bash$(NC) : Access the database environment via bash.\n" + @printf " $(BOLD)$(GREEN)db:fresh$(NC) : Reset and re-seed the database.\n" + @printf " $(BOLD)$(GREEN)db:logs$(NC) : View database logs.\n" + @printf " $(BOLD)$(GREEN)db:delete$(NC) : Delete the database.\n" + @printf " $(BOLD)$(GREEN)db:secure$(NC) : Apply database security configurations.\n" + @printf " $(BOLD)$(GREEN)db:secure:show$(NC): Display database security configurations.\n" + @printf " $(BOLD)$(GREEN)db:chmod$(NC) : Adjust database file or directory permissions.\n" + @printf " $(BOLD)$(GREEN)db:seed$(NC) : Run database seeders to populate data.\n" + @printf " $(BOLD)$(GREEN)db:migrate$(NC) : Run database migrations.\n" + @printf " $(BOLD)$(GREEN)db:rollback$(NC) : Rollback database migrations (usually the last batch).\n" + @printf " $(BOLD)$(GREEN)db:migrate:create$(NC): Create a new database migration file.\n" + @printf " $(BOLD)$(GREEN)db:migrate:force$(NC): Force database migrations to run.\n\n" + + @printf "$(BOLD)$(BLUE)Environment Commands:$(NC)\n" + @printf " $(BOLD)$(GREEN)env:check$(NC) : Verify environment configuration.\n" + @printf " $(BOLD)$(GREEN)env:fresh$(NC) : Refresh environment settings.\n" + @printf " $(BOLD)$(GREEN)env:init$(NC) : Initialize environment settings.\n" + @printf " $(BOLD)$(GREEN)env:print$(NC) : Display current environment settings.\n\n" + + @printf "$(BOLD)$(BLUE)Log Commands:$(NC)\n" + @printf " $(BOLD)$(GREEN)logs:fresh$(NC) : Clear application logs.\n" + + @printf "$(NC)" diff --git a/config/makefile/app.mk b/config/makefile/app.mk new file mode 100644 index 00000000..8c7f1f19 --- /dev/null +++ b/config/makefile/app.mk @@ -0,0 +1,25 @@ +.PHONY: fresh audit watch format + +format: + gofmt -w -s . + +fresh: + rm -rf $(DB_INFRA_DATA_PATH) && \ + docker compose down --remove-orphans && \ + docker container prune -f && \ + docker image prune -f && \ + docker volume prune -f && \ + docker network prune -f && \ + docker ps + +audit: + $(call external_deps,'.') + $(call external_deps,'./bin/...') + $(call external_deps,'./app/...') + $(call external_deps,'./database/...') + $(call external_deps,'./docs/...') + +watch: + # --- Works with (air). + # https://github.com/air-verse/air + cd $(APP_PATH) && air diff --git a/config/makefile/build.mk b/config/makefile/build.mk new file mode 100644 index 00000000..6210f9f1 --- /dev/null +++ b/config/makefile/build.mk @@ -0,0 +1,50 @@ +.PHONY: build\:app build\:flush build\:app\:linux build\:release build\:run build\:fresh + +___BIN___ROOT__PATH := $(shell pwd) +___BIN___ENV___FILE__TEMPLATE := .env.production +___BIN___FULL__PATH := $(___BIN___ROOT__PATH)/bin +___BIN___ENV___FILE := $(___BIN___FULL__PATH)/.env +___BIN___APP___FILE := $(___BIN___FULL__PATH)/app + +# --- Storage +___BIN___STORAGE__PATH := $(___BIN___FULL__PATH)/storage +___BIN___LOGS__PATH := $(___BIN___STORAGE__PATH)/logs + + +build\:fresh: + make build:app && make build:run + +build\:run: + cd $(___BIN___FULL__PATH) && ./app + +# +build\:app\:linux: + @printf "\n$(BLUE)[BIN]$(NC) Building the app in [amd64] has started.\n" + make build:env && \ + make build:flush && \ + cd $(APP_PATH) && \ + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o "$(ROOT_PATH)/bin/app_linux" -ldflags='-X main.Version=$(VERSION) -extldflags "-static"' -tags '$(DATABASE) $(SOURCE)' $(APP_PATH) + +build\:release: + git tag v$(V) + @read -p "Press enter to confirm and push to origin ..." && git push origin v$(V) + +build\:app: + @printf "\n$(BLUE)[BIN]$(NC) Building the app has started.\n" + make build:env && \ + make build:flush && \ + CGO_ENABLED=0 go build -a -ldflags='-X main.Version=$(VERSION)' -o "$(ROOT_PATH)/bin/app" -tags '$(DATABASE) $(SOURCE)' $(APP_PATH) + @printf "$(GREEN)[BIN]$(NC) Building the app has finished.\n\n" + +build\:flush: + @printf "$(BLUE)[BIN]$(NC) Flushing the previous builds has started.\n" + @sleep 1 + rm -f $(___BIN___ENV___FILE) + rm -f $(___BIN___APP___FILE) + rm -rf $(___BIN___LOGS__PATH) + mkdir -m 755 $(___BIN___LOGS__PATH) + touch $(___BIN___LOGS__PATH)/.gitkeep + @printf "$(GREEN)[BIN]$(NC) Flushing has finished.\n\n" + +build\:env: + cp $(___BIN___ENV___FILE__TEMPLATE) $(___BIN___ENV___FILE) diff --git a/config/makefile/db.mk b/config/makefile/db.mk new file mode 100644 index 00000000..8a09534e --- /dev/null +++ b/config/makefile/db.mk @@ -0,0 +1,83 @@ +# --- Metadata +.PHONY: db\:local db\:up db\:ping db\:bash db\:fresh db\:logs +.PHONY: db\:delete db\:secure db\:secure\:show db\:chmod db\:seed +.PHONY: db\:migrate db\:rollback db\:migrate\:create db\:migrate\:force + +# --- Docker +DB_DOCKER_SERVICE_NAME := postgres +DB_DOCKER_CONTAINER_NAME := gocanto-db + +# --- Paths +DB_SEEDER_ROOT_PATH := $(ROOT_PATH)/database/seeder +DB_INFRA_ROOT_PATH := $(ROOT_PATH)/database/infra +DB_INFRA_SSL_PATH := $(DB_INFRA_ROOT_PATH)/ssl +DB_INFRA_DATA_PATH := $(DB_INFRA_ROOT_PATH)/data + +# --- SSL +DB_INFRA_SERVER_CRT := $(DB_INFRA_SSL_PATH)/server.crt +DB_INFRA_SERVER_CSR := $(DB_INFRA_SSL_PATH)/server.csr +DB_INFRA_SERVER_KEY := $(DB_INFRA_SSL_PATH)/server.key + +# --- Migrations +DB_MIGRATE_PATH := $(DB_INFRA_ROOT_PATH)/migrations +DB_MIGRATE_VOL_MAP := $(DB_MIGRATE_PATH):$(DB_MIGRATE_PATH) + +db\:local: + # --- Works with your local PG installation. + cd $(EN_DB_BIN_DIR) && \ + ./psql -h $(ENV_DB_HOST) -U $(ENV_DB_USER_NAME) -d $(ENV_DB_DATABASE_NAME) -p $(ENV_DB_PORT) + +db\:seed: + go run $(DB_SEEDER_ROOT_PATH)/main.go + +db\:up: + docker compose up $(DB_DOCKER_SERVICE_NAME) -d && \ + make db:logs + +db\:ping: + docker port $(DB_DOCKER_CONTAINER_NAME) + +db\:bash: + docker exec -it $(DB_DOCKER_CONTAINER_NAME) bash + +db\:fresh: + make db:delete && make db:up + +db\:logs: + docker logs -f $(DB_DOCKER_CONTAINER_NAME) + +db\:delete: + docker compose down $(DB_DOCKER_SERVICE_NAME) --remove-orphans && \ + rm -rf $(DB_INFRA_DATA_PATH) && \ + docker ps + +db\:secure: + make fresh && \ + rm -rf $(DB_INFRA_SERVER_CRT) && rm -rf $(DB_INFRA_SERVER_CSR) && rm -rf $(DB_INFRA_SERVER_KEY) && \ + openssl genpkey -algorithm RSA -out $(DB_INFRA_SERVER_KEY) && \ + openssl req -new -key $(DB_INFRA_SERVER_KEY) -out $(DB_INFRA_SERVER_CSR) && \ + openssl x509 -req -days 365 -in $(DB_INFRA_SERVER_CSR) -signkey $(DB_INFRA_SERVER_KEY) -out $(DB_INFRA_SERVER_CRT) && \ + make db:secure:permissions + +db\:chmod: + chmod 600 $(DB_INFRA_SERVER_KEY) && chmod 600 $(DB_INFRA_SERVER_CRT) + +db\:secure\:show: + docker exec -it $(DB_DOCKER_CONTAINER_NAME) ls -l /etc/ssl/private/server.key && \ + docker exec -it $(DB_DOCKER_CONTAINER_NAME) ls -l /etc/ssl/certs/server.crt + +db\:migrate: + @printf "\n$(BLUE)[DB]$(NC) Migration has started.\n" + @docker run -v $(DB_MIGRATE_VOL_MAP) --network $(ROOT_NETWORK) migrate/migrate -verbose -path=$(DB_MIGRATE_PATH) -database $(ENV_DB_URL) up + @printf "$(GREEN)[DB]$(NC) Migration has finished.\n\n" + +db\:rollback: + @printf "\n$(RED)[DB]$(NC) Migration rollback has started.\n" + @docker run -v $(DB_MIGRATE_VOL_MAP) --network $(ROOT_NETWORK) migrate/migrate -verbose -path=$(DB_MIGRATE_PATH) -database $(ENV_DB_URL) down 1 + @printf "$(GREEN)[DB]$(NC) Migration rollback has finished.\n\n" + +db\:migrate\:create: + docker run -v $(DB_MIGRATE_VOL_MAP) --network $(ROOT_NETWORK) migrate/migrate create -ext sql -dir $(DB_MIGRATE_PATH) -seq $(name) + +db\:migrate\:force: + docker run -v $(DB_MIGRATE_VOL_MAP) --network $(ROOT_NETWORK) migrate/migrate migrate -path $(DB_MIGRATE_PATH) -database $(ENV_DB_URL) force $(version) diff --git a/config/makefile/env.mk b/config/makefile/env.mk new file mode 100644 index 00000000..afffdf5d --- /dev/null +++ b/config/makefile/env.mk @@ -0,0 +1,36 @@ +.PHONY: env\:check env\:fresh env\:init env\:print + +___ENV___ROOT__PATH := $(shell pwd) +___ENV___FILE_NAME := ".env" +___ENV___EXAMPLE_FILE_NAME := ".env.example" + +include $(___ENV___ROOT__PATH)/.env + +env\:init: + @if [ ! -f $(___ENV___FILE_NAME) ]; then \ + printf "The $(BLUE)[.env]$(NC) file not found in the current directory.\n"; \ + printf "New $(GREEN)[.env]$(NC) file successfully create from the $(YELLOW)[.env.example]$(NC) file using the $(BLUE)[make env:init]$(NC).\n"; \ + cp $(___ENV___EXAMPLE_FILE_NAME) $(___ENV___FILE_NAME) ; \ + fi + +env\:check: + @if [ ! -f $(___ENV___FILE_NAME) ]; then \ + printf "$(RED)Error:$(NC) $(BLUE)[.env]$(NC) file not found in the current directory. Please run $(BLUE)[env:init]$(NC) first.\n"; \ + else \ + printf "$(BLUE)[.env]$(NC) file found.\n"; \ + fi + +env\:fresh: + @if [ -f $(___ENV___FILE_NAME) ]; then \ + printf "\nRemoving development environment file $(YELLOW)[$(___ENV___FILE_NAME)]$(NC).\n"; \ + rm -f $(___ENV___FILE_NAME); \ + printf "Finished removing $(YELLOW)[$(___ENV___FILE_NAME)]$(NC) ($(RED)if it existed$(NC)).\n\n----\n"; \ + $(MAKE) env:init; \ + else \ + $(MAKE) env:init; \ + fi + +env\:print: + @echo "APP NAME ... : $(ENV_APP_NAME)" + @echo "APP TYPE ... : $(ENV_APP_ENV_TYPE)" + @echo "APP ENV .... : $(ENV_APP_ENV)" diff --git a/config/makefile/helpers.mk b/config/makefile/helpers.mk new file mode 100644 index 00000000..894ac843 --- /dev/null +++ b/config/makefile/helpers.mk @@ -0,0 +1,9 @@ + +define external_deps + @echo '-- $(1)'; go list -f '{{join .Deps "\n"}}' $(1) | grep -v github.com/$(REPO_OWNER)/blog | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' +endef + +# --- Padding left or Right +define padding_lr + @printf "%*s" $(1) "" +endef diff --git a/config/makefile/logs.mk b/config/makefile/logs.mk new file mode 100644 index 00000000..f5570eaf --- /dev/null +++ b/config/makefile/logs.mk @@ -0,0 +1,6 @@ +.PHONY: logs\:fresh + +logs\:fresh: + find $(STORAGE_PATH)/logs -maxdepth 1 -type f -not -name ".gitkeep" -delete + + diff --git a/database/infra/migrations/000001_schema.down.sql b/database/infra/migrations/000001_schema.down.sql index f630c723..18f1daf4 100644 --- a/database/infra/migrations/000001_schema.down.sql +++ b/database/infra/migrations/000001_schema.down.sql @@ -1,3 +1,4 @@ +DROP TABLE IF EXISTS newsletters; DROP TABLE IF EXISTS likes; DROP TABLE IF EXISTS comments; DROP TABLE IF EXISTS post_views; diff --git a/database/infra/migrations/000001_schema.up.sql b/database/infra/migrations/000001_schema.up.sql index 2cad255a..a2a9a580 100644 --- a/database/infra/migrations/000001_schema.up.sql +++ b/database/infra/migrations/000001_schema.up.sql @@ -41,6 +41,7 @@ CREATE TABLE IF NOT EXISTS posts ( created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP DEFAULT NULL, + CONSTRAINT fk_user FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE ); @@ -65,7 +66,10 @@ CREATE TABLE IF NOT EXISTS post_categories ( category_id BIGINT NOT NULL REFERENCES categories(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (post_id, category_id) + PRIMARY KEY (post_id, category_id), + + CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, + CONSTRAINT fk_category FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE ); CREATE INDEX idx_category_post ON post_categories (category_id, post_id); @@ -87,7 +91,10 @@ CREATE TABLE IF NOT EXISTS post_tags ( tag_id BIGINT NOT NULL REFERENCES tags(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (post_id, tag_id) + PRIMARY KEY (post_id, tag_id), + + CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, + CONSTRAINT fk_tag FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS post_views ( @@ -97,7 +104,10 @@ CREATE TABLE IF NOT EXISTS post_views ( ip_address INET, user_agent TEXT, viewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - UNIQUE(post_id, user_id, ip_address, user_agent) -- Prevents duplicate counting + UNIQUE(post_id, user_id, ip_address, user_agent), -- Prevents duplicate counting + + CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, + CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX idx_post_tags_tag_post ON post_tags (tag_id, post_id); @@ -114,7 +124,11 @@ CREATE TABLE IF NOT EXISTS comments ( approved_at TIMESTAMP DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP DEFAULT NULL + deleted_at TIMESTAMP DEFAULT NULL, + + CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, + CONSTRAINT fk_user FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE, + CONSTRAINT fk_comment FOREIGN KEY (parent_id) REFERENCES comments(id) ON DELETE CASCADE ); CREATE INDEX idx_comments_post_id ON comments (post_id); @@ -130,7 +144,27 @@ CREATE TABLE likes ( created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP DEFAULT NULL, - UNIQUE (post_id, user_id) -- Prevent duplicate likes + UNIQUE (post_id, user_id), -- Prevent duplicate likes + + CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, + CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX idx_likes_user_post ON likes (user_id, post_id); + +--------------------------------------------------- NEWSLETTERS --------------------------------------------------------- +CREATE TABLE newsletters ( + id BIGSERIAL PRIMARY KEY, + email VARCHAR(255) UNIQUE NOT NULL, + name VARCHAR(255) NOT NULL, + subscribed_at TIMESTAMP DEFAULT NULL, + unsubscribed_at TIMESTAMP DEFAULT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + UNIQUE (email, name) +); + +CREATE INDEX idx_newsletters_created_at ON newsletters(created_at); +CREATE INDEX idx_newsletters_subscribed_at ON newsletters(subscribed_at); +CREATE INDEX idx_newsletters_unsubscribed_at ON newsletters(unsubscribed_at); diff --git a/main.go b/main.go index 82c79139..5502273e 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "github.com/getsentry/sentry-go" "github.com/gocanto/blog/bootstrap" "github.com/gocanto/blog/env" "github.com/gocanto/blog/webkit" @@ -21,8 +20,6 @@ func init() { } func main() { - defer sentry.Recover() - dbConnection := bootstrap.MakeDbConnection(environment) logs := bootstrap.MakeLogs(environment) adminUser := bootstrap.MakeAdminUser(environment)