{"id":13794307,"url":"https://github.com/axiaoxin-com/pink-lady","last_synced_at":"2025-08-31T10:34:25.474Z","repository":{"id":41379427,"uuid":"153586601","full_name":"axiaoxin-com/pink-lady","owner":"axiaoxin-com","description":"a template project of gin app.","archived":false,"fork":false,"pushed_at":"2025-08-24T09:14:12.000Z","size":79721,"stargazers_count":78,"open_issues_count":1,"forks_count":20,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-08-24T14:54:32.647Z","etag":null,"topics":["boilerplate-application","gin","gin-boilerplate","gin-framework","gin-skeleton","go","gorm","redis","sentry","swag","template-project","viper","zap"],"latest_commit_sha":null,"homepage":"https://axiaoxin.com/pink-lady","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axiaoxin-com.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null}},"created_at":"2018-10-18T08:05:21.000Z","updated_at":"2025-08-24T09:14:15.000Z","dependencies_parsed_at":"2024-01-14T08:46:06.916Z","dependency_job_id":"23e13905-57bf-45b2-a072-22eb40257b09","html_url":"https://github.com/axiaoxin-com/pink-lady","commit_stats":null,"previous_names":["axiaoxin/gin-skeleton","axiaoxin/pink-lady"],"tags_count":21,"template":true,"template_full_name":null,"purl":"pkg:github/axiaoxin-com/pink-lady","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiaoxin-com%2Fpink-lady","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiaoxin-com%2Fpink-lady/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiaoxin-com%2Fpink-lady/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiaoxin-com%2Fpink-lady/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axiaoxin-com","download_url":"https://codeload.github.com/axiaoxin-com/pink-lady/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiaoxin-com%2Fpink-lady/sbom","scorecard":{"id":220089,"data":{"date":"2025-08-11","repo":{"name":"github.com/axiaoxin-com/pink-lady","commit":"34a9ac1658105765972e52a39b458988ebc1c742"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"18 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/autoi18n.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.4.3 not signed: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/69355554","Warn: release artifact v1.4.2 not signed: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/45311914","Warn: release artifact v1.4.1 not signed: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/45310294","Warn: release artifact v1.4.3 does not have provenance: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/69355554","Warn: release artifact v1.4.2 does not have provenance: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/45311914","Warn: release artifact v1.4.1 does not have provenance: https://api.github.com/repos/axiaoxin-com/pink-lady/releases/45310294"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/autoi18n.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/axiaoxin-com/pink-lady/autoi18n.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/autoi18n.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/axiaoxin-com/pink-lady/autoi18n.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/autoi18n.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/axiaoxin-com/pink-lady/autoi18n.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/autoi18n.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/axiaoxin-com/pink-lady/autoi18n.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating alpine to alpine@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":3,"reason":"7 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2024-2687 / GHSA-4v7x-pqxf-cx7m","Warn: Project is vulnerable to: GO-2024-3333","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2024-2611 / GHSA-8r3f-844c-mc37"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T02:17:32.403Z","repository_id":41379427,"created_at":"2025-08-17T02:17:32.403Z","updated_at":"2025-08-17T02:17:32.403Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271938402,"owners_count":24846754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["boilerplate-application","gin","gin-boilerplate","gin-framework","gin-skeleton","go","gorm","redis","sentry","swag","template-project","viper","zap"],"created_at":"2024-08-03T23:00:38.628Z","updated_at":"2025-08-31T10:34:25.446Z","avatar_url":"https://github.com/axiaoxin-com.png","language":"Go","funding_links":[],"categories":["Framework based on gin"],"sub_categories":[],"readme":"# pink-lady\n\n![proj-icon](./misc/pics/logo.png)\n\n[![go report card](https://goreportcard.com/badge/github.com/axiaoxin-com/pink-lady)](https://goreportcard.com/report/github.com/axiaoxin-com/pink-lady)\n[![version-badge](https://img.shields.io/github/release/axiaoxin-com/pink-lady.svg)](https://github.com/axiaoxin-com/pink-lady/releases)\n[![license](https://img.shields.io/github/license/axiaoxin-com/pink-lady.svg)](https://github.com/axiaoxin-com/pink-lady/blob/master/LICENSE)\n[![issues](https://img.shields.io/github/issues/axiaoxin-com/pink-lady.svg)](https://github.com/axiaoxin-com/pink-lady/issues)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/axiaoxin-com/pink-lady/pulls)\n\n\u003e Pinklady is a template project of gin app, which encapsulates mysql, redis, logging, viper, swagger, middlewares and other common components.\n\npink-lady 是基于 Golang web 开发框架 [gin](https://github.com/gin-gonic/gin)\n来进行 **API服务/WEB网站** 开发的示例项目，新建项目时可以使用它作为项目模板。\n\n之所以叫 pink-lady 首先字面意思就是红粉佳人或粉红女郎，有这个性感的名字相信你更会好好对你的代码负责。\n其次，因为 gin 就是国外六大类烈酒之一的金酒，是近百年来调制鸡尾酒时最常使用的基酒，其配方多达千种以上，\n而 pink lady 是以 gin 作 base 的国标鸡尾酒之一，在这里 pink-lady 则是以 gin 作 base 的代码骨架模板之一\n\n## 使用 pink-lady 模板创建项目\n\n点击 \u003chttps://github.com/axiaoxin-com/pink-lady/generate\u003e 创建你的 github 项目（使用该方式创建项目时，如需修改项目名称需手动修改）\n\n或者手动本地创建（如想自定义项目名，推荐使用该方式）：\n\n```\nbash \u003c(curl -s https://raw.githubusercontent.com/axiaoxin-com/pink-lady/master/misc/scripts/new_project.sh)\n```\n\n## 特性\n\n- 使用 viper 加载配置，支持配置热更新，服务所有特性都通过配置文件控制\n- 支持生成 swagger api 文档\n- 封装数据库连接实例池，通过读取配置文件可以直接在代码中使用 gorm 和 sqlx 快速连接 mysql、sqlite3、postgresql、sqlserver\n- 封装 redis， redis sentinel， redis cluster 连接实例池\n- 封装统一的 JSON 返回结构\n- 集成 sentry 搜集错误\n- 内置 GinLogger 中间件打印详细的访问日志，支持不同的 http 状态码使用不同的日志级别，通过配置开关打印请求头，请求餐宿，响应体等调试信息\n- 内置 GinRecovery 中间件，异常服务默认按状态码返回 JSON 错误信息，panic 错误统一交由 GinLogger 打印，支持自定义输出格式\n- 使用 logging 打印日志，支持 trace id，error 以上级别自动上报到 sentry\n- 支持 prometheus metrics exporter\n- 支持 ratelimiter 请求限频\n- 通过配置集成 go html template，可自由注册 template funcs map\n- embed 静态资源编译进二进制文件中\n- i18n国际化支持\n- 支持类似Django的[flatpages](https://github.com/axiaoxin-com/pink-lady/blob/master/statics/flatpages/docs/README.md)\n- SEO良好支持\n\n## 使用 `pink-lady/webserver` 3 步组装一个 WEB 应用\n\n1. 确认配置文件正确。\n   配置文件必须满足能解析出指定的内容，复制或修改 [config.default.toml](https://github.com/axiaoxin-com/pink-lady/blob/master/config.default.toml) 中的配置项\n2. 创建自定义中间件的 gin app `NewGinEngine` （可选）\n3. 运行 web 应用服务器 `Run`。\n   需传入 gin app 和在该 app 上注册 URL 路由注册函数\n\n实现代码在`src`路径下，在 pink-lady 模板项目下，你只需关注如何实现你的业务逻辑，不用考虑如何组织项目结构和集成一些通用功能，比如数据库的连接封装，配置文件的读取，swagger 文档生成，统一的 JSON 返回结果，错误码定义，集成 Sentry 等等。\n\n你可以在`routes`路径下实现你的 api，并在 `routes/routes.go` 的 `Routes` 函数中注册 URL 即可。外部第三方服务放在 `services` 包中进行加载或初始化。数据库模型相关定义放到 `models` 包中便于复用。\n\n## 关于 gin\n\n### gin 框架源码图解\n\n![gin arch](https://github.com/axiaoxin-com/pink-lady/blob/master/misc/pics/gin_arch.svg)\n\n### gin 中间件原理解析\n\n\u003chttps://github.com/axiaoxin/axiaoxin/issues/17\u003e\n\n## 开发环境搭建\n\n### 安装 swagger api 文档生成工具 [swag](https://github.com/swaggo/swag)\n\n```\ngo get -u github.com/swaggo/swag/cmd/swag\n```\n\n在项目根目录中执行以下命令会在 `routes` 目录中生成 api 文档\n\n```\nswag init --dir ./ --generalInfo routes/routes.go --propertyStrategy snakecase --output ./routes/docs\n```\n\napi 文档地址： \u003chttp://localhost:4869/x/apidocs/index.html\u003e\n\n服务启动时如果环境变量设置了 `DISABLE_GIN_SWAGGER` 会关闭 api 文档。\n首次访问需经过 Basic 认证登录，登录账号密码可通过配置修改，默认为 `admin` `admin`\n\nswag 中文文档: \u003chttps://github.com/swaggo/swag/blob/master/README_zh-CN.md\u003e\n\n## 配置文件\n\n服务通过 [viper](https://github.com/spf13/viper) 加载配置文件， viper 支持的配置文件格式都可以使用。\n\n服务启动时默认加载当前目录的 `config.default.toml`\n\n服务启动时可以通过以下参数指定其他配置文件： `-c` 指定配置文件的路径\n\n**建议**：在开发自己的服务时，复制当前目录的 toml 配置创建一份新的配置，再在其上进行修改或新增配置，然后通过指定参数加载自己的配置。\n\n## 日志打印\n\n使用 [logging](https://github.com/axiaoxin-com/logging) 的方法打印带 trace id 的日志，可通过配置文件中 `[logging]` 下的配置项进行相关设置。\n\n配置 sentry dsn 后，`Error` 级别以上的日志会被自动采集到 Sentry 便于错误发现与定位。\n\n## API 开发\n\n使用 [pink-lady](http://github.com/axiaoxin-com/pink-lady) 开发 web api 服务，你只需实现 gin 的 `HandlerFunc` 并在 `routes/routes.go` 的 `Routes` 函数中注册到对应的 URL 上即可。\n\napi 中使用 `c.Error(err)` 会将 err 保存到 context 中，打印访问日志时会以 `Error` 级别自动打印错误信息。避免同一类错误打印多次日志影响问题定位效率。\n\n手动完整的启动服务命令：\n\n```\ngo run main.go -c config.default.toml\n```\n\n编译：\n\n```\ngo generate\nCGO_ENABLED=0 GOOS=linux go build -ldflags \"-X github.com/axiaoxin-com/pink-lady/routes.BuildID=${buildid}\" -o pink-lady\n```\n\n## i18n国际化支持集成方法\n\ni18n使用gettext方式读取po文件，通过自定义脚本 `i18n.sh` 一键提取翻译文本生成pot模板，自动合并更新po文件，并使用谷歌翻译进行自动翻译。\n\n谷歌翻译需开代理访问。\n\n### 标记i18n字符串\n\n1. 对golang代码中需要进行翻译的文字使用`webserver.CtxI18n(c, \"文字\")`、`webserver.LangI18n(\"en\", \"文字\")`或`I18nString(\"文字\")`包裹\n2. 对网页模板中的翻译文字使用 `{{ _i18n .meta.Lang \"文字\" }}`包裹。\n\n具体的使用示例可以参考[demo主页代码](https://github.com/axiaoxin-com/pink-lady/blob/master/routes/page_home.go)\n\n示例代码 `./routes/page_home.go`：\n\n```go\nfunc PageHome(c *gin.Context) {\n\tmeta := NewMetaData(c, webserver.CtxI18n(c, \"首页\"))\n\n\tdata := gin.H{\n\t\t\"meta\":  meta,\n\t\t\"alert\": Alert(c, \"\", \"\"),\n\t}\n\n\tc.HTML(http.StatusOK, \"home.html\", data)\n\treturn\n}\n```\n\n其中文字\"首页\"将被自动翻译为多语言。\n\n### 自动提取i18n翻译文本并自动翻译\n\n需先安装python脚本依赖：`pip install -r ./misc/i18n/requirements.txt`\n\n自动提取需要翻译文字生成翻译模板并完成自动谷歌翻译：`./i18n.sh`\n\n打开对应路径（默认为`statics/i18n`）下的po文件进行校验修改，msgid为原始字符串，对应的msgstr是翻译后的语言。\n\n### 自定义数据源提取翻译文本\n\n如果需要从数据库等自定义数据源提取需要翻译的文本，可以通过插件机制实现：\n\n1. 在 `misc/i18n/plugins/` 目录下创建插件文件，例如 `db_strings.py`：\n```python\n#!/usr/bin/env python3\n\nfrom typing import Set\nimport os\nimport sys\n\n# 添加项目根目录到 Python 路径\nproject_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))\nsys.path.append(project_root)\n\n# 导入你的数据库模型和连接\n# from your_app.models import YourModel\n\ndef extract_strings() -\u003e Set[str]:\n    \"\"\"\n    从数据库提取需要翻译的字符串\n    返回类型必须是 Set[str]\n    \"\"\"\n    strings = set()\n    try:\n        # 实现你的数据库查询逻辑\n        # 例如：\n        # db = get_db_connection()\n        # results = db.query(YourModel).all()\n        # for item in results:\n        #     strings.add(item.title)\n        #     strings.add(item.description)\n        pass\n    except Exception as e:\n        print(f\"Error extracting strings from database: {e}\")\n    return strings\n```\n\n2. 插件文件必须实现 `extract_strings()` 函数，该函数返回一个字符串集合\n3. 运行 `./i18n.sh` 时会自动加载并执行所有插件\n4. 插件执行结果会被合并到最终的翻译模板中\n\n插件系统特点：\n- 模块化：每个数据源可以有自己的插件\n- 可扩展：轻松添加新的数据源\n- 解耦：数据源逻辑与主程序分离\n- 容错：单个插件失败不影响整体运行\n- 灵活：插件可以访问项目的任何模块和依赖","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiaoxin-com%2Fpink-lady","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxiaoxin-com%2Fpink-lady","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiaoxin-com%2Fpink-lady/lists"}