From f462f81460153ed6badf734c38a7338b7382d635 Mon Sep 17 00:00:00 2001 From: Carryall Date: Wed, 22 Feb 2023 15:06:47 +0700 Subject: [PATCH 01/43] [gh-92] Add script and command to check test coverage --- {{cookiecutter.app_name}}/.gitignore | 1 + {{cookiecutter.app_name}}/Makefile | 9 ++++++++- .../bin/check-coverage.sh | 20 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 {{cookiecutter.app_name}}/bin/check-coverage.sh diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index e1097ed..a8945ed 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -1,5 +1,6 @@ {% if cookiecutter._web_variant == "yes" %}/node_modules {% endif %}tmp/ +coverage/ .env {%- if cookiecutter.use_heroku == "yes" %} diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index cb0ae14..c8d84c8 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -43,8 +43,15 @@ install-dependencies: test: docker-compose -f docker-compose.test.yml up -d ENV=test make db/migrate - go test -v -p 1 -count=1 ./... + go test -v -p 1 -count=1 ./... -coverprofile=coverage/coverage.out docker-compose -f docker-compose.test.yml down +coverage: + go tool cover -html=coverage/coverage.out -o coverage/coverage.html + go tool cover -func=coverage/coverage.out + +coverage-check: coverage + ./bin/check-coverage.sh + wait-for-postgres: $(shell DATABASE_URL=$(DATABASE_URL) ./bin/wait-for-postgres.sh) diff --git a/{{cookiecutter.app_name}}/bin/check-coverage.sh b/{{cookiecutter.app_name}}/bin/check-coverage.sh new file mode 100755 index 0000000..09e68b9 --- /dev/null +++ b/{{cookiecutter.app_name}}/bin/check-coverage.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# go tool cover -func coverage/coverage.out results in the multiline text telling coverage percentage on each function in the following format +# github.com/nimblehq/gulf-approval-web/helpers/config.go:8: GetConfigPrefix 100.0% +# github.com/nimblehq/gulf-approval-web/helpers/config.go:28: GetStringConfig 100.0% +# github.com/nimblehq/gulf-approval-web/lib/api/v1/controllers/health.go:13: HealthStatus 100.0% +# total: (statements) 100.0% +# grep total to get the line start with `total` which contain the overall coverage percentage +# awk '{print substr($3, 1, length($3)-1)}' with the built-in variable `$3` to grab the 3rd part after the line is splited with space and substr to remove the % +# which will result in 100.0 +coverage=$(go tool cover -func coverage/coverage.out | grep total | awk '{print substr($3, 1, length($3)-1)}') +expected=100 + +if [ "$(echo $coverage '<' $expected | bc -l)" -eq 1 ]; then\ + echo "coverage percentage is too low ${coverage}%, the expected percentage is ${expected}%" + exit 1 +else\ + echo "coverage percentage meet expectation ${coverage}%" + exit 0 +fi; From 017d1c8f6dac32c0e7efe9f9543aa6839f2086a6 Mon Sep 17 00:00:00 2001 From: Carryall Date: Tue, 21 Mar 2023 14:46:22 +0700 Subject: [PATCH 02/43] [gh-92] Update the coverage check output --- {{cookiecutter.app_name}}/bin/check-coverage.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/{{cookiecutter.app_name}}/bin/check-coverage.sh b/{{cookiecutter.app_name}}/bin/check-coverage.sh index 09e68b9..57bcfc2 100755 --- a/{{cookiecutter.app_name}}/bin/check-coverage.sh +++ b/{{cookiecutter.app_name}}/bin/check-coverage.sh @@ -8,13 +8,16 @@ # grep total to get the line start with `total` which contain the overall coverage percentage # awk '{print substr($3, 1, length($3)-1)}' with the built-in variable `$3` to grab the 3rd part after the line is splited with space and substr to remove the % # which will result in 100.0 +RED='\033[0;31m' +GREEN='\033[0;32m' + coverage=$(go tool cover -func coverage/coverage.out | grep total | awk '{print substr($3, 1, length($3)-1)}') expected=100 if [ "$(echo $coverage '<' $expected | bc -l)" -eq 1 ]; then\ - echo "coverage percentage is too low ${coverage}%, the expected percentage is ${expected}%" + echo "${RED}Coverage percentage is too low ${coverage}%, the expected percentage is ${expected}%" exit 1 else\ - echo "coverage percentage meet expectation ${coverage}%" + echo "${GREEN}Coverage percentage meet expectation ${coverage}%" exit 0 fi; From c8ed3196b0640ed63d9667f1e7ae45183d7ffb4f Mon Sep 17 00:00:00 2001 From: Carryall Date: Tue, 21 Mar 2023 14:46:37 +0700 Subject: [PATCH 03/43] [gh-92] Add test report --- {{cookiecutter.app_name}}/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index c8d84c8..5de54ed 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -43,7 +43,7 @@ install-dependencies: test: docker-compose -f docker-compose.test.yml up -d ENV=test make db/migrate - go test -v -p 1 -count=1 ./... -coverprofile=coverage/coverage.out + go test -v -p 1 -count=1 ./... -coverprofile=coverage/coverage.out -ginkgo.reportFile=coverage/test-report.xml docker-compose -f docker-compose.test.yml down coverage: From e9b1eb9128252c249b781fea8e2c7ffd723f35c7 Mon Sep 17 00:00:00 2001 From: Carryall Date: Tue, 21 Mar 2023 15:03:00 +0700 Subject: [PATCH 04/43] [gh-92] Ensure executable coverage script --- hooks/post_gen_project.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index fcc92a8..7d0ed20 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -5,7 +5,6 @@ # Get the root project directory PROJECT_DIRECTORY = os.path.realpath(os.path.curdir) - def remove_files(path): """ Removes files in path @@ -14,7 +13,6 @@ def remove_files(path): PROJECT_DIRECTORY, path )) - def remove_file(path): """ Removes file with path @@ -24,8 +22,6 @@ def remove_file(path): )) # Print log with color - - def print_log(message): """ Print log with color @@ -34,7 +30,6 @@ def print_log(message): CEND = '\033[0m' # END color print(CYELLOW + message + CEND) - def remove_empty_folders(): """ List all empty folders and remove them @@ -46,6 +41,12 @@ def remove_empty_folders(): print_log(f'Removing {dir} folder') os.rmdir(os.path.join(root, dir)) +def ensure_coverage_check_script(): + """ + Ensure coverage check script is executable + """ + print_log('Ensure coverage check is executable') + subprocess.call(['chmod', '+x', './bin/check-coverage.sh']) def init_git(message): """ @@ -57,7 +58,6 @@ def init_git(message): subprocess.call( ['git', 'commit', '-m', 'Initialize project using gin-templates']) - # Remove logrus add-on if not seleted if '{{ cookiecutter.use_logrus }}'.lower() == 'no': print_log('Removing logrus add-on') @@ -108,5 +108,8 @@ def init_git(message): # Remove empty folders remove_empty_folders() +# Ensure coverage check script is executable CI +ensure_coverage_check_script() + # Initialize git init_git('Initializing git repository') From 76a3d3d4a13c52954b146841e3fa3846ee5c1173 Mon Sep 17 00:00:00 2001 From: Carryall Date: Thu, 25 May 2023 18:06:35 +0700 Subject: [PATCH 05/43] [gh-93] Update the command --- {{cookiecutter.app_name}}/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 350f655..729f9cf 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -6,10 +6,10 @@ endif .PHONY: env-setup env-teardown db/migrate db/rollback migration/create migration/status dev install-dependencies test wait-for-postgres env-setup: - docker-compose -f docker-compose.dev.yml up -d + docker compose -f docker-compose.dev.yml up -d env-teardown: - docker-compose -f docker-compose.dev.yml down + docker compose -f docker-compose.dev.yml down db/migrate: make wait-for-postgres @@ -41,10 +41,10 @@ install-dependencies: {% if cookiecutter._web_variant == "yes" %}npm install{% endif %} test: - docker-compose -f docker-compose.test.yml up -d + docker compose -f docker-compose.test.yml up -d make wait-for-postgres go test -v -p 1 -count=1 ./... -coverprofile=coverage/coverage.out -ginkgo.reportFile=coverage/test-report.xml - docker-compose -f docker-compose.test.yml down + docker compose -f docker-compose.test.yml down coverage: go tool cover -html=coverage/coverage.out -o coverage/coverage.html From 3aa7e36674842f7e3031997431d320f8c56bfb1c Mon Sep 17 00:00:00 2001 From: Carryall Date: Fri, 26 May 2023 16:06:10 +0700 Subject: [PATCH 06/43] [gh-90] Use cases instead --- {{cookiecutter.app_name}}/database/database.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/{{cookiecutter.app_name}}/database/database.go b/{{cookiecutter.app_name}}/database/database.go index 0d141a3..6fc606f 100644 --- a/{{cookiecutter.app_name}}/database/database.go +++ b/{{cookiecutter.app_name}}/database/database.go @@ -2,7 +2,6 @@ package database import ( "fmt" - "strings" {% if cookiecutter.use_logrus == "no" %}"log" {% endif %} @@ -13,6 +12,7 @@ import ( "github.com/gin-gonic/gin" "github.com/pressly/goose/v3" "github.com/spf13/viper" + "golang.org/x/text/cases" "gorm.io/driver/postgres" "gorm.io/gorm" ) @@ -25,7 +25,8 @@ func InitDatabase(databaseURL string) { log.Fatalf("Failed to connect to %v database: %v", gin.Mode(), err) } else { viper.Set("database", db) - log.Println(strings.Title(gin.Mode()) + " database connected successfully.") + caser := cases.Title(language.English) + log.Println(caser.String(gin.Mode()) + " database connected successfully.") } migrateDB(db) From 933fc87c443fa881054d39201b25ec77770efdf7 Mon Sep 17 00:00:00 2001 From: Carryall Date: Fri, 26 May 2023 16:12:23 +0700 Subject: [PATCH 07/43] [gh-90] Update readme to include how to develop --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 2bb4946..265f234 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,20 @@ Check this [wiki](https://github.com/nimblehq/gin-templates/wiki/Directories) fo make test ``` +## Development + +- Build the command with + + ```sh + go build -o + ``` + +- Run the build file follow by the `create` command and the prompt to create a Go project should appear + + ```sh + create + ``` + ## License This project is Copyright (c) 2014 and onwards Nimble. It is free software, From 79d8e9b560a45a8be01a410714ad3a00ef630829 Mon Sep 17 00:00:00 2001 From: Carryall Date: Thu, 1 Jun 2023 17:39:01 +0700 Subject: [PATCH 08/43] [#103] Upgrade air version --- {{cookiecutter.app_name}}/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 350f655..f519e81 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -34,7 +34,7 @@ dev: forego start -f Procfile.dev install-dependencies: - go install github.com/cosmtrek/air@v1.41.1 + go install github.com/cosmtrek/air@v1.43.0 go install github.com/pressly/goose/v3/cmd/goose@v3.9.0 go install github.com/ddollar/forego@latest go mod tidy From b6161c5a4dca0fc4a358d29173a3389866b8001b Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 15:50:35 +0700 Subject: [PATCH 09/43] [#105] Add `use_openapi` --- cookiecutter.json | 1 + 1 file changed, 1 insertion(+) diff --git a/cookiecutter.json b/cookiecutter.json index 39c6878..ebbb7a5 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -4,6 +4,7 @@ "css_addon": ["Bootstrap", "Tailwind", "None"], "use_logrus": ["yes", "no"], "use_heroku": ["yes", "no"], + "use_openapi": ["yes", "no"], "_api_variant": "no", "_web_variant": "no", From 50d01c2379cc36f5b083002eb92c48f6410a68a5 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 15:59:53 +0700 Subject: [PATCH 10/43] [#105] Add docs folder --- .../docs/openapi/examples/requests/.gitkeep | 0 .../openapi/examples/responses/health.json | 24 ++++++++++++++ .../docs/openapi/openapi.yml | 31 +++++++++++++++++++ .../docs/openapi/paths/health.yml | 20 ++++++++++++ .../docs/openapi/request_bodies/.gitkeep | 0 .../docs/openapi/responses.yml | 4 +++ .../docs/openapi/responses/default_error.yml | 11 +++++++ .../docs/openapi/schemas.yml | 12 +++++++ .../docs/openapi/schemas/requests/.gitkeep | 0 .../docs/openapi/schemas/responses/health.yml | 24 ++++++++++++++ .../docs/openapi/schemas/shared/error.yml | 15 +++++++++ 11 files changed, 141 insertions(+) create mode 100644 {{cookiecutter.app_name}}/docs/openapi/examples/requests/.gitkeep create mode 100644 {{cookiecutter.app_name}}/docs/openapi/examples/responses/health.json create mode 100644 {{cookiecutter.app_name}}/docs/openapi/openapi.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/paths/health.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/request_bodies/.gitkeep create mode 100644 {{cookiecutter.app_name}}/docs/openapi/responses.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/responses/default_error.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/schemas.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/schemas/requests/.gitkeep create mode 100644 {{cookiecutter.app_name}}/docs/openapi/schemas/responses/health.yml create mode 100644 {{cookiecutter.app_name}}/docs/openapi/schemas/shared/error.yml diff --git a/{{cookiecutter.app_name}}/docs/openapi/examples/requests/.gitkeep b/{{cookiecutter.app_name}}/docs/openapi/examples/requests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/{{cookiecutter.app_name}}/docs/openapi/examples/responses/health.json b/{{cookiecutter.app_name}}/docs/openapi/examples/responses/health.json new file mode 100644 index 0000000..32abe7b --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/examples/responses/health.json @@ -0,0 +1,24 @@ +{ + "ok": { + "value": { + "data": { + "id": "1", + "type": "health", + "attributes": { + "message": "OK" + } + } + } + }, + "error": { + "value": { + "errors": [ + { + "status": "500", + "title": "Internal Server Error", + "detail": "Something went wrong." + } + ] + } + } +} diff --git a/{{cookiecutter.app_name}}/docs/openapi/openapi.yml b/{{cookiecutter.app_name}}/docs/openapi/openapi.yml new file mode 100644 index 0000000..9771c74 --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/openapi.yml @@ -0,0 +1,31 @@ +--- +openapi: 3.0.0 +info: + title: API Documentation + description: This is the API documentation for the mock server. + version: 1.0.0 + +servers: + - url: http://localhost:4010 + description: Mock server + +security: + - BearerAuth: [] + +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + schemas: + $ref: "schemas.yml" + responses: + $ref: "responses.yml" + +paths: + /health: + $ref: "paths/health.yml" + +tags: + - name: Status + description: Status APIs of the project diff --git a/{{cookiecutter.app_name}}/docs/openapi/paths/health.yml b/{{cookiecutter.app_name}}/docs/openapi/paths/health.yml new file mode 100644 index 0000000..541229b --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/paths/health.yml @@ -0,0 +1,20 @@ +--- +get: + tags: + - Status + security: [] + summary: Get the status of the application. + description: Call this API to get the status of the application. + + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../schemas.yml#/responses_health' + examples: + $ref: '../examples/responses/health.json' + + default: + $ref: '../responses.yml#/responses_default_error' diff --git a/{{cookiecutter.app_name}}/docs/openapi/request_bodies/.gitkeep b/{{cookiecutter.app_name}}/docs/openapi/request_bodies/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/{{cookiecutter.app_name}}/docs/openapi/responses.yml b/{{cookiecutter.app_name}}/docs/openapi/responses.yml new file mode 100644 index 0000000..6e4535e --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/responses.yml @@ -0,0 +1,4 @@ +--- + +responses_default_error: + $ref: "responses/default_error.yml" diff --git a/{{cookiecutter.app_name}}/docs/openapi/responses/default_error.yml b/{{cookiecutter.app_name}}/docs/openapi/responses/default_error.yml new file mode 100644 index 0000000..8ea2d5e --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/responses/default_error.yml @@ -0,0 +1,11 @@ +--- +description: Default Error + +content: + application/json: + schema: + $ref: '../schemas.yml#/error' + example: + errors: + - code: 'invalid_request' + detail: 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.' diff --git a/{{cookiecutter.app_name}}/docs/openapi/schemas.yml b/{{cookiecutter.app_name}}/docs/openapi/schemas.yml new file mode 100644 index 0000000..cf312d7 --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/schemas.yml @@ -0,0 +1,12 @@ +--- +#### REQUESTS #### + +#### RESPONSES #### + +responses_health: + $ref: "schemas/responses/health.yml" + +#### REUSABLE SCHEMAS #### + +error: + $ref: "schemas/shared/error.yml" diff --git a/{{cookiecutter.app_name}}/docs/openapi/schemas/requests/.gitkeep b/{{cookiecutter.app_name}}/docs/openapi/schemas/requests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/{{cookiecutter.app_name}}/docs/openapi/schemas/responses/health.yml b/{{cookiecutter.app_name}}/docs/openapi/schemas/responses/health.yml new file mode 100644 index 0000000..8d4a722 --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/schemas/responses/health.yml @@ -0,0 +1,24 @@ +--- +type: object + +description: A response body for the health API + +properties: + data: + type: object + description: The data object + properties: + id: + type: string + description: The identifier of the health + example: "123" + type: + type: string + description: The type of the health + example: 'health' + attributes: + type: object + properties: + message: + type: string + description: The message description of the status diff --git a/{{cookiecutter.app_name}}/docs/openapi/schemas/shared/error.yml b/{{cookiecutter.app_name}}/docs/openapi/schemas/shared/error.yml new file mode 100644 index 0000000..49f6461 --- /dev/null +++ b/{{cookiecutter.app_name}}/docs/openapi/schemas/shared/error.yml @@ -0,0 +1,15 @@ +type: object + +properties: + errors: + type: array + maxItems: 10 + items: + type: object + properties: + code: + type: string + description: an application-specific error code + detail: + type: string + description: "a human-readable explanation specific to this occurrence of the problem. Like title, this field's value can be localized." From 975e4f4277bd9c88cedf1113daff48578bb4bb35 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:13:12 +0700 Subject: [PATCH 11/43] [#105] Add dockerignore --- {{cookiecutter.app_name}}/.dockerignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 {{cookiecutter.app_name}}/.dockerignore diff --git a/{{cookiecutter.app_name}}/.dockerignore b/{{cookiecutter.app_name}}/.dockerignore new file mode 100644 index 0000000..9548f47 --- /dev/null +++ b/{{cookiecutter.app_name}}/.dockerignore @@ -0,0 +1,7 @@ +.github/ +.gitignore +{%- if cookiecutter._web_variant == "yes" || cookiecutter.use_openapi == "yes" -%} +node_modules/ +{% endif %} +docker-compose.dev.yml +README.md From 5e01de0e218af2c33750d20fb0638a1f27a57fcd Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:15:09 +0700 Subject: [PATCH 12/43] [#105] Fix condition --- {{cookiecutter.app_name}}/.dockerignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/.dockerignore b/{{cookiecutter.app_name}}/.dockerignore index 9548f47..a63dedd 100644 --- a/{{cookiecutter.app_name}}/.dockerignore +++ b/{{cookiecutter.app_name}}/.dockerignore @@ -1,6 +1,6 @@ .github/ .gitignore -{%- if cookiecutter._web_variant == "yes" || cookiecutter.use_openapi == "yes" -%} +{%- if cookiecutter._web_variant == "yes" ors cookiecutter.use_openapi == "yes" -%} node_modules/ {% endif %} docker-compose.dev.yml From ec55e2fb1e3e2edeaf4ab0f346b838abc2c7ed42 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:15:28 +0700 Subject: [PATCH 13/43] [#105] Fix typo --- {{cookiecutter.app_name}}/.dockerignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/.dockerignore b/{{cookiecutter.app_name}}/.dockerignore index a63dedd..4e5f9af 100644 --- a/{{cookiecutter.app_name}}/.dockerignore +++ b/{{cookiecutter.app_name}}/.dockerignore @@ -1,6 +1,6 @@ .github/ .gitignore -{%- if cookiecutter._web_variant == "yes" ors cookiecutter.use_openapi == "yes" -%} +{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" -%} node_modules/ {% endif %} docker-compose.dev.yml From 727eb96abce745fa2872d35a0d951733147276f3 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:35:35 +0700 Subject: [PATCH 14/43] [#105] Add set up for openapi --- hooks/post_gen_project.py | 19 ++++++++++++++++-- {{cookiecutter.app_name}}/.dockerignore | 2 -- {{cookiecutter.app_name}}/.eslintignore | 2 ++ {{cookiecutter.app_name}}/.eslintrc.json | 13 ++++++++++++ {{cookiecutter.app_name}}/.gitignore | 5 +++++ {{cookiecutter.app_name}}/.spectral.yaml | 6 ++++++ {{cookiecutter.app_name}}/.tool-versions | 3 +++ {{cookiecutter.app_name}}/Makefile | 6 ++++++ {{cookiecutter.app_name}}/package.json | 25 +++++++++++++++++++++--- 9 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 {{cookiecutter.app_name}}/.eslintignore create mode 100644 {{cookiecutter.app_name}}/.spectral.yaml diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 7d0ed20..7eae55f 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -90,13 +90,28 @@ def init_git(message): remove_files('lib/web') # Config files - remove_file('.eslintrc.json') remove_file('.npmrc') - remove_file('package.json') remove_file('snowpack.config.js') remove_file('postcss.config.js') remove_file('tsconfig.json') + # Remove if openapi is not selected + if '{{ cookiecutter.use_openapi }}' == 'no': + remove_file('.eslintrc.json') + remove_file('package.json') + +# Remove openapi if not seleted +if '{{ cookiecutter.use_openapi }}' == 'no': + print_log('Removing openapi') + + # docs folder + remove_files("docs") + + # openapi related files + remove_file(".dockerignore") + remove_file(".eslintignore") + remove_file(".spectral.yaml") + # Download the missing dependencies print_log('Downloading dependencies') subprocess.call(['go', 'mod', 'tidy']) diff --git a/{{cookiecutter.app_name}}/.dockerignore b/{{cookiecutter.app_name}}/.dockerignore index 4e5f9af..e205a7d 100644 --- a/{{cookiecutter.app_name}}/.dockerignore +++ b/{{cookiecutter.app_name}}/.dockerignore @@ -1,7 +1,5 @@ .github/ .gitignore -{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" -%} node_modules/ -{% endif %} docker-compose.dev.yml README.md diff --git a/{{cookiecutter.app_name}}/.eslintignore b/{{cookiecutter.app_name}}/.eslintignore new file mode 100644 index 0000000..32652b7 --- /dev/null +++ b/{{cookiecutter.app_name}}/.eslintignore @@ -0,0 +1,2 @@ +/node_modules/** +/public/** diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index e66bffa..21e0a32 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -1,3 +1,4 @@ +{% if cookiecutter._web_variant == "yes" %} { "rules": {}, "env": { @@ -18,3 +19,15 @@ "SharedArrayBuffer": "readonly" } } +{% endif %} +{% if cookiecutter.use_openapi == "yes" %} +{ + "extends": [ + "@nimblehq/eslint-config-nimble", + "plugin:yml/recommended" + ], + "globals": { + "I18n": true + } +} +{% endif %} diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index a8945ed..4e6e019 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -10,3 +10,8 @@ deploy/**/terraform.tfstate deploy/**/terraform.tfstate.backup deploy/**/*.tfvars {%- endif %} + +{% if cookiecutter.use_openapi == "yes" %} +## OpenAPI +/public/openapi.yml +{% endif %} \ No newline at end of file diff --git a/{{cookiecutter.app_name}}/.spectral.yaml b/{{cookiecutter.app_name}}/.spectral.yaml new file mode 100644 index 0000000..ae54600 --- /dev/null +++ b/{{cookiecutter.app_name}}/.spectral.yaml @@ -0,0 +1,6 @@ +extends: ["spectral:oas"] + +rules: + oas3-unused-component: false + operation-operationId: false + info-contact: false diff --git a/{{cookiecutter.app_name}}/.tool-versions b/{{cookiecutter.app_name}}/.tool-versions index f3ab914..3baa070 100644 --- a/{{cookiecutter.app_name}}/.tool-versions +++ b/{{cookiecutter.app_name}}/.tool-versions @@ -1 +1,4 @@ golang 1.20 +{% if cookiecutter.use_openapi == "yes" %} +nodejs 18.15.0 +{% endif %} diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 14a2554..a7da935 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -28,6 +28,11 @@ endif migration/status: goose -dir database/migrations -table "migration_versions" postgres "$(DATABASE_URL)" status +{% if cookiecutter.use_openapi == "yes" %} +doc/generate: + npm run build:docs +{% endif %} + dev: make env-setup make db/migrate @@ -39,6 +44,7 @@ install-dependencies: go install github.com/ddollar/forego@latest go mod tidy {% if cookiecutter._web_variant == "yes" %}npm install{% endif %} + {% if cookiecutter.use_openapi == "yes" %}make doc/generate{% endif %} test: docker compose -f docker-compose.test.yml up -d diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index c3d848f..c337399 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -6,16 +6,28 @@ "author": "NimbleHQ", "license": "MIT", "scripts": { + {% if cookiecutter._web_variant == "yes" %} "dev": "NODE_ENV=development MODE=development snowpack build --watch --no-minify --no-bundle", "build": "snowpack build", - "clean": "rm -rf static" + "clean": "rm -rf static", + {% endif %} + {% if cookiecutter.use_openapi == "yes" %} + "lint:docs:yml": "eslint docs/openapi --ext .yml --color", + "lint:docs:openapi": "spectral lint docs/openapi/openapi.yml -F error", + "lint:docs:dev": "yarn lint:docs:yml && yarn lint:docs:openapi", + "lint:docs:public": "yarn build:docs && eslint public/openapi.yml --color --no-ignore && spectral lint public/openapi.yml -F error", + "build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml", + {% endif %} }, "devDependencies": { + {% if cookiecutter._web_variant == "yes" %} "@snowpack/plugin-postcss": "1.4.3", "@snowpack/plugin-sass": "1.4.0", "@types/node": "15.12.5", - "autoprefixer": "10.2.6",{% if cookiecutter._bootstrap_addon == "yes" %} - "bootstrap": "5.0.2",{% endif %} + "autoprefixer": "10.2.6", + {% if cookiecutter._bootstrap_addon == "yes" %} + "bootstrap": "5.0.2", + {% endif %} "eslint": "7.29.0", "eslint-config-prettier": "8.3.0", "eslint-plugin-prettier": "3.4.0", @@ -23,5 +35,12 @@ "prettier": "2.3.2", "snowpack": "3.7.1"{% if cookiecutter._tailwind_addon == "yes" %}, "tailwindcss": "2.2.7"{% endif %} + {% endif %} + {% if cookiecutter.use_openapi == "yes" %} + "@apidevtools/swagger-cli": "4.0.4", + "@nimblehq/eslint-config-nimble": "2.1.1", + "@stoplight/spectral-cli": "6.8.0", + "eslint-plugin-yml": "1.8.0" + {% endif %} } } From 5b093de31957b296c65edc00ccff4c23e2ebf17e Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:45:22 +0700 Subject: [PATCH 15/43] [#105] Fix indents --- {{cookiecutter.app_name}}/.eslintrc.json | 11 +++-------- {{cookiecutter.app_name}}/.tool-versions | 6 ++---- {{cookiecutter.app_name}}/Makefile | 6 ++---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index 21e0a32..5bdc45d 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -1,5 +1,4 @@ -{% if cookiecutter._web_variant == "yes" %} -{ +{% if cookiecutter._web_variant == "yes" %}{ "rules": {}, "env": { "es6": true, @@ -18,10 +17,7 @@ "Atomics": "readonly", "SharedArrayBuffer": "readonly" } -} -{% endif %} -{% if cookiecutter.use_openapi == "yes" %} -{ +}{% endif %}{% if cookiecutter.use_openapi == "yes" %}{ "extends": [ "@nimblehq/eslint-config-nimble", "plugin:yml/recommended" @@ -29,5 +25,4 @@ "globals": { "I18n": true } -} -{% endif %} +}{% endif %} diff --git a/{{cookiecutter.app_name}}/.tool-versions b/{{cookiecutter.app_name}}/.tool-versions index 3baa070..e86ac1e 100644 --- a/{{cookiecutter.app_name}}/.tool-versions +++ b/{{cookiecutter.app_name}}/.tool-versions @@ -1,4 +1,2 @@ -golang 1.20 -{% if cookiecutter.use_openapi == "yes" %} -nodejs 18.15.0 -{% endif %} +golang 1.20{% if cookiecutter.use_openapi == "yes" %} +nodejs 18.15.0{% endif %} diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index a7da935..3eb0994 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -28,10 +28,8 @@ endif migration/status: goose -dir database/migrations -table "migration_versions" postgres "$(DATABASE_URL)" status -{% if cookiecutter.use_openapi == "yes" %} -doc/generate: - npm run build:docs -{% endif %} +{% if cookiecutter.use_openapi == "yes" %}doc/generate: + npm run build:docs{% endif %} dev: make env-setup From e9210add914991e3d52cf8e9a2143d206a7d3ce6 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:49:27 +0700 Subject: [PATCH 16/43] [#105] Add `-` for cookiecutter --- {{cookiecutter.app_name}}/.gitignore | 4 ++-- {{cookiecutter.app_name}}/package.json | 24 +++++++++++------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index 4e6e019..f5380bf 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -11,7 +11,7 @@ deploy/**/terraform.tfstate.backup deploy/**/*.tfvars {%- endif %} -{% if cookiecutter.use_openapi == "yes" %} +{%- if cookiecutter.use_openapi == "yes" %} ## OpenAPI /public/openapi.yml -{% endif %} \ No newline at end of file +{%- endif %} diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index c337399..4796f56 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -6,28 +6,26 @@ "author": "NimbleHQ", "license": "MIT", "scripts": { - {% if cookiecutter._web_variant == "yes" %} + {%- if cookiecutter._web_variant == "yes" %} "dev": "NODE_ENV=development MODE=development snowpack build --watch --no-minify --no-bundle", "build": "snowpack build", "clean": "rm -rf static", - {% endif %} - {% if cookiecutter.use_openapi == "yes" %} + {%- endif %} + {%- if cookiecutter.use_openapi == "yes" %} "lint:docs:yml": "eslint docs/openapi --ext .yml --color", "lint:docs:openapi": "spectral lint docs/openapi/openapi.yml -F error", "lint:docs:dev": "yarn lint:docs:yml && yarn lint:docs:openapi", "lint:docs:public": "yarn build:docs && eslint public/openapi.yml --color --no-ignore && spectral lint public/openapi.yml -F error", - "build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml", - {% endif %} + "build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml" + {%- endif %} }, "devDependencies": { - {% if cookiecutter._web_variant == "yes" %} + {%- if cookiecutter._web_variant == "yes" %} "@snowpack/plugin-postcss": "1.4.3", "@snowpack/plugin-sass": "1.4.0", "@types/node": "15.12.5", - "autoprefixer": "10.2.6", - {% if cookiecutter._bootstrap_addon == "yes" %} - "bootstrap": "5.0.2", - {% endif %} + "autoprefixer": "10.2.6",{% if cookiecutter._bootstrap_addon == "yes" %} + "bootstrap": "5.0.2",{% endif %} "eslint": "7.29.0", "eslint-config-prettier": "8.3.0", "eslint-plugin-prettier": "3.4.0", @@ -35,12 +33,12 @@ "prettier": "2.3.2", "snowpack": "3.7.1"{% if cookiecutter._tailwind_addon == "yes" %}, "tailwindcss": "2.2.7"{% endif %} - {% endif %} - {% if cookiecutter.use_openapi == "yes" %} + {%- endif %} + {%- if cookiecutter.use_openapi == "yes" %} "@apidevtools/swagger-cli": "4.0.4", "@nimblehq/eslint-config-nimble": "2.1.1", "@stoplight/spectral-cli": "6.8.0", "eslint-plugin-yml": "1.8.0" - {% endif %} + {%- endif %} } } From 6217f93233845688797766ccca899d984006368b Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:53:13 +0700 Subject: [PATCH 17/43] [#105] Improve syntax --- {{cookiecutter.app_name}}/Makefile | 10 ++++++---- {{cookiecutter.app_name}}/package.json | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 3eb0994..184e09b 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -28,8 +28,10 @@ endif migration/status: goose -dir database/migrations -table "migration_versions" postgres "$(DATABASE_URL)" status -{% if cookiecutter.use_openapi == "yes" %}doc/generate: - npm run build:docs{% endif %} +{%- if cookiecutter.use_openapi == "yes" %} +doc/generate: + npm run build:docs +{%- endif %} dev: make env-setup @@ -41,8 +43,8 @@ install-dependencies: go install github.com/pressly/goose/v3/cmd/goose@v3.9.0 go install github.com/ddollar/forego@latest go mod tidy - {% if cookiecutter._web_variant == "yes" %}npm install{% endif %} - {% if cookiecutter.use_openapi == "yes" %}make doc/generate{% endif %} + {%- if cookiecutter._web_variant == "yes" %}npm install{% endif %} + {%- if cookiecutter.use_openapi == "yes" %}make doc/generate{% endif %} test: docker compose -f docker-compose.test.yml up -d diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index 4796f56..69ba928 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -9,7 +9,7 @@ {%- if cookiecutter._web_variant == "yes" %} "dev": "NODE_ENV=development MODE=development snowpack build --watch --no-minify --no-bundle", "build": "snowpack build", - "clean": "rm -rf static", + "clean": "rm -rf static"{%- if cookiecutter.use_openapi == "yes" %},{%- endif %} {%- endif %} {%- if cookiecutter.use_openapi == "yes" %} "lint:docs:yml": "eslint docs/openapi --ext .yml --color", From 95b3d25fe9cebf77e8dcf7d93ef94df473f70f6e Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 16:58:19 +0700 Subject: [PATCH 18/43] [#105] Improve command --- {{cookiecutter.app_name}}/.gitignore | 6 ++++-- {{cookiecutter.app_name}}/package.json | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index f5380bf..ad5b399 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -1,5 +1,7 @@ -{% if cookiecutter._web_variant == "yes" %}/node_modules -{% endif %}tmp/ +{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" %} +/node_modules +{%- endif %} +tmp/ coverage/ .env diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index 69ba928..52b197b 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -14,8 +14,8 @@ {%- if cookiecutter.use_openapi == "yes" %} "lint:docs:yml": "eslint docs/openapi --ext .yml --color", "lint:docs:openapi": "spectral lint docs/openapi/openapi.yml -F error", - "lint:docs:dev": "yarn lint:docs:yml && yarn lint:docs:openapi", - "lint:docs:public": "yarn build:docs && eslint public/openapi.yml --color --no-ignore && spectral lint public/openapi.yml -F error", + "lint:docs:dev": "npm lint:docs:yml && npm lint:docs:openapi", + "lint:docs:public": "npm build:docs && eslint public/openapi.yml --color --no-ignore && spectral lint public/openapi.yml -F error", "build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml" {%- endif %} }, From 949647ff7303167cffb1c725d4a85454d76964ff Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 17:12:43 +0700 Subject: [PATCH 19/43] [#105] Improve configuration --- cookiecutter.json | 1 + hooks/post_gen_project.py | 3 +++ hooks/pre_gen_project.py | 14 ++++++++++++++ {{cookiecutter.app_name}}/.gitignore | 3 +-- {{cookiecutter.app_name}}/docs/openapi/openapi.yml | 4 ++-- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cookiecutter.json b/cookiecutter.json index ebbb7a5..5b9c487 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -8,6 +8,7 @@ "_api_variant": "no", "_web_variant": "no", + "_only_web_variant": "no", "_bootstrap_addon": "no", "_tailwind_addon": "no" } diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 7eae55f..7606ac9 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -116,6 +116,9 @@ def init_git(message): print_log('Downloading dependencies') subprocess.call(['go', 'mod', 'tidy']) +if '{{ cookiecutter._web_variant }}' == 'yes' or '{{ cookiecutter.use_openapi }}' == 'yes': + subprocess.call(['npm', 'install']) + # Format code print_log('Formating code') subprocess.call(['go', 'fmt', './...']) diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 679ccaa..20c76b8 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -5,11 +5,16 @@ Web/API Variant cookiecutter._web_variant cookiecutter._api_variant +cookiecutter._only_web_variant ----------- {% if cookiecutter.variant in ['Web only', 'Both'] %} {{ cookiecutter.update({ '_web_variant': 'yes' }) }} {% endif %} +{% if cookiecutter.variant == 'Web only' %} + {{ cookiecutter.update({ '_only_web_variant': 'yes' }) }} +{% endif %} + API Variant {% if cookiecutter.variant in ['API only', 'Both'] %} {{ cookiecutter.update({ '_api_variant': 'yes' }) }} @@ -28,4 +33,13 @@ {{ cookiecutter.update({ '_tailwind_addon': 'yes' }) }} {% endif %} {% endif %} + +----------- +OpenAPI +cookiecutter.use_openapi +----------- +Only project with web only: +{% if cookiecutter._only_web_variant == 'yes' %} + {{ cookiecutter.update({ 'use_openapi': 'no' }) }} +{% endif %} ''' diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index ad5b399..638ec62 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -1,5 +1,4 @@ -{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" %} -/node_modules +{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" %}/node_modules {%- endif %} tmp/ coverage/ diff --git a/{{cookiecutter.app_name}}/docs/openapi/openapi.yml b/{{cookiecutter.app_name}}/docs/openapi/openapi.yml index 9771c74..26c78e6 100644 --- a/{{cookiecutter.app_name}}/docs/openapi/openapi.yml +++ b/{{cookiecutter.app_name}}/docs/openapi/openapi.yml @@ -6,8 +6,8 @@ info: version: 1.0.0 servers: - - url: http://localhost:4010 - description: Mock server + - url: http://localhost:8080/api/v1 + description: Development Base URL security: - BearerAuth: [] From 19379fda5ced2087c707e217cd667e488f1588ed Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 17:22:25 +0700 Subject: [PATCH 20/43] [#105] Add lint CI --- hooks/post_gen_project.py | 1 + .../.github/workflows/lint_docs.yml | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 {{cookiecutter.app_name}}/.github/workflows/lint_docs.yml diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 7606ac9..7272091 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -111,6 +111,7 @@ def init_git(message): remove_file(".dockerignore") remove_file(".eslintignore") remove_file(".spectral.yaml") + remove_file(".github/workflows/lint_docs.yml") # Download the missing dependencies print_log('Downloading dependencies') diff --git a/{{cookiecutter.app_name}}/.github/workflows/lint_docs.yml b/{{cookiecutter.app_name}}/.github/workflows/lint_docs.yml new file mode 100644 index 0000000..6ae056e --- /dev/null +++ b/{{cookiecutter.app_name}}/.github/workflows/lint_docs.yml @@ -0,0 +1,31 @@ +name: Lint OpenAPI docs + +on: pull_request + +concurrency: + group: {{ "${{ github.workflow }}-${{ github.ref }}" }} + cancel-in-progress: true + +jobs: + docs_lint: + name: Run lint for API docs + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up node and restore cached dependencies + uses: actions/setup-node@v3 + with: + node-version: "18.x" + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies + run: npm install + + - name: Generate API docs + run: npm run build:docs + + - name: Run API docs linters + run: npm run lint:docs:public From 4b33ed62abc638efdcc2e1011b57330d59c700f2 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 17:31:33 +0700 Subject: [PATCH 21/43] [#105] Fix the wrong setup for both web and api --- {{cookiecutter.app_name}}/.eslintrc.json | 9 ++++----- {{cookiecutter.app_name}}/Makefile | 3 +-- {{cookiecutter.app_name}}/package.json | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index 5bdc45d..3e39faa 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -11,7 +11,9 @@ }, "extends": [ "eslint:recommended", - "plugin:prettier/recommended" + "plugin:prettier/recommended"{% if cookiecutter.use_openapi == "yes" %}, + "@nimblehq/eslint-config-nimble", + "plugin:yml/recommended"{% endif %} ], "globals": { "Atomics": "readonly", @@ -21,8 +23,5 @@ "extends": [ "@nimblehq/eslint-config-nimble", "plugin:yml/recommended" - ], - "globals": { - "I18n": true - } + ] }{% endif %} diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 184e09b..475552b 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -28,8 +28,7 @@ endif migration/status: goose -dir database/migrations -table "migration_versions" postgres "$(DATABASE_URL)" status -{%- if cookiecutter.use_openapi == "yes" %} -doc/generate: +{% if cookiecutter.use_openapi == "yes" %}doc/generate: npm run build:docs {%- endif %} diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index 52b197b..bf224f4 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -32,7 +32,7 @@ "postcss": "8.3.5", "prettier": "2.3.2", "snowpack": "3.7.1"{% if cookiecutter._tailwind_addon == "yes" %}, - "tailwindcss": "2.2.7"{% endif %} + "tailwindcss": "2.2.7"{% endif %}{%- if cookiecutter.use_openapi == "yes" %},{%- endif %} {%- endif %} {%- if cookiecutter.use_openapi == "yes" %} "@apidevtools/swagger-cli": "4.0.4", From 4eae88027266bf889cfe1bc634ccd6ea2b1ecd06 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 17:35:20 +0700 Subject: [PATCH 22/43] [#105] Add support eslint --- {{cookiecutter.app_name}}/.eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index 3e39faa..4f0b6f8 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -19,7 +19,7 @@ "Atomics": "readonly", "SharedArrayBuffer": "readonly" } -}{% endif %}{% if cookiecutter.use_openapi == "yes" %}{ +}{% endif %}{% if cookiecutter._api_variant == "yes" and cookiecutter.use_openapi == "yes" %}{ "extends": [ "@nimblehq/eslint-config-nimble", "plugin:yml/recommended" From da3b5961afd2ad3a55337e825f5217091fe69721 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 17:44:53 +0700 Subject: [PATCH 23/43] [#105] Add both variant to easy to check the logic --- cookiecutter.json | 1 + hooks/pre_gen_project.py | 6 +++++- {{cookiecutter.app_name}}/.eslintrc.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cookiecutter.json b/cookiecutter.json index 5b9c487..3e57137 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -8,6 +8,7 @@ "_api_variant": "no", "_web_variant": "no", + "_both_variant": "no", "_only_web_variant": "no", "_bootstrap_addon": "no", "_tailwind_addon": "no" diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 20c76b8..c5bac06 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -6,6 +6,7 @@ cookiecutter._web_variant cookiecutter._api_variant cookiecutter._only_web_variant +cookiecutter._both_variant ----------- {% if cookiecutter.variant in ['Web only', 'Both'] %} {{ cookiecutter.update({ '_web_variant': 'yes' }) }} @@ -15,11 +16,14 @@ {{ cookiecutter.update({ '_only_web_variant': 'yes' }) }} {% endif %} -API Variant {% if cookiecutter.variant in ['API only', 'Both'] %} {{ cookiecutter.update({ '_api_variant': 'yes' }) }} {% endif %} +{% if cookiecutter.variant == 'Both' %} + {{ cookiecutter.update({ '_both_variant': 'yes' }) }} +{% endif %} + ----------- CSS Addons cookiecutter._bootstrap_addon diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index 4f0b6f8..10cd9cd 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -19,7 +19,7 @@ "Atomics": "readonly", "SharedArrayBuffer": "readonly" } -}{% endif %}{% if cookiecutter._api_variant == "yes" and cookiecutter.use_openapi == "yes" %}{ +}{% endif %}{% if cookiecutter._both_variant == "no" and cookiecutter.use_openapi == "yes" %}{ "extends": [ "@nimblehq/eslint-config-nimble", "plugin:yml/recommended" From 8bfbff2ea117eca0c4d42342ddd9c82aebeabd1c Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 11 Aug 2023 18:04:38 +0700 Subject: [PATCH 24/43] [#105] Add tests for docs/openapi --- cmd/create_test.go | 52 +++++++++++++++++++++++++++++ tests/cookiecutter.go | 15 ++++++--- {{cookiecutter.app_name}}/Makefile | 4 +-- {{cookiecutter.app_name}}/README.md | 9 +++++ 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index de2dddd..641bcd3 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1012,4 +1012,56 @@ var _ = Describe("Create template", func() { Expect(content).NotTo(ContainSubstring(expectedContent)) }) }) + + Context("given openapi add-on", func() { + It("contains docs/openapi folder", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("docs/openapi") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains OpenAPI instruction in README", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("README.md") + + expectedContent := "Generate API documentation" + + Expect(content).To(ContainSubstring(expectedContent)) + }) + }) + + Context("given NO heroku add-on", func() { + It("does NOT contains docs/openapi folder", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("docs/openapi") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains OpenAPI instruction in README", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("README.md") + + expectedContent := "Generate API documentation" + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + }) }) diff --git a/tests/cookiecutter.go b/tests/cookiecutter.go index eead37e..4cb1fa9 100644 --- a/tests/cookiecutter.go +++ b/tests/cookiecutter.go @@ -25,11 +25,12 @@ const ( // Field and order MUST be the same as cookiecutter.json type Cookiecutter struct { - AppName string - Variant Variants - CssAddon CssAddons - UseLogrus Choices - UseHeroku Choices + AppName string + Variant Variants + CssAddon CssAddons + UseLogrus Choices + UseHeroku Choices + UseOpenAPI Choices } func (c *Cookiecutter) fillDefaultValue() { @@ -45,6 +46,10 @@ func (c *Cookiecutter) fillDefaultValue() { c.UseHeroku = No } + if c.UseOpenAPI != Yes && c.UseOpenAPI != No { + c.UseOpenAPI = No + } + if c.CssAddon != Bootstrap && c.CssAddon != Tailwind && c.CssAddon != None { c.CssAddon = None } diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 475552b..84620a5 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -42,8 +42,8 @@ install-dependencies: go install github.com/pressly/goose/v3/cmd/goose@v3.9.0 go install github.com/ddollar/forego@latest go mod tidy - {%- if cookiecutter._web_variant == "yes" %}npm install{% endif %} - {%- if cookiecutter.use_openapi == "yes" %}make doc/generate{% endif %} + {% if cookiecutter._web_variant == "yes" %}npm install{% endif %} + {% if cookiecutter.use_openapi == "yes" %}make doc/generate{%- endif %} test: docker compose -f docker-compose.test.yml up -d diff --git a/{{cookiecutter.app_name}}/README.md b/{{cookiecutter.app_name}}/README.md index 0546d08..e973b50 100644 --- a/{{cookiecutter.app_name}}/README.md +++ b/{{cookiecutter.app_name}}/README.md @@ -50,6 +50,15 @@ Execute all unit tests: ```make make test ``` +{%- if cookiecutter.use_openapi == "yes" %} +### API Documentation + +Generate API documentation: + +```make +make doc/generate +``` +{%- endif %} ### Migration From 81a550bcfe4e37d930e25759c870fd807a86f085 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 09:41:34 +0700 Subject: [PATCH 25/43] [#105] Fix tests --- cmd/create_test.go | 6 +++--- hooks/post_gen_project.py | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index 641bcd3..142640e 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1039,11 +1039,11 @@ var _ = Describe("Create template", func() { }) }) - Context("given NO heroku add-on", func() { + Context("given NO openapi add-on", func() { It("does NOT contains docs/openapi folder", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + UseOpenAPI: tests.No, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat("docs/openapi") @@ -1054,7 +1054,7 @@ var _ = Describe("Create template", func() { It("does NOT contains OpenAPI instruction in README", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + UseOpenAPI: tests.No, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile("README.md") diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 7272091..09e08f7 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -117,9 +117,6 @@ def init_git(message): print_log('Downloading dependencies') subprocess.call(['go', 'mod', 'tidy']) -if '{{ cookiecutter._web_variant }}' == 'yes' or '{{ cookiecutter.use_openapi }}' == 'yes': - subprocess.call(['npm', 'install']) - # Format code print_log('Formating code') subprocess.call(['go', 'fmt', './...']) From a429cda351cb25af62fc47f607a65e902c4535b3 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 10:52:08 +0700 Subject: [PATCH 26/43] [#105] Add tests for OpenAPI add-on --- cmd/create_test.go | 274 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 273 insertions(+), 1 deletion(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index 142640e..e3c4212 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1014,6 +1014,54 @@ var _ = Describe("Create template", func() { }) Context("given openapi add-on", func() { + Context("given only Web variant", func() { + It("does NOT contains openapi requirement in .eslintrc.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.Web, + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".eslintrc.json") + + expectedContent := `plugin:yml/recommended` + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + }) + + Context("given only API variant", func() { + It("contains openapi requirement in .eslintrc.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.API, + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".eslintrc.json") + + expectedContent := `plugin:yml/recommended` + + Expect(content).To(ContainSubstring(expectedContent)) + }) + }) + + Context("given both variant", func() { + It("contains openapi requirement in .eslintrc.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.Both, + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".eslintrc.json") + + expectedContent := `plugin:yml/recommended` + + Expect(content).To(ContainSubstring(expectedContent)) + }) + }) + It("contains docs/openapi folder", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", @@ -1025,7 +1073,7 @@ var _ = Describe("Create template", func() { Expect(os.IsNotExist(err)).To(BeFalse()) }) - It("contains OpenAPI instruction in README", func() { + It("contains openapi instruction in README", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", UseOpenAPI: tests.Yes, @@ -1037,12 +1085,164 @@ var _ = Describe("Create template", func() { Expect(content).To(ContainSubstring(expectedContent)) }) + + It("contains .dockerignore file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".dockerignore") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains .eslintignore file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".eslintignore") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains .github/workflows/lint_docs.yml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".github/workflows/lint_docs.yml") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains openapi requirement in .gitignore", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".gitignore") + + expectedContent := "/public/openapi.yml" + + Expect(content).To(ContainSubstring(expectedContent)) + }) + + It("contains .spectral.yaml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".spectral.yaml") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains openapi requirement in .tool-versions", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".tool-versions") + + expectedContent := "nodejs 18.15.0" + + Expect(content).To(ContainSubstring(expectedContent)) + }) + + It("contains openapi requirement in Makefile", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("Makefile") + + expectedContent := "npm run build:docs" + + Expect(content).To(ContainSubstring(expectedContent)) + }) + + It("contains openapi requirement in package.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("package.json") + + expectedContent := `"build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml"` + + Expect(content).To(ContainSubstring(expectedContent)) + }) }) Context("given NO openapi add-on", func() { + Context("given only Web variant", func() { + It("does NOT contains openapi requirement in .eslintrc.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.Web, + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".eslintrc.json") + + expectedContent := `plugin:yml/recommended` + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + + It("does NOT contains openapi requirement in package.json", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.Web, + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("package.json") + + expectedContent := `"build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml"` + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + }) + + Context("given only API variant", func() { + It("does NOT contains .eslintrc.json file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + Variant: tests.API, + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".eslintrc.json") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains package.json file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("package.json") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + }) + It("does NOT contains docs/openapi folder", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", + Variant: tests.API, UseOpenAPI: tests.No, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) @@ -1063,5 +1263,77 @@ var _ = Describe("Create template", func() { Expect(content).NotTo(ContainSubstring(expectedContent)) }) + + It("does NOT contains .dockerignore file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".dockerignore") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains .github/workflows/lint_docs.yml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".github/workflows/lint_docs.yml") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains openapi requirement in .gitignore", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".gitignore") + + expectedContent := "/public/openapi.yml" + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + + It("does NOT contains .spectral.yaml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".spectral.yaml") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains openapi requirement in .tool-versions", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile(".tool-versions") + + expectedContent := "nodejs 18.15.0" + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) + + It("does NOT contains openapi requirement in Makefile", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseOpenAPI: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("Makefile") + + expectedContent := "npm run build:docs" + + Expect(content).NotTo(ContainSubstring(expectedContent)) + }) }) }) From 65b389d6662b178adef4f418e8d8d81376e7ccda Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 16 Aug 2023 10:37:33 +0700 Subject: [PATCH 27/43] [#105] Improve the logic for only web variant --- cookiecutter.json | 1 - hooks/pre_gen_project.py | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cookiecutter.json b/cookiecutter.json index 3e57137..a0fdb62 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -9,7 +9,6 @@ "_api_variant": "no", "_web_variant": "no", "_both_variant": "no", - "_only_web_variant": "no", "_bootstrap_addon": "no", "_tailwind_addon": "no" } diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index c5bac06..98e4347 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -5,17 +5,12 @@ Web/API Variant cookiecutter._web_variant cookiecutter._api_variant -cookiecutter._only_web_variant cookiecutter._both_variant ----------- {% if cookiecutter.variant in ['Web only', 'Both'] %} {{ cookiecutter.update({ '_web_variant': 'yes' }) }} {% endif %} -{% if cookiecutter.variant == 'Web only' %} - {{ cookiecutter.update({ '_only_web_variant': 'yes' }) }} -{% endif %} - {% if cookiecutter.variant in ['API only', 'Both'] %} {{ cookiecutter.update({ '_api_variant': 'yes' }) }} {% endif %} @@ -43,7 +38,7 @@ cookiecutter.use_openapi ----------- Only project with web only: -{% if cookiecutter._only_web_variant == 'yes' %} +{% if cookiecutter._web_variant == 'yes' and cookiecutter._both_variant == 'no' %} {{ cookiecutter.update({ 'use_openapi': 'no' }) }} {% endif %} ''' From a122d4e34c961013e1bf7165c1d9657432c455e1 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 11:11:15 +0700 Subject: [PATCH 28/43] [#105] Optimize logic without `_both_variant` or `use_openapi` option --- cmd/create_test.go | 234 ++--------------------- cookiecutter.json | 2 - hooks/post_gen_project.py | 7 +- hooks/pre_gen_project.py | 14 -- tests/cookiecutter.go | 15 +- {{cookiecutter.app_name}}/.eslintrc.json | 4 +- {{cookiecutter.app_name}}/.gitignore | 5 +- {{cookiecutter.app_name}}/.tool-versions | 4 +- {{cookiecutter.app_name}}/Makefile | 6 +- {{cookiecutter.app_name}}/README.md | 2 +- {{cookiecutter.app_name}}/package.json | 8 +- 11 files changed, 36 insertions(+), 265 deletions(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index e3c4212..c1cf618 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -690,17 +690,6 @@ var _ = Describe("Create template", func() { Expect(os.IsNotExist(err)).To(BeTrue()) }) - It("does NOT contain .eslintrc.json file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat(".eslintrc.json") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - It("does NOT contain .npmrc file", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", @@ -712,17 +701,6 @@ var _ = Describe("Create template", func() { Expect(os.IsNotExist(err)).To(BeTrue()) }) - It("does NOT contain package.json file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat("package.json") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - It("does NOT contain snowpack.config.js file", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", @@ -782,19 +760,6 @@ var _ = Describe("Create template", func() { Expect(content).NotTo(ContainSubstring(expectedContent)) }) - It("does NOT contain npm install in Makefile", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("Makefile") - - expectedContent := "npm install" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - It("does NOT contain Node 14 in README.md", func() { cookiecutter := tests.Cookiecutter{ AppName: "test-gin-templates", @@ -1017,9 +982,8 @@ var _ = Describe("Create template", func() { Context("given only Web variant", func() { It("does NOT contains openapi requirement in .eslintrc.json", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.Web, - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", + Variant: tests.Web, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile(".eslintrc.json") @@ -1033,9 +997,8 @@ var _ = Describe("Create template", func() { Context("given only API variant", func() { It("contains openapi requirement in .eslintrc.json", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", + Variant: tests.API, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile(".eslintrc.json") @@ -1049,9 +1012,8 @@ var _ = Describe("Create template", func() { Context("given both variant", func() { It("contains openapi requirement in .eslintrc.json", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.Both, - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", + Variant: tests.Both, } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile(".eslintrc.json") @@ -1064,8 +1026,7 @@ var _ = Describe("Create template", func() { It("contains docs/openapi folder", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat("docs/openapi") @@ -1075,8 +1036,7 @@ var _ = Describe("Create template", func() { It("contains openapi instruction in README", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile("README.md") @@ -1088,8 +1048,7 @@ var _ = Describe("Create template", func() { It("contains .dockerignore file", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat(".dockerignore") @@ -1099,8 +1058,7 @@ var _ = Describe("Create template", func() { It("contains .eslintignore file", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat(".eslintignore") @@ -1110,8 +1068,7 @@ var _ = Describe("Create template", func() { It("contains .github/workflows/lint_docs.yml file", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat(".github/workflows/lint_docs.yml") @@ -1121,8 +1078,7 @@ var _ = Describe("Create template", func() { It("contains openapi requirement in .gitignore", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile(".gitignore") @@ -1134,8 +1090,7 @@ var _ = Describe("Create template", func() { It("contains .spectral.yaml file", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) _, err := os.Stat(".spectral.yaml") @@ -1145,8 +1100,7 @@ var _ = Describe("Create template", func() { It("contains openapi requirement in .tool-versions", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile(".tool-versions") @@ -1158,8 +1112,7 @@ var _ = Describe("Create template", func() { It("contains openapi requirement in Makefile", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile("Makefile") @@ -1171,8 +1124,7 @@ var _ = Describe("Create template", func() { It("contains openapi requirement in package.json", func() { cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.Yes, + AppName: "test-gin-templates", } cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile("package.json") @@ -1182,158 +1134,4 @@ var _ = Describe("Create template", func() { Expect(content).To(ContainSubstring(expectedContent)) }) }) - - Context("given NO openapi add-on", func() { - Context("given only Web variant", func() { - It("does NOT contains openapi requirement in .eslintrc.json", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.Web, - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile(".eslintrc.json") - - expectedContent := `plugin:yml/recommended` - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - - It("does NOT contains openapi requirement in package.json", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.Web, - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("package.json") - - expectedContent := `"build:docs": "swagger-cli bundle docs/openapi/openapi.yml --outfile public/openapi.yml --type yaml"` - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - }) - - Context("given only API variant", func() { - It("does NOT contains .eslintrc.json file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat(".eslintrc.json") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("does NOT contains package.json file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat("package.json") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - }) - - It("does NOT contains docs/openapi folder", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat("docs/openapi") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("does NOT contains OpenAPI instruction in README", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("README.md") - - expectedContent := "Generate API documentation" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - - It("does NOT contains .dockerignore file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat(".dockerignore") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("does NOT contains .github/workflows/lint_docs.yml file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat(".github/workflows/lint_docs.yml") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("does NOT contains openapi requirement in .gitignore", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile(".gitignore") - - expectedContent := "/public/openapi.yml" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - - It("does NOT contains .spectral.yaml file", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - _, err := os.Stat(".spectral.yaml") - - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("does NOT contains openapi requirement in .tool-versions", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile(".tool-versions") - - expectedContent := "nodejs 18.15.0" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - - It("does NOT contains openapi requirement in Makefile", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - UseOpenAPI: tests.No, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("Makefile") - - expectedContent := "npm run build:docs" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) - }) }) diff --git a/cookiecutter.json b/cookiecutter.json index a0fdb62..39c6878 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -4,11 +4,9 @@ "css_addon": ["Bootstrap", "Tailwind", "None"], "use_logrus": ["yes", "no"], "use_heroku": ["yes", "no"], - "use_openapi": ["yes", "no"], "_api_variant": "no", "_web_variant": "no", - "_both_variant": "no", "_bootstrap_addon": "no", "_tailwind_addon": "no" } diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 09e08f7..9c0e94b 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -95,13 +95,8 @@ def init_git(message): remove_file('postcss.config.js') remove_file('tsconfig.json') - # Remove if openapi is not selected - if '{{ cookiecutter.use_openapi }}' == 'no': - remove_file('.eslintrc.json') - remove_file('package.json') - # Remove openapi if not seleted -if '{{ cookiecutter.use_openapi }}' == 'no': +if '{{ cookiecutter._api_variant }}' == 'no': print_log('Removing openapi') # docs folder diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 98e4347..59acb13 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -5,7 +5,6 @@ Web/API Variant cookiecutter._web_variant cookiecutter._api_variant -cookiecutter._both_variant ----------- {% if cookiecutter.variant in ['Web only', 'Both'] %} {{ cookiecutter.update({ '_web_variant': 'yes' }) }} @@ -15,10 +14,6 @@ {{ cookiecutter.update({ '_api_variant': 'yes' }) }} {% endif %} -{% if cookiecutter.variant == 'Both' %} - {{ cookiecutter.update({ '_both_variant': 'yes' }) }} -{% endif %} - ----------- CSS Addons cookiecutter._bootstrap_addon @@ -32,13 +27,4 @@ {{ cookiecutter.update({ '_tailwind_addon': 'yes' }) }} {% endif %} {% endif %} - ------------ -OpenAPI -cookiecutter.use_openapi ------------ -Only project with web only: -{% if cookiecutter._web_variant == 'yes' and cookiecutter._both_variant == 'no' %} - {{ cookiecutter.update({ 'use_openapi': 'no' }) }} -{% endif %} ''' diff --git a/tests/cookiecutter.go b/tests/cookiecutter.go index 4cb1fa9..eead37e 100644 --- a/tests/cookiecutter.go +++ b/tests/cookiecutter.go @@ -25,12 +25,11 @@ const ( // Field and order MUST be the same as cookiecutter.json type Cookiecutter struct { - AppName string - Variant Variants - CssAddon CssAddons - UseLogrus Choices - UseHeroku Choices - UseOpenAPI Choices + AppName string + Variant Variants + CssAddon CssAddons + UseLogrus Choices + UseHeroku Choices } func (c *Cookiecutter) fillDefaultValue() { @@ -46,10 +45,6 @@ func (c *Cookiecutter) fillDefaultValue() { c.UseHeroku = No } - if c.UseOpenAPI != Yes && c.UseOpenAPI != No { - c.UseOpenAPI = No - } - if c.CssAddon != Bootstrap && c.CssAddon != Tailwind && c.CssAddon != None { c.CssAddon = None } diff --git a/{{cookiecutter.app_name}}/.eslintrc.json b/{{cookiecutter.app_name}}/.eslintrc.json index 10cd9cd..3414d75 100644 --- a/{{cookiecutter.app_name}}/.eslintrc.json +++ b/{{cookiecutter.app_name}}/.eslintrc.json @@ -11,7 +11,7 @@ }, "extends": [ "eslint:recommended", - "plugin:prettier/recommended"{% if cookiecutter.use_openapi == "yes" %}, + "plugin:prettier/recommended"{% if cookiecutter._api_variant == "yes" %}, "@nimblehq/eslint-config-nimble", "plugin:yml/recommended"{% endif %} ], @@ -19,7 +19,7 @@ "Atomics": "readonly", "SharedArrayBuffer": "readonly" } -}{% endif %}{% if cookiecutter._both_variant == "no" and cookiecutter.use_openapi == "yes" %}{ +}{% endif %}{% if cookiecutter._api_variant == "yes" and cookiecutter._web_variant == "no" %}{ "extends": [ "@nimblehq/eslint-config-nimble", "plugin:yml/recommended" diff --git a/{{cookiecutter.app_name}}/.gitignore b/{{cookiecutter.app_name}}/.gitignore index 638ec62..4aeba4a 100644 --- a/{{cookiecutter.app_name}}/.gitignore +++ b/{{cookiecutter.app_name}}/.gitignore @@ -1,5 +1,4 @@ -{%- if cookiecutter._web_variant == "yes" or cookiecutter.use_openapi == "yes" %}/node_modules -{%- endif %} +/node_modules tmp/ coverage/ .env @@ -12,7 +11,7 @@ deploy/**/terraform.tfstate.backup deploy/**/*.tfvars {%- endif %} -{%- if cookiecutter.use_openapi == "yes" %} +{%- if cookiecutter._api_variant == "yes" %} ## OpenAPI /public/openapi.yml {%- endif %} diff --git a/{{cookiecutter.app_name}}/.tool-versions b/{{cookiecutter.app_name}}/.tool-versions index e86ac1e..151e0f7 100644 --- a/{{cookiecutter.app_name}}/.tool-versions +++ b/{{cookiecutter.app_name}}/.tool-versions @@ -1,2 +1,2 @@ -golang 1.20{% if cookiecutter.use_openapi == "yes" %} -nodejs 18.15.0{% endif %} +golang 1.20 +nodejs 18.15.0 diff --git a/{{cookiecutter.app_name}}/Makefile b/{{cookiecutter.app_name}}/Makefile index 84620a5..d5ccfe0 100644 --- a/{{cookiecutter.app_name}}/Makefile +++ b/{{cookiecutter.app_name}}/Makefile @@ -28,7 +28,7 @@ endif migration/status: goose -dir database/migrations -table "migration_versions" postgres "$(DATABASE_URL)" status -{% if cookiecutter.use_openapi == "yes" %}doc/generate: +{% if cookiecutter._api_variant == "yes" %}doc/generate: npm run build:docs {%- endif %} @@ -42,8 +42,8 @@ install-dependencies: go install github.com/pressly/goose/v3/cmd/goose@v3.9.0 go install github.com/ddollar/forego@latest go mod tidy - {% if cookiecutter._web_variant == "yes" %}npm install{% endif %} - {% if cookiecutter.use_openapi == "yes" %}make doc/generate{%- endif %} + npm install + {% if cookiecutter._api_variant == "yes" %}make doc/generate{%- endif %} test: docker compose -f docker-compose.test.yml up -d diff --git a/{{cookiecutter.app_name}}/README.md b/{{cookiecutter.app_name}}/README.md index e973b50..1559103 100644 --- a/{{cookiecutter.app_name}}/README.md +++ b/{{cookiecutter.app_name}}/README.md @@ -50,7 +50,7 @@ Execute all unit tests: ```make make test ``` -{%- if cookiecutter.use_openapi == "yes" %} +{%- if cookiecutter._api_variant == "yes" %} ### API Documentation Generate API documentation: diff --git a/{{cookiecutter.app_name}}/package.json b/{{cookiecutter.app_name}}/package.json index bf224f4..21d8e5f 100644 --- a/{{cookiecutter.app_name}}/package.json +++ b/{{cookiecutter.app_name}}/package.json @@ -9,9 +9,9 @@ {%- if cookiecutter._web_variant == "yes" %} "dev": "NODE_ENV=development MODE=development snowpack build --watch --no-minify --no-bundle", "build": "snowpack build", - "clean": "rm -rf static"{%- if cookiecutter.use_openapi == "yes" %},{%- endif %} + "clean": "rm -rf static"{%- if cookiecutter._api_variant == "yes" %},{%- endif %} {%- endif %} - {%- if cookiecutter.use_openapi == "yes" %} + {%- if cookiecutter._api_variant == "yes" %} "lint:docs:yml": "eslint docs/openapi --ext .yml --color", "lint:docs:openapi": "spectral lint docs/openapi/openapi.yml -F error", "lint:docs:dev": "npm lint:docs:yml && npm lint:docs:openapi", @@ -32,9 +32,9 @@ "postcss": "8.3.5", "prettier": "2.3.2", "snowpack": "3.7.1"{% if cookiecutter._tailwind_addon == "yes" %}, - "tailwindcss": "2.2.7"{% endif %}{%- if cookiecutter.use_openapi == "yes" %},{%- endif %} + "tailwindcss": "2.2.7"{% endif %}{%- if cookiecutter._api_variant == "yes" %},{%- endif %} {%- endif %} - {%- if cookiecutter.use_openapi == "yes" %} + {%- if cookiecutter._api_variant == "yes" %} "@apidevtools/swagger-cli": "4.0.4", "@nimblehq/eslint-config-nimble": "2.1.1", "@stoplight/spectral-cli": "6.8.0", From 7c0628395dd4da51902eb324bb2f4d2eb9e1cc31 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 11:19:18 +0700 Subject: [PATCH 29/43] [#105] Improve message --- hooks/post_gen_project.py | 2 +- hooks/pre_gen_project.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 9c0e94b..9187bd9 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -95,7 +95,7 @@ def init_git(message): remove_file('postcss.config.js') remove_file('tsconfig.json') -# Remove openapi if not seleted +# Remove openapi if the project has web variant only if '{{ cookiecutter._api_variant }}' == 'no': print_log('Removing openapi') diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 59acb13..679ccaa 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -10,6 +10,7 @@ {{ cookiecutter.update({ '_web_variant': 'yes' }) }} {% endif %} +API Variant {% if cookiecutter.variant in ['API only', 'Both'] %} {{ cookiecutter.update({ '_api_variant': 'yes' }) }} {% endif %} From 7dbb08f0961586fa911ee2ebe4544fb657083cc6 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 11:56:15 +0700 Subject: [PATCH 30/43] [#105] Improve readme --- {{cookiecutter.app_name}}/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/{{cookiecutter.app_name}}/README.md b/{{cookiecutter.app_name}}/README.md index 1559103..44cfa1d 100644 --- a/{{cookiecutter.app_name}}/README.md +++ b/{{cookiecutter.app_name}}/README.md @@ -9,6 +9,7 @@ ### Prerequisites - [Go - 1.20](https://golang.org/doc/go1.20) or newer +- [Node - 18](https://nodejs.org/en/) {% if cookiecutter._web_variant == "yes" %}- [Node - 14](https://nodejs.org/en/){% endif %} From 6b30577af88c3a223f16b9ab8f1350a9a9c66be3 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 15:19:01 +0700 Subject: [PATCH 31/43] [#105] Remove wrong version --- {{cookiecutter.app_name}}/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/{{cookiecutter.app_name}}/README.md b/{{cookiecutter.app_name}}/README.md index 44cfa1d..b7da9ae 100644 --- a/{{cookiecutter.app_name}}/README.md +++ b/{{cookiecutter.app_name}}/README.md @@ -11,8 +11,6 @@ - [Go - 1.20](https://golang.org/doc/go1.20) or newer - [Node - 18](https://nodejs.org/en/) -{% if cookiecutter._web_variant == "yes" %}- [Node - 14](https://nodejs.org/en/){% endif %} - ### Development #### Create an ENV file From acf5356d17db2c34557e581a1b855d2a46b2d820 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 15:26:16 +0700 Subject: [PATCH 32/43] [#105] Remove tests --- cmd/create_test.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index c1cf618..bde4898 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -663,19 +663,6 @@ var _ = Describe("Create template", func() { Expect(content).To(ContainSubstring(expectedContent)) }) - - It("contains Node 14 in README.md", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.Web, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("README.md") - - expectedContent := "[Node - 14](https://nodejs.org/en/)" - - Expect(content).To(ContainSubstring(expectedContent)) - }) }) Context("given NO Web variant", func() { @@ -759,19 +746,6 @@ var _ = Describe("Create template", func() { Expect(content).NotTo(ContainSubstring(expectedContent)) }) - - It("does NOT contain Node 14 in README.md", func() { - cookiecutter := tests.Cookiecutter{ - AppName: "test-gin-templates", - Variant: tests.API, - } - cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) - content := tests.ReadFile("README.md") - - expectedContent := "[Node - 14](https://nodejs.org/en/)" - - Expect(content).NotTo(ContainSubstring(expectedContent)) - }) }) Context("given bootstrap add-on", func() { From 2e7d7fe9ee8c3d1e6907e68227d538805362a3e1 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 14:54:10 +0700 Subject: [PATCH 33/43] [#105] Add `/docs/openapi` endpoint to support showing documentation --- hooks/post_gen_project.py | 1 + {{cookiecutter.app_name}}/bootstrap/router.go | 4 ++++ {{cookiecutter.app_name}}/go.mod | 1 + .../lib/api/docs/controllers/openapi.go | 13 +++++++++++++ .../lib/api/docs/routers/router.go | 14 ++++++++++++++ .../lib/api/docs/views/openapi/show.html | 17 +++++++++++++++++ 6 files changed, 50 insertions(+) create mode 100644 {{cookiecutter.app_name}}/lib/api/docs/controllers/openapi.go create mode 100644 {{cookiecutter.app_name}}/lib/api/docs/routers/router.go create mode 100644 {{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 9187bd9..86eb922 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -101,6 +101,7 @@ def init_git(message): # docs folder remove_files("docs") + remove_files("lib/api/docs") # openapi related files remove_file(".dockerignore") diff --git a/{{cookiecutter.app_name}}/bootstrap/router.go b/{{cookiecutter.app_name}}/bootstrap/router.go index 72ac012..fee0af5 100644 --- a/{{cookiecutter.app_name}}/bootstrap/router.go +++ b/{{cookiecutter.app_name}}/bootstrap/router.go @@ -1,9 +1,12 @@ package bootstrap import ( + {%- if cookiecutter.use_openapi == "yes" -%}apidocsrouter "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/docs/routers"{%- endif %} apiv1router "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/v1/routers" {% if cookiecutter._web_variant == "yes" %}webrouter "github.com/nimblehq/{{cookiecutter.app_name}}/lib/web/routers" {% endif %} + + {%- if cookiecutter.use_openapi == "yes" -%}"github.com/gin-gonic/contrib/static"{%- endif %} "github.com/gin-gonic/gin" ) @@ -11,6 +14,7 @@ func SetupRouter() *gin.Engine { r := gin.Default() apiv1router.ComebineRoutes(r) + {% if cookiecutter.use_openapi == "yes" -%}webrouter.ComebineRoutes(r){%- endif %} {% if cookiecutter._web_variant == "yes" %}webrouter.ComebineRoutes(r) {% endif %} return r diff --git a/{{cookiecutter.app_name}}/go.mod b/{{cookiecutter.app_name}}/go.mod index 75eb4c4..8a1132a 100644 --- a/{{cookiecutter.app_name}}/go.mod +++ b/{{cookiecutter.app_name}}/go.mod @@ -11,4 +11,5 @@ require ( gorm.io/driver/postgres v1.0.8 gorm.io/gorm v1.20.12 {% if cookiecutter.use_logrus == "yes" -%}github.com/sirupsen/logrus v1.8.1{%- endif %} + {% if cookiecutter.use_openapi == "yes" -%}github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2{%- endif %} ) diff --git a/{{cookiecutter.app_name}}/lib/api/docs/controllers/openapi.go b/{{cookiecutter.app_name}}/lib/api/docs/controllers/openapi.go new file mode 100644 index 0000000..dd89aaa --- /dev/null +++ b/{{cookiecutter.app_name}}/lib/api/docs/controllers/openapi.go @@ -0,0 +1,13 @@ +package controllers + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +type OpenAPIController struct{} + +func (OpenAPIController) Show(c *gin.Context) { + c.HTML(http.StatusOK, "show.html", gin.H{}) +} diff --git a/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go b/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go new file mode 100644 index 0000000..b395185 --- /dev/null +++ b/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go @@ -0,0 +1,14 @@ +package routers + +import ( + "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/docs/controllers" + + "github.com/gin-gonic/gin" +) + +func ComebineRoutes(engine *gin.Engine) { + docs := engine.Group("/api/docs") + + engine.LoadHTMLFiles("lib/api/docs/views/openapi/show.html") + docs.GET("/openapi", controllers.OpenAPIController{}.Show) +} diff --git a/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html new file mode 100644 index 0000000..4e973ee --- /dev/null +++ b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html @@ -0,0 +1,17 @@ + + + + + + + Open API documentation + + + + + + + + + + From 27ec54d4988d9a6417f0673de3d02715db671547 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 15:06:03 +0700 Subject: [PATCH 34/43] [#105] Improve the router import --- {{cookiecutter.app_name}}/bootstrap/router.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/bootstrap/router.go b/{{cookiecutter.app_name}}/bootstrap/router.go index fee0af5..82b45ad 100644 --- a/{{cookiecutter.app_name}}/bootstrap/router.go +++ b/{{cookiecutter.app_name}}/bootstrap/router.go @@ -13,8 +13,10 @@ import ( func SetupRouter() *gin.Engine { r := gin.Default() + {% if cookiecutter.use_openapi == "yes" -%}r.Use(static.Serve("/", static.LocalFile("./public", true))){%- endif %} + apiv1router.ComebineRoutes(r) - {% if cookiecutter.use_openapi == "yes" -%}webrouter.ComebineRoutes(r){%- endif %} + {% if cookiecutter.use_openapi == "yes" -%}apidocsrouter.ComebineRoutes(r){%- endif %} {% if cookiecutter._web_variant == "yes" %}webrouter.ComebineRoutes(r) {% endif %} return r From b0b904e9c0a0e0ce14613c64b062befd5a1996ff Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 15:30:32 +0700 Subject: [PATCH 35/43] [#105] Add tests for having endpoint for API docs --- cmd/create_test.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/cmd/create_test.go b/cmd/create_test.go index bde4898..3780b4f 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1107,5 +1107,39 @@ var _ = Describe("Create template", func() { Expect(content).To(ContainSubstring(expectedContent)) }) + + It("contains lib/api/docs folder", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("lib/api/docs") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains openapi requirement in go.mod", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("go.mod") + + expectedContent := "github.com/gin-gonic/contrib" + + Expect(content).To(ContainSubstring(expectedContent)) + }) + + It("contains openapi requirement in router.go", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + content := tests.ReadFile("bootstrap/router.go") + + expectedContent := "apidocsrouter.ComebineRoutes(r)" + + Expect(content).To(ContainSubstring(expectedContent)) + }) }) }) From 2bcd90e5fe216ae5b6ea4a9de4ad10d6ae99cf6d Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 15:38:37 +0700 Subject: [PATCH 36/43] [#105] Fix typo --- {{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html index 4e973ee..7f5a8f9 100644 --- a/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html +++ b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html @@ -4,7 +4,7 @@ - Open API documentation + API documentation From 2fc0d99fa049d9b38bc0d0815f5544b462bd5327 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Wed, 23 Aug 2023 11:32:44 +0700 Subject: [PATCH 37/43] [#105] Improve logic for api variant --- {{cookiecutter.app_name}}/bootstrap/router.go | 8 ++++---- {{cookiecutter.app_name}}/go.mod | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/{{cookiecutter.app_name}}/bootstrap/router.go b/{{cookiecutter.app_name}}/bootstrap/router.go index 82b45ad..e4574be 100644 --- a/{{cookiecutter.app_name}}/bootstrap/router.go +++ b/{{cookiecutter.app_name}}/bootstrap/router.go @@ -1,22 +1,22 @@ package bootstrap import ( - {%- if cookiecutter.use_openapi == "yes" -%}apidocsrouter "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/docs/routers"{%- endif %} + {%- if cookiecutter._api_variant == "yes" -%}apidocsrouter "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/docs/routers"{%- endif %} apiv1router "github.com/nimblehq/{{cookiecutter.app_name}}/lib/api/v1/routers" {% if cookiecutter._web_variant == "yes" %}webrouter "github.com/nimblehq/{{cookiecutter.app_name}}/lib/web/routers" {% endif %} - {%- if cookiecutter.use_openapi == "yes" -%}"github.com/gin-gonic/contrib/static"{%- endif %} + {%- if cookiecutter._api_variant == "yes" -%}"github.com/gin-gonic/contrib/static"{%- endif %} "github.com/gin-gonic/gin" ) func SetupRouter() *gin.Engine { r := gin.Default() - {% if cookiecutter.use_openapi == "yes" -%}r.Use(static.Serve("/", static.LocalFile("./public", true))){%- endif %} + {% if cookiecutter._api_variant == "yes" -%}r.Use(static.Serve("/", static.LocalFile("./public", true))){%- endif %} apiv1router.ComebineRoutes(r) - {% if cookiecutter.use_openapi == "yes" -%}apidocsrouter.ComebineRoutes(r){%- endif %} + {% if cookiecutter._api_variant == "yes" -%}apidocsrouter.ComebineRoutes(r){%- endif %} {% if cookiecutter._web_variant == "yes" %}webrouter.ComebineRoutes(r) {% endif %} return r diff --git a/{{cookiecutter.app_name}}/go.mod b/{{cookiecutter.app_name}}/go.mod index 8a1132a..423483d 100644 --- a/{{cookiecutter.app_name}}/go.mod +++ b/{{cookiecutter.app_name}}/go.mod @@ -11,5 +11,5 @@ require ( gorm.io/driver/postgres v1.0.8 gorm.io/gorm v1.20.12 {% if cookiecutter.use_logrus == "yes" -%}github.com/sirupsen/logrus v1.8.1{%- endif %} - {% if cookiecutter.use_openapi == "yes" -%}github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2{%- endif %} + {% if cookiecutter._api_variant == "yes" -%}github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2{%- endif %} ) From a6886bd520745b38bfbc6c7e420dca6f573589b0 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 25 Aug 2023 11:04:17 +0700 Subject: [PATCH 38/43] [#105] Improve naming and description --- cmd/create_test.go | 2 +- {{cookiecutter.app_name}}/bootstrap/router.go | 6 +++--- {{cookiecutter.app_name}}/lib/api/docs/routers/router.go | 2 +- .../lib/api/docs/views/openapi/show.html | 2 +- {{cookiecutter.app_name}}/lib/api/v1/routers/router.go | 2 +- {{cookiecutter.app_name}}/lib/web/routers/router.go | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/create_test.go b/cmd/create_test.go index 3780b4f..29493f9 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1137,7 +1137,7 @@ var _ = Describe("Create template", func() { cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) content := tests.ReadFile("bootstrap/router.go") - expectedContent := "apidocsrouter.ComebineRoutes(r)" + expectedContent := "apidocsrouter.CombineRoutes(r)" Expect(content).To(ContainSubstring(expectedContent)) }) diff --git a/{{cookiecutter.app_name}}/bootstrap/router.go b/{{cookiecutter.app_name}}/bootstrap/router.go index e4574be..41bda01 100644 --- a/{{cookiecutter.app_name}}/bootstrap/router.go +++ b/{{cookiecutter.app_name}}/bootstrap/router.go @@ -15,9 +15,9 @@ func SetupRouter() *gin.Engine { {% if cookiecutter._api_variant == "yes" -%}r.Use(static.Serve("/", static.LocalFile("./public", true))){%- endif %} - apiv1router.ComebineRoutes(r) - {% if cookiecutter._api_variant == "yes" -%}apidocsrouter.ComebineRoutes(r){%- endif %} - {% if cookiecutter._web_variant == "yes" %}webrouter.ComebineRoutes(r) + apiv1router.CombineRoutes(r) + {% if cookiecutter._api_variant == "yes" -%}apidocsrouter.CombineRoutes(r){%- endif %} + {% if cookiecutter._web_variant == "yes" %}webrouter.CombineRoutes(r) {% endif %} return r } diff --git a/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go b/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go index b395185..6ffeb84 100644 --- a/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go +++ b/{{cookiecutter.app_name}}/lib/api/docs/routers/router.go @@ -6,7 +6,7 @@ import ( "github.com/gin-gonic/gin" ) -func ComebineRoutes(engine *gin.Engine) { +func CombineRoutes(engine *gin.Engine) { docs := engine.Group("/api/docs") engine.LoadHTMLFiles("lib/api/docs/views/openapi/show.html") diff --git a/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html index 7f5a8f9..58fad03 100644 --- a/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html +++ b/{{cookiecutter.app_name}}/lib/api/docs/views/openapi/show.html @@ -5,7 +5,7 @@ API documentation - + diff --git a/{{cookiecutter.app_name}}/lib/api/v1/routers/router.go b/{{cookiecutter.app_name}}/lib/api/v1/routers/router.go index 2b3dd9d..1ef30c1 100644 --- a/{{cookiecutter.app_name}}/lib/api/v1/routers/router.go +++ b/{{cookiecutter.app_name}}/lib/api/v1/routers/router.go @@ -6,7 +6,7 @@ import ( "github.com/gin-gonic/gin" ) -func ComebineRoutes(engine *gin.Engine) { +func CombineRoutes(engine *gin.Engine) { v1 := engine.Group("/api/v1") v1.GET("/health", controllers.HealthController{}.HealthStatus) diff --git a/{{cookiecutter.app_name}}/lib/web/routers/router.go b/{{cookiecutter.app_name}}/lib/web/routers/router.go index f9bb78f..8f3077c 100644 --- a/{{cookiecutter.app_name}}/lib/web/routers/router.go +++ b/{{cookiecutter.app_name}}/lib/web/routers/router.go @@ -10,7 +10,7 @@ import ( eztemplate "github.com/michelloworld/ez-gin-template" ) -func ComebineRoutes(engine *gin.Engine) { +func CombineRoutes(engine *gin.Engine) { // Register HTML renderer htmlRender := eztemplate.New() htmlRender.Debug = gin.IsDebugging() From 17addfab9c27e5dff692368025ed3840bcf1671a Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 28 Aug 2023 13:02:43 +0700 Subject: [PATCH 39/43] [#105] Improve the post script --- hooks/post_gen_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 86eb922..4e16139 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -101,7 +101,7 @@ def init_git(message): # docs folder remove_files("docs") - remove_files("lib/api/docs") + remove_files("lib/api") # openapi related files remove_file(".dockerignore") From 59f1ca15325d99a1a73291df637f267cf54ff8a0 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 15:47:47 +0700 Subject: [PATCH 40/43] [#105] Add mock server setup with fly.io --- cookiecutter.json | 1 + tests/cookiecutter.go | 15 ++++++++----- .../.github/workflows/deploy_mock_server | 22 +++++++++++++++++++ {{cookiecutter.app_name}}/Dockerfile.mock | 7 ++++++ {{cookiecutter.app_name}}/fly.toml | 13 +++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 {{cookiecutter.app_name}}/.github/workflows/deploy_mock_server create mode 100644 {{cookiecutter.app_name}}/Dockerfile.mock create mode 100644 {{cookiecutter.app_name}}/fly.toml diff --git a/cookiecutter.json b/cookiecutter.json index 39c6878..8bfc18f 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -4,6 +4,7 @@ "css_addon": ["Bootstrap", "Tailwind", "None"], "use_logrus": ["yes", "no"], "use_heroku": ["yes", "no"], + "use_mock_server": ["yes","no"], "_api_variant": "no", "_web_variant": "no", diff --git a/tests/cookiecutter.go b/tests/cookiecutter.go index eead37e..57dc9c3 100644 --- a/tests/cookiecutter.go +++ b/tests/cookiecutter.go @@ -25,11 +25,12 @@ const ( // Field and order MUST be the same as cookiecutter.json type Cookiecutter struct { - AppName string - Variant Variants - CssAddon CssAddons - UseLogrus Choices - UseHeroku Choices + AppName string + Variant Variants + CssAddon CssAddons + UseLogrus Choices + UseHeroku Choices + UseMockServer Choices } func (c *Cookiecutter) fillDefaultValue() { @@ -45,6 +46,10 @@ func (c *Cookiecutter) fillDefaultValue() { c.UseHeroku = No } + if c.UseMockServer != Yes && c.UseMockServer != No { + c.UseMockServer = No + } + if c.CssAddon != Bootstrap && c.CssAddon != Tailwind && c.CssAddon != None { c.CssAddon = None } diff --git a/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server new file mode 100644 index 0000000..bd50f7a --- /dev/null +++ b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server @@ -0,0 +1,22 @@ +name: Deploy Mock Server + +on: + push: + branches: + - develop + +jobs: + deploy: + name: Deploy server mock + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up flyctl + uses: superfly/flyctl-actions/setup-flyctl@master + + - name: Deploy to fly + run: flyctl deploy --remote-only + env: + FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} diff --git a/{{cookiecutter.app_name}}/Dockerfile.mock b/{{cookiecutter.app_name}}/Dockerfile.mock new file mode 100644 index 0000000..db70c4b --- /dev/null +++ b/{{cookiecutter.app_name}}/Dockerfile.mock @@ -0,0 +1,7 @@ +FROM stoplight/prism:latest + +COPY /docs /usr/src/prism/packages/cli/docs/ + +EXPOSE 80 + +CMD ["mock", "-h", "0.0.0.0", "-p", "80", "docs/openapi/openapi.yml"] diff --git a/{{cookiecutter.app_name}}/fly.toml b/{{cookiecutter.app_name}}/fly.toml new file mode 100644 index 0000000..ca69210 --- /dev/null +++ b/{{cookiecutter.app_name}}/fly.toml @@ -0,0 +1,13 @@ +app = "api-mock-server" +primary_region = "sin" + +[build] + dockerfile = "Dockerfile.mock" + +[http_service] + internal_port = 80 + force_https = true + auto_stop_machines = true + auto_start_machines = true + min_machines_running = 0 + processes = ["app"] From efa52c9c2135e9184cd6cf6417156842bee18c2f Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 16:35:19 +0700 Subject: [PATCH 41/43] [#105] Add tests for mock server --- cmd/create_test.go | 70 +++++++++++++++++++ hooks/post_gen_project.py | 9 +++ hooks/pre_gen_project.py | 9 +++ ...loy_mock_server => deploy_mock_server.yml} | 2 +- 4 files changed, 89 insertions(+), 1 deletion(-) rename {{cookiecutter.app_name}}/.github/workflows/{deploy_mock_server => deploy_mock_server.yml} (85%) diff --git a/cmd/create_test.go b/cmd/create_test.go index 29493f9..fcd7b03 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -1142,4 +1142,74 @@ var _ = Describe("Create template", func() { Expect(content).To(ContainSubstring(expectedContent)) }) }) + + Context("given mock_server add-on", func() { + It("contains deploy_mock_server.yml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".github/workflows/deploy_mock_server.yml") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains Dockerfile.mock file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("Dockerfile.mock") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + + It("contains fly.toml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.Yes, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("fly.toml") + + Expect(os.IsNotExist(err)).To(BeFalse()) + }) + }) + + Context("given NO mock_server add-on", func() { + It("does NOT contains deploy_mock_server.yml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat(".github/workflows/deploy_mock_server.yml") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains Dockerfile.mock file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("Dockerfile.mock") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + + It("does NOT contains fly.toml file", func() { + cookiecutter := tests.Cookiecutter{ + AppName: "test-gin-templates", + UseMockServer: tests.No, + } + cookiecutter.CreateProjectFromGinTemplate(currentTemplatePath) + _, err := os.Stat("fly.toml") + + Expect(os.IsNotExist(err)).To(BeTrue()) + }) + }) }) diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 4e16139..458af8d 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -109,6 +109,15 @@ def init_git(message): remove_file(".spectral.yaml") remove_file(".github/workflows/lint_docs.yml") +# Remove mock_server if not seleted +if '{{ cookiecutter.use_mock_server }}' == 'no': + print_log('Removing mock_server') + + # mock_server related files + remove_file("Dockerfile.mock") + remove_file("fly.toml") + remove_file(".github/workflows/deploy_mock_server.yml") + # Download the missing dependencies print_log('Downloading dependencies') subprocess.call(['go', 'mod', 'tidy']) diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 679ccaa..51a4432 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -28,4 +28,13 @@ {{ cookiecutter.update({ '_tailwind_addon': 'yes' }) }} {% endif %} {% endif %} + +----------- +Mock Server +cookiecutter.use_mock_server +----------- +Only project with openapi: +{% if cookiecutter._api_variant == 'no' %} + {{ cookiecutter.update({ 'use_mock_server': 'no' }) }} +{% endif %} ''' diff --git a/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml similarity index 85% rename from {{cookiecutter.app_name}}/.github/workflows/deploy_mock_server rename to {{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml index bd50f7a..578f40e 100644 --- a/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server +++ b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml @@ -19,4 +19,4 @@ jobs: - name: Deploy to fly run: flyctl deploy --remote-only env: - FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} + FLY_API_TOKEN: {{ "${{ secrets.FLY_API_TOKEN }}" }} From c636f474f0fc5829418c6034fec673c289711f5b Mon Sep 17 00:00:00 2001 From: Su Ho Date: Mon, 14 Aug 2023 16:43:42 +0700 Subject: [PATCH 42/43] [#105] Fix space --- cookiecutter.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookiecutter.json b/cookiecutter.json index 8bfc18f..1e7c3e3 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -4,7 +4,7 @@ "css_addon": ["Bootstrap", "Tailwind", "None"], "use_logrus": ["yes", "no"], "use_heroku": ["yes", "no"], - "use_mock_server": ["yes","no"], + "use_mock_server": ["yes", "no"], "_api_variant": "no", "_web_variant": "no", From b0da17a56c2d2c047b8ec75baddad4f23fd70fc1 Mon Sep 17 00:00:00 2001 From: Su Ho Date: Fri, 25 Aug 2023 11:08:34 +0700 Subject: [PATCH 43/43] [#105] Improve naming --- .../.github/workflows/deploy_mock_server.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml index 578f40e..d6823c8 100644 --- a/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml +++ b/{{cookiecutter.app_name}}/.github/workflows/deploy_mock_server.yml @@ -7,7 +7,7 @@ on: jobs: deploy: - name: Deploy server mock + name: Deploy mock server runs-on: ubuntu-latest steps: - name: Checkout