diff --git a/.gitignore b/.gitignore
index 1fc116a74..257ef31d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,7 +28,7 @@ vendor/
/answer-data/
/answer
/new_answer
-
+build/tools/
dist/
# Lint setup generated file
diff --git a/.golangci.yaml b/.golangci.yaml
new file mode 100644
index 000000000..af00efc3b
--- /dev/null
+++ b/.golangci.yaml
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+version: "2"
+linters:
+ default: none
+
+formatters:
+ enable:
+ - gofmt
+ settings:
+ gofmt:
+ simplify: true
+ rewrite-rules:
+ - pattern: 'interface{}'
+ replacement: 'any'
diff --git a/Makefile b/Makefile
index 8ab23cce3..fd3f044fa 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,15 @@ Revision=$(shell git rev-parse --short HEAD 2>/dev/null || echo "")
GO_FLAGS=-ldflags="-X github.com/apache/answer/cmd.Version=$(VERSION) -X 'github.com/apache/answer/cmd.Revision=$(Revision)' -X 'github.com/apache/answer/cmd.Time=`date +%s`' -extldflags -static"
GO=$(GO_ENV) "$(shell which go)"
+GOLANGCI_VERSION ?= v2.6.2
+TOOLS_BIN := $(shell mkdir -p build/tools && realpath build/tools)
+
+GOLANGCI = $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION)
+$(GOLANGCI):
+ rm -f $(TOOLS_BIN)/golangci-lint*
+ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_VERSION)/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOLANGCI_VERSION)
+ mv $(TOOLS_BIN)/golangci-lint $(TOOLS_BIN)/golangci-lint-$(GOLANGCI_VERSION)
+
build: generate
@$(GO) build $(GO_FLAGS) -o $(BIN) $(DIR_SRC)
@@ -50,8 +59,12 @@ install-ui-packages:
ui:
@cd ui && pnpm pre-install && pnpm build && cd -
-lint: generate
+lint: generate $(GOLANGCI)
+ @bash ./script/check-asf-header.sh
+ $(GOLANGCI) run
+
+lint-fix: generate $(GOLANGCI)
@bash ./script/check-asf-header.sh
- @gofmt -w -l .
+ $(GOLANGCI) run --fix
all: clean build
diff --git a/docs/docs.go b/docs/docs.go
index c87313917..5e9d5b39d 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -8080,9 +8080,6 @@ const docTemplate = `{
"id": {
"type": "string"
},
- "question_id": {
- "type": "string"
- },
"title": {
"type": "string"
}
@@ -10920,7 +10917,7 @@ const docTemplate = `{
},
"theme_config": {
"type": "object",
- "additionalProperties": true
+ "additionalProperties": {}
}
}
},
@@ -10935,7 +10932,7 @@ const docTemplate = `{
},
"theme_config": {
"type": "object",
- "additionalProperties": true
+ "additionalProperties": {}
},
"theme_options": {
"type": "array",
diff --git a/docs/swagger.json b/docs/swagger.json
index 9f89cb157..e0f6378e4 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -8053,9 +8053,6 @@
"id": {
"type": "string"
},
- "question_id": {
- "type": "string"
- },
"title": {
"type": "string"
}
@@ -10893,7 +10890,7 @@
},
"theme_config": {
"type": "object",
- "additionalProperties": true
+ "additionalProperties": {}
}
}
},
@@ -10908,7 +10905,7 @@
},
"theme_config": {
"type": "object",
- "additionalProperties": true
+ "additionalProperties": {}
},
"theme_options": {
"type": "array",
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index d2dd076cf..e0244083b 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -399,8 +399,6 @@ definitions:
type: string
id:
type: string
- question_id:
- type: string
title:
type: string
required:
@@ -2364,7 +2362,7 @@ definitions:
maxLength: 255
type: string
theme_config:
- additionalProperties: true
+ additionalProperties: {}
type: object
required:
- theme
@@ -2376,7 +2374,7 @@ definitions:
theme:
type: string
theme_config:
- additionalProperties: true
+ additionalProperties: {}
type: object
theme_options:
items:
diff --git a/internal/base/handler/handler.go b/internal/base/handler/handler.go
index 7670feea7..5a4961a3e 100644
--- a/internal/base/handler/handler.go
+++ b/internal/base/handler/handler.go
@@ -31,7 +31,7 @@ import (
)
// HandleResponse Handle response body
-func HandleResponse(ctx *gin.Context, err error, data interface{}) {
+func HandleResponse(ctx *gin.Context, err error, data any) {
lang := GetLang(ctx)
// no error
if err == nil {
@@ -61,7 +61,7 @@ func HandleResponse(ctx *gin.Context, err error, data interface{}) {
}
// BindAndCheck bind request and check
-func BindAndCheck(ctx *gin.Context, data interface{}) bool {
+func BindAndCheck(ctx *gin.Context, data any) bool {
lang := GetLang(ctx)
ctx.Set(constant.AcceptLanguageFlag, lang)
if err := ctx.ShouldBind(data); err != nil {
@@ -79,7 +79,7 @@ func BindAndCheck(ctx *gin.Context, data interface{}) bool {
}
// BindAndCheckReturnErr bind request and check
-func BindAndCheckReturnErr(ctx *gin.Context, data interface{}) (errFields []*validator.FormErrorField) {
+func BindAndCheckReturnErr(ctx *gin.Context, data any) (errFields []*validator.FormErrorField) {
lang := GetLang(ctx)
if err := ctx.ShouldBind(data); err != nil {
log.Errorf("http_handle BindAndCheck fail, %s", err.Error())
diff --git a/internal/base/handler/response.go b/internal/base/handler/response.go
index 827e0b362..51be8a8a1 100644
--- a/internal/base/handler/response.go
+++ b/internal/base/handler/response.go
@@ -34,7 +34,7 @@ type RespBody struct {
// response message
Message string `json:"msg"`
// response data
- Data interface{} `json:"data"`
+ Data any `json:"data"`
}
// TrMsg translate the reason cause as a message
@@ -63,7 +63,7 @@ func NewRespBodyFromError(e *errors.Error) *RespBody {
}
// NewRespBodyData new response body with data
-func NewRespBodyData(code int, reason string, data interface{}) *RespBody {
+func NewRespBodyData(code int, reason string, data any) *RespBody {
return &RespBody{
Code: code,
Reason: reason,
diff --git a/internal/base/pager/pager.go b/internal/base/pager/pager.go
index d7a4caa14..b14d99bfa 100644
--- a/internal/base/pager/pager.go
+++ b/internal/base/pager/pager.go
@@ -27,7 +27,7 @@ import (
)
// Help xorm page helper
-func Help(page, pageSize int, rowsSlicePtr interface{}, rowElement interface{}, session *xorm.Session) (total int64, err error) {
+func Help(page, pageSize int, rowsSlicePtr any, rowElement any, session *xorm.Session) (total int64, err error) {
page, pageSize = ValPageAndPageSize(page, pageSize)
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
diff --git a/internal/base/pager/pagination.go b/internal/base/pager/pagination.go
index 36849fed5..1b09e1f21 100644
--- a/internal/base/pager/pagination.go
+++ b/internal/base/pager/pagination.go
@@ -25,8 +25,8 @@ import (
// PageModel page model
type PageModel struct {
- Count int64 `json:"count"`
- List interface{} `json:"list"`
+ Count int64 `json:"count"`
+ List any `json:"list"`
}
// PageCond page condition
@@ -36,7 +36,7 @@ type PageCond struct {
}
// NewPageModel new page model
-func NewPageModel(totalRecords int64, records interface{}) *PageModel {
+func NewPageModel(totalRecords int64, records any) *PageModel {
sliceValue := reflect.Indirect(reflect.ValueOf(records))
if sliceValue.Kind() != reflect.Slice {
panic("not a slice")
diff --git a/internal/base/server/http_funcmap.go b/internal/base/server/http_funcmap.go
index 9d8e98f96..8f6cac5fc 100644
--- a/internal/base/server/http_funcmap.go
+++ b/internal/base/server/http_funcmap.go
@@ -64,7 +64,7 @@ var funcMap = template.FuncMap{
"formatLinkNofollow": func(data string) template.HTML {
return template.HTML(FormatLinkNofollow(data))
},
- "translator": func(la i18n.Language, data string, params ...interface{}) string {
+ "translator": func(la i18n.Language, data string, params ...any) string {
trans := translator.GlobalTrans.Tr(la, data)
if len(params) > 0 && len(params)%2 == 0 {
@@ -128,8 +128,8 @@ var funcMap = template.FuncMap{
trans = translator.GlobalTrans.Tr(la, "ui.dates.long_date_with_year")
return day.Format(timestamp, trans, tz)
},
- "wrapComments": func(comments []*schema.GetCommentResp, la i18n.Language, tz string) map[string]interface{} {
- return map[string]interface{}{
+ "wrapComments": func(comments []*schema.GetCommentResp, la i18n.Language, tz string) map[string]any {
+ return map[string]any{
"comments": comments,
"language": la,
"timezone": tz,
diff --git a/internal/base/translator/provider.go b/internal/base/translator/provider.go
index 9838d185d..47212e84f 100644
--- a/internal/base/translator/provider.go
+++ b/internal/base/translator/provider.go
@@ -76,14 +76,14 @@ func NewTranslator(c *I18n) (tr i18n.Translator, err error) {
// parse the backend translation
originalTr := struct {
- Backend map[string]map[string]interface{} `yaml:"backend"`
- UI map[string]interface{} `yaml:"ui"`
- Plugin map[string]interface{} `yaml:"plugin"`
+ Backend map[string]map[string]any `yaml:"backend"`
+ UI map[string]any `yaml:"ui"`
+ Plugin map[string]any `yaml:"plugin"`
}{}
if err = yaml.Unmarshal(buf, &originalTr); err != nil {
return nil, err
}
- translation := make(map[string]interface{}, 0)
+ translation := make(map[string]any, 0)
for k, v := range originalTr.Backend {
translation[k] = v
}
diff --git a/internal/base/validator/validator.go b/internal/base/validator/validator.go
index 70c7be2e9..22761c521 100644
--- a/internal/base/validator/validator.go
+++ b/internal/base/validator/validator.go
@@ -187,7 +187,7 @@ func GetValidatorByLang(lang i18n.Language) *MyValidator {
}
// Check /
-func (m *MyValidator) Check(value interface{}) (errFields []*FormErrorField, err error) {
+func (m *MyValidator) Check(value any) (errFields []*FormErrorField, err error) {
defer func() {
if len(errFields) == 0 {
return
@@ -261,7 +261,7 @@ type Checker interface {
Check() (errField []*FormErrorField, err error)
}
-func getObjectTagByFieldName(obj interface{}, fieldName string) (tag string) {
+func getObjectTagByFieldName(obj any, fieldName string) (tag string) {
defer func() {
if err := recover(); err != nil {
log.Error(err)
diff --git a/internal/install/install_from_env.go b/internal/install/install_from_env.go
index a6b668bab..c05d2aaba 100644
--- a/internal/install/install_from_env.go
+++ b/internal/install/install_from_env.go
@@ -133,7 +133,7 @@ func initBaseInfo(env *Env) (err error) {
return requestAPI(req, "POST", "/installation/base-info", InitBaseInfo)
}
-func requestAPI(req interface{}, method, url string, handlerFunc gin.HandlerFunc) error {
+func requestAPI(req any, method, url string, handlerFunc gin.HandlerFunc) error {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
body, _ := json.Marshal(req)
diff --git a/internal/migrations/init.go b/internal/migrations/init.go
index 392ecb2c6..184c986b9 100644
--- a/internal/migrations/init.go
+++ b/internal/migrations/init.go
@@ -208,7 +208,7 @@ func (m *Mentor) initSiteInfoGeneralData() {
}
func (m *Mentor) initSiteInfoLoginConfig() {
- loginConfig := map[string]interface{}{
+ loginConfig := map[string]any{
"allow_new_registrations": true,
"allow_email_registrations": true,
"allow_password_login": true,
@@ -223,7 +223,7 @@ func (m *Mentor) initSiteInfoLoginConfig() {
}
func (m *Mentor) initSiteInfoLegalConfig() {
- legalConfig := map[string]interface{}{
+ legalConfig := map[string]any{
"external_content_display": m.userData.ExternalContentDisplay,
}
legalConfigDataBytes, _ := json.Marshal(legalConfig)
@@ -244,7 +244,7 @@ func (m *Mentor) initSiteInfoThemeConfig() {
}
func (m *Mentor) initSiteInfoSEOConfig() {
- seoData := map[string]interface{}{
+ seoData := map[string]any{
"permalink": constant.PermalinkQuestionID,
"robots": defaultSEORobotTxt + m.userData.SiteURL + "/sitemap.xml",
}
@@ -276,7 +276,7 @@ func (m *Mentor) initSiteInfoUsersConfig() {
}
func (m *Mentor) initSiteInfoPrivilegeRank() {
- privilegeRankData := map[string]interface{}{
+ privilegeRankData := map[string]any{
"level": schema.PrivilegeLevel2,
}
privilegeRankDataBytes, _ := json.Marshal(privilegeRankData)
@@ -288,7 +288,7 @@ func (m *Mentor) initSiteInfoPrivilegeRank() {
}
func (m *Mentor) initSiteInfoWrite() {
- writeData := map[string]interface{}{
+ writeData := map[string]any{
"min_content": 6,
"restrict_answer": true,
"min_tags": 1,
diff --git a/internal/migrations/init_data.go b/internal/migrations/init_data.go
index 96151625d..356a915a7 100644
--- a/internal/migrations/init_data.go
+++ b/internal/migrations/init_data.go
@@ -43,7 +43,7 @@ Sitemap: `
)
var (
- tables = []interface{}{
+ tables = []any{
&entity.Activity{},
&entity.Answer{},
&entity.Collection{},
diff --git a/internal/migrations/v25.go b/internal/migrations/v25.go
index 560a852ac..228c2ef26 100644
--- a/internal/migrations/v25.go
+++ b/internal/migrations/v25.go
@@ -39,7 +39,7 @@ func addFileRecord(ctx context.Context, x *xorm.Engine) error {
if err != nil {
return fmt.Errorf("get legal config failed: %w", err)
}
- legalConfig := make(map[string]interface{})
+ legalConfig := make(map[string]any)
if exist {
if err := json.Unmarshal([]byte(legalInfo.Content), &legalConfig); err != nil {
return fmt.Errorf("unmarshal legal config failed: %w", err)
diff --git a/internal/migrations/v6.go b/internal/migrations/v6.go
index 9171ad47a..88fb58497 100644
--- a/internal/migrations/v6.go
+++ b/internal/migrations/v6.go
@@ -45,7 +45,7 @@ func addNewAnswerNotification(ctx context.Context, x *xorm.Engine) error {
}
}
- m := make(map[string]interface{})
+ m := make(map[string]any)
_ = json.Unmarshal([]byte(cond.Value), &m)
m["new_answer_title"] = "[{{.SiteName}}] {{.DisplayName}} answered your question"
m["new_answer_body"] = "{{.QuestionTitle}}
\n\n{{.DisplayName}}:
\n
{{.AnswerSummary}}