{"id":37117852,"url":"https://github.com/xvrzhao/groove","last_synced_at":"2026-01-14T13:46:56.962Z","repository":{"id":265412661,"uuid":"895944155","full_name":"xvrzhao/groove","owner":"xvrzhao","description":"The Groove CLI. Groove is a minimalist HTTP/Cron service scaffold for singleton.","archived":false,"fork":false,"pushed_at":"2025-01-13T08:37:25.000Z","size":3914,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-13T09:36:01.990Z","etag":null,"topics":["agile-development","cron","crud-generator","framework","go","http","scaffold","singleton"],"latest_commit_sha":null,"homepage":"https://github.com/xvrzhao/groove-scaffold","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xvrzhao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-29T08:30:28.000Z","updated_at":"2025-01-13T08:33:19.000Z","dependencies_parsed_at":"2024-11-29T09:43:01.493Z","dependency_job_id":null,"html_url":"https://github.com/xvrzhao/groove","commit_stats":null,"previous_names":["xvrzhao/groove"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/xvrzhao/groove","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvrzhao%2Fgroove","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvrzhao%2Fgroove/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvrzhao%2Fgroove/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvrzhao%2Fgroove/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xvrzhao","download_url":"https://codeload.github.com/xvrzhao/groove/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvrzhao%2Fgroove/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28422215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agile-development","cron","crud-generator","framework","go","http","scaffold","singleton"],"created_at":"2026-01-14T13:46:56.276Z","updated_at":"2026-01-14T13:46:56.944Z","avatar_url":"https://github.com/xvrzhao.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"500px\" src=\"./logos/logo.svg\" /\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/xvrzhao/groove/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/xvrzhao/groove\" alt=\"issues\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/xvrzhao/groove/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/xvrzhao/groove\" alt=\"license\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/xvrzhao/groove/tags\"\u003e\u003cimg src=\"https://img.shields.io/github/v/tag/xvrzhao/groove?label=version\" alt=\"tags\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nGroove is a minimalist HTTP/Cron service scaffold that integrates basic Web development packages, including JWT authentication, logging, password hashing, paging queries, standardized HTTP response formats, etc. It also comes with a one-click CRUD interface generation tool suitable for agile development, making it very suitable for the development of small singleton backend services.\n\n[中文文档](./README-CN.md)\n\n## Table of Contents\n\n\u003c!-- toc --\u003e\n\n- [Usage](#usage)\n- [Groove Design Philosophy](#groove-design-philosophy)\n  * [Environment Variables](#environment-variables)\n    + [Reading Environment Variables](#reading-environment-variables)\n    + [Environment Variable Files](#environment-variable-files)\n    + [Environment Variables and Image Publishing](#environment-variables-and-image-publishing)\n    + [When to Read Environment Variables](#when-to-read-environment-variables)\n  * [Image and Version](#image-and-version)\n  * [HTTP Request Lifecycle](#http-request-lifecycle)\n    + [Controller Layer](#controller-layer)\n    + [Service Layer](#service-layer)\n    + [Model Layer](#model-layer)\n  * [Database Migration File](#database-migration-file)\n  * [DEBUG and Unit Testing](#debug-and-unit-testing)\n  * [Graceful Shutdown](#graceful-shutdown)\n- [Groove Shortcuts](#groove-shortcuts)\n  * [Launch the Groove App Locally](#launch-the-groove-app-locally)\n  * [Generate CRUD code](#generate-crud-code)\n  * [Code Formatting and Static Check](#code-formatting-and-static-check)\n  * [Publish Image](#publish-image)\n\n\u003c!-- tocstop --\u003e\n\n## Usage\n\n```bash\n# Install the Groove CLI, and make sure your $GOBIN ($GOPATH/bin) directory is added to your $PATH env variable.\ngo install github.com/xvrzhao/groove@latest\n\n# Create your Groove project.\ngroove create my-app\n\n# Start developing your project using vscode.\ncode ./my-app\n```\n\n## Groove Design Philosophy\n\n### Environment Variables\n\n#### Reading Environment Variables\n\nGroove's design philosophy is that the Go application itself is a stateless application. It is just a logical machine, and different environment variables (states) will give it different behaviors.\n\nThe Go application itself does not handle the export of environment variables or the reading of configuration files. The environment variables are read by the `bin/go` (local environment) and `bin/exec` (in the container) scripts at startup. The `.env` file under the project root path is exported to the application. The Go application only needs to read from the environment variables. Therefore, when you execute the `go` command, you need to use `bin/go` instead, for example: `bin/go test ./...`, `bin/go run ./cmd/http`, etc.\n\n**Another reason for this design is that if the Go application handles the reading of configuration files, the working directory (`pwd`) will be changed to the unit test package when executing unit tests, which will cause the configuration file to be unable to read and an error will be reported.**\n\n#### Environment Variable Files\n\nWhether in a local environment or an online container environment, starting the Groove application will read the `.env` file from the project root path. To prevent important information from being leaked, the file has been included in `.gitignore`. Therefore, you need to copy `.env`.example and name it `.env` before starting the project.\n\n#### Environment Variables and Image Publishing\n\nGroove scaffolding integrates the `make publish` shortcut command to build and publish images. If you read the `Makefile` and `Dockerfile` files carefully, you will find that the publishing environment will be specified according to the `env` parameter of `make publish` or the `PUBLISH_MODE` parameter of `docker build` during the image building process, and in the `Dockerfile`, the **.env.environment.${specifiedEnvironment}** file will be copied to `.env` for application use according to the specified environment.\n\nTherefore, you can create multiple different environment variable files, such as **.env.development**, **.env.production**, etc. In this way, when executing, for example, `make publish version=1.0.0 env=development` or `make publish version=1.0.0 env=production`, the corresponding environment variable files will be applied respectively.\n\n#### When to Read Environment Variables\n\nGo applications are composed of several packages, and packages are independent and autonomous units that provide available interfaces to the outside world. Therefore, in order to ensure that the content provided by the package is always available, the content provided to the outside world should be initialized in the initialization phase of the package (`init` function), so the environment variables should be read in the `init` function and the exposed content should be initialized.\n\nYou can refer to the `db/conn.go` file. The `db` package only provides the `Client` variable to the outside world. `Client` is a database client, and its initialization and configuration reading are completed in the `init` phase.\n\n**Groove strongly discourages putting initialization work in the running phase (after the `main` function starts executing), which will also make unit testing impossible in some cases, unless the initialization code is manually written in the unit test, such as initializing the database connection.**\n\n### Image and Version\n\nGroove is composed of two applications, HTTP and Cron. Since Groove is a singleton project, changes to the public package will affect both applications. Therefore, Groove believes that the two program entries should keep the same version number. The image building process will compile both entries into the same image. When deploying, you only need to use different startup instructions for the same image (`CMD` of `Dockerfile`, or `command` of `docker-compose`).\n\n### HTTP Request Lifecycle\n\nGroove respects the classic *Controller - Service - Model* three-layer architecture design.\n\n#### Controller Layer\n\nThe Controller layer is responsible for the verification of request parameters and the encapsulation of response data.\n\n#### Service Layer\n\nThe Service layer is the core of the business logic. The API of this layer should have general and abstract capabilities for different business modules to call. The purpose of extracting the Service layer is to simulate the calling relationship of the microservice architecture. **Each Service is an independent microservice**, and Services cooperate with each other and call each other. **At the same time, the Service of each business module should only have the authority to call the Model under its jurisdiction, and should not call the Model outside its jurisdiction. If it is to be used, it should be implemented through API calls between Services.** Such strict code discipline will be very convenient for the real microservice splitting in the future.\n\n#### Model Layer\n\nThe Model layer is the data model used in the business. It only declares the data attributes of the Model itself and does not contain any business logic.\n\n### Database Migration File\n\nGroove uses a simple SQL file to represent the DDL operation of the database. Its naming rule is `date.${businessName}.sql`. In this way, the files will be sorted in date order. Since the project may be developed by multiple people, this sorting can ensure that SQL can be executed in the correct order during deployment, and there will be no wrong overwriting operations.\n\n### DEBUG and Unit Testing\n\nGroove comes with a vscode `launch.json` file, which declares the HTTP debug startup entry internally. When it starts, it will read the environment variables from `.env` to facilitate debugging.\n\nGroove advocates writing unit tests.\n\n### Graceful Shutdown\n\nAlthough the Go application is started by the `bin/exec` script in the container, it can ensure that the Go application is the main program of the container (pid: 1) and can normally receive the `TERM`/`KILL` and other signals of the container. You can write the graceful shutdown logic in the code yourself.\n\n## Groove Shortcuts\n\n### Launch the Groove App Locally\n\n```bash\n# Start HTTP service locally.\nmake run-http\n# Start the Cron program locally.\nmake run-cron\n```\n\n### Generate CRUD code\n\n```bash\n# Parameter description:\n#   table: database table name\n#   model: model name to generate\nmake crud table=x_persons model=Person\n```\n\n### Code Formatting and Static Check\n\n```bash\nmake code\n```\n\n### Publish Image\n\n```bash\n# Parameter description:\n#   version: version number\n#   env: published environment, different environments will package different env files\nmake publish version=1.0.0 env=development\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxvrzhao%2Fgroove","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxvrzhao%2Fgroove","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxvrzhao%2Fgroove/lists"}