Skip to content

Commit c8e942c

Browse files
authored
Merge pull request #246 from yokowu/feat-scanner
feat: 实现扫描器
2 parents fbe458d + 7ac32a8 commit c8e942c

File tree

10 files changed

+280
-16
lines changed

10 files changed

+280
-16
lines changed

.github/workflows/backend-ci-cd.yml

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,26 @@ jobs:
160160
cache-from: type=gha
161161
cache-to: type=gha,mode=max
162162

163+
- name: Build and push scanner image
164+
uses: docker/build-push-action@v5
165+
with:
166+
context: ./backend
167+
file: ./backend/build/Dockerfile.scanner
168+
push: true
169+
platforms: ${{ matrix.platform }}
170+
tags: |
171+
${{ env.REGISTRY }}/scanner:${{ steps.get_version.outputs.VERSION }}-${{ matrix.arch }}
172+
${{ env.REGISTRY }}/scanner:latest-${{ matrix.arch }}
173+
build-args: |
174+
GOCACHE=/tmp/go-build
175+
GOMODCACHE=/tmp/go-mod
176+
REPO_COMMIT=${{ github.sha }}
177+
VERSION=${{ steps.get_version.outputs.VERSION }}
178+
BUILD_TIME=${{ steps.get_build_time.outputs.BUILD_TIME }}
179+
GIT_COMMIT=${{ steps.get_git_commit.outputs.GIT_COMMIT }}
180+
cache-from: type=gha
181+
cache-to: type=gha,mode=max
182+
163183
create-manifest:
164184
needs: build
165185
runs-on: ubuntu-latest
@@ -176,14 +196,26 @@ jobs:
176196
run: |
177197
VERSION=${{ needs.build.outputs.version }}
178198
179-
# Create and push version manifest
199+
# Create and push backend version manifest
180200
docker manifest create ${{ env.REGISTRY }}/backend:${VERSION} \
181201
${{ env.REGISTRY }}/backend:${VERSION}-x86_64 \
182202
${{ env.REGISTRY }}/backend:${VERSION}-aarch64
183203
docker manifest push ${{ env.REGISTRY }}/backend:${VERSION}
184204
185-
# Create and push latest manifest
205+
# Create and push backend latest manifest
186206
docker manifest create ${{ env.REGISTRY }}/backend:latest \
187207
${{ env.REGISTRY }}/backend:latest-x86_64 \
188208
${{ env.REGISTRY }}/backend:latest-aarch64
189-
docker manifest push ${{ env.REGISTRY }}/backend:latest
209+
docker manifest push ${{ env.REGISTRY }}/backend:latest
210+
211+
# Create and push scanner version manifest
212+
docker manifest create ${{ env.REGISTRY }}/scanner:${VERSION} \
213+
${{ env.REGISTRY }}/scanner:${VERSION}-x86_64 \
214+
${{ env.REGISTRY }}/scanner:${VERSION}-aarch64
215+
docker manifest push ${{ env.REGISTRY }}/scanner:${VERSION}
216+
217+
# Create and push scanner latest manifest
218+
docker manifest create ${{ env.REGISTRY }}/scanner:latest \
219+
${{ env.REGISTRY }}/scanner:latest-x86_64 \
220+
${{ env.REGISTRY }}/scanner:latest-aarch64
221+
docker manifest push ${{ env.REGISTRY }}/scanner:latest

backend/Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ image:
2323
--output ${OUTPUT} \
2424
.
2525

26+
image-scanner:
27+
docker buildx build \
28+
-f build/Dockerfile.scanner \
29+
--build-arg GOCACHE=${GOCACHE} \
30+
--build-arg GOMODCACHE=${GOMODCACHE} \
31+
--build-arg REPO_COMMIT=$(shell git rev-parse HEAD) \
32+
--build-arg VERSION=${VERSION} \
33+
--build-arg BUILD_TIME=${BUILD_TIME} \
34+
--build-arg GIT_COMMIT=${GIT_COMMIT} \
35+
--platform ${PLATFORM} \
36+
--tag ${REGISTRY}/scanner:${TAG} \
37+
--output ${OUTPUT} \
38+
.
39+
2640
wire:
2741
wire pro/cmd/server/wire.go pro/cmd/server/main.go
2842

backend/build/Dockerfile

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,12 @@ go build \
2121
-o /out/main \
2222
pro/cmd/server/main.go pro/cmd/server/wire_gen.go
2323

24-
FROM debian:bullseye-20250721-slim as binary
25-
26-
RUN apt-get update && \
27-
apt-get install -y ca-certificates && \
28-
apt-get clean && \
29-
rm -rf /var/lib/apt/lists/* && \
30-
update-ca-certificates
24+
FROM alpine:3.22.1 as binary
3125

3226
WORKDIR /app
3327

3428
ADD migration ./migration
35-
ADD assets ./assets
29+
ADD assets/vsix ./assets/vsix
3630

3731
COPY --from=builder /out/main /app/main
3832

backend/build/Dockerfile.scanner

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder
2+
3+
WORKDIR /src
4+
ENV CGO_ENABLED=0
5+
6+
COPY go.* .
7+
ARG GOMODCACHE
8+
RUN --mount=type=cache,target=${GOMODCACHE} \
9+
go mod download
10+
11+
ARG TARGETOS TARGETARCH GOCACHE
12+
ARG VERSION
13+
ARG BUILD_TIME
14+
ARG GIT_COMMIT
15+
RUN --mount=type=bind,target=. \
16+
--mount=type=cache,target=${GOMODCACHE} \
17+
--mount=type=cache,target=${GOCACHE} \
18+
GOOS=$TARGETOS GOARCH=$TARGETARCH \
19+
go build \
20+
-ldflags "-w -s -X 'github.com/chaitin/MonkeyCode/backend/pkg/version.Version=${VERSION}' -X 'github.com/chaitin/MonkeyCode/backend/pkg/version.BuildTime=${BUILD_TIME}' -X 'github.com/chaitin/MonkeyCode/backend/pkg/version.GitCommit=${GIT_COMMIT}'" \
21+
-o /out/main \
22+
cmd/scanner/main.go cmd/scanner/wire_gen.go
23+
24+
FROM debian:bullseye-20250721-slim as binary
25+
26+
WORKDIR /app
27+
28+
ADD assets/sgp ./assets/sgp
29+
30+
COPY --from=builder /out/main /app/main
31+
32+
CMD [ "./main" ]

backend/cmd/scanner/main.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"context"
5+
6+
"github.com/google/wire"
7+
8+
"github.com/chaitin/MonkeyCode/backend/config"
9+
v1 "github.com/chaitin/MonkeyCode/backend/internal/scanner/handler/http/v1"
10+
"github.com/chaitin/MonkeyCode/backend/pkg"
11+
"github.com/chaitin/MonkeyCode/backend/pkg/logger"
12+
"github.com/chaitin/MonkeyCode/backend/pkg/service"
13+
"github.com/chaitin/MonkeyCode/backend/pkg/version"
14+
)
15+
16+
func main() {
17+
s, err := newServer()
18+
if err != nil {
19+
panic(err)
20+
}
21+
22+
s.version.Print()
23+
s.logger.With("config", s.config).Debug("config")
24+
s.web.PrintRoutes()
25+
26+
svc := service.NewService(service.WithPprof())
27+
svc.Add(s)
28+
if err := svc.Run(); err != nil {
29+
panic(err)
30+
}
31+
}
32+
33+
// Name implements service.Servicer.
34+
func (s *Server) Name() string {
35+
return "Scanner Server"
36+
}
37+
38+
// Start implements service.Servicer.
39+
func (s *Server) Start() error {
40+
return s.web.Run(s.config.Server.Addr)
41+
}
42+
43+
// Stop implements service.Servicer.
44+
func (s *Server) Stop() error {
45+
return s.web.Echo().Shutdown(context.Background())
46+
}
47+
48+
var AppSet = wire.NewSet(
49+
wire.FieldsOf(new(*config.Config), "Logger"),
50+
config.Init,
51+
pkg.NewWeb,
52+
logger.NewLogger,
53+
version.NewVersionInfo,
54+
v1.NewScannerHandler,
55+
)

backend/cmd/scanner/wire.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//go:build wireinject
2+
// +build wireinject
3+
4+
package main
5+
6+
import (
7+
"log/slog"
8+
9+
"github.com/google/wire"
10+
11+
"github.com/GoYoko/web"
12+
13+
"github.com/chaitin/MonkeyCode/backend/config"
14+
v1 "github.com/chaitin/MonkeyCode/backend/internal/scanner/handler/http/v1"
15+
"github.com/chaitin/MonkeyCode/backend/pkg/version"
16+
)
17+
18+
type Server struct {
19+
config *config.Config
20+
web *web.Web
21+
logger *slog.Logger
22+
version *version.VersionInfo
23+
scanner *v1.ScannerHandler
24+
}
25+
26+
func newServer() (*Server, error) {
27+
wire.Build(
28+
wire.Struct(new(Server), "*"),
29+
AppSet,
30+
)
31+
return &Server{}, nil
32+
}

backend/cmd/scanner/wire_gen.go

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/domain/security.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ func (s *SecurityScanningBrief) From(e *db.SecurityScanning) *SecurityScanningBr
7070
return s
7171
}
7272

73+
type ScanReq struct {
74+
TaskID string `json:"task_id"`
75+
UserID string `json:"user_id"`
76+
Workspace string `json:"workspace"` // 项目目录
77+
Language consts.SecurityScanningLanguage `json:"language"` // 扫描语言
78+
}
79+
7380
type CreateSecurityScanningReq struct {
7481
UserID string `json:"user_id"`
7582
Workspace string `json:"workspace"` // 项目目录

backend/internal/proxy/usecase/proxy.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import (
44
"context"
55
"fmt"
66
"log/slog"
7+
"net/http"
78
"os"
89
"path"
9-
"strings"
1010
"time"
1111

1212
"github.com/redis/go-redis/v9"
@@ -38,7 +38,13 @@ func NewProxyUsecase(
3838
cfg *config.Config,
3939
redis *redis.Client,
4040
) domain.ProxyUsecase {
41-
client := request.NewClient("http", "monkeycode-scanner:8888", 15*time.Second)
41+
client := request.NewClient("http", "monkeycode-scanner:8888", 30*time.Minute, request.WithTransport(&http.Transport{
42+
MaxIdleConns: 100,
43+
MaxIdleConnsPerHost: 100,
44+
MaxConnsPerHost: 100,
45+
IdleConnTimeout: 90 * time.Second,
46+
ForceAttemptHTTP2: true,
47+
}))
4248
client.SetDebug(cfg.Debug)
4349
p := &ProxyUsecase{
4450
repo: repo,
@@ -128,7 +134,7 @@ func (p *ProxyUsecase) TaskHandle(ctx context.Context, task *queuerunner.Task[do
128134
p.logger.With("id", id).With("error", err).ErrorContext(ctx, "failed to get security scanning")
129135
return err
130136
}
131-
prefix := fmt.Sprintf("/app/codes/%s", id)
137+
prefix := fmt.Sprintf("/app/static/codes/%s", id)
132138
rootPath := path.Join(prefix, scanning.Edges.WorkspaceEdge.RootPath)
133139
defer os.RemoveAll(prefix)
134140

@@ -151,8 +157,13 @@ func (p *ProxyUsecase) TaskHandle(ctx context.Context, task *queuerunner.Task[do
151157
return err
152158
}
153159

154-
rule := strings.ToLower(string(scanning.Language))
155-
result, err := scan.Scan(task.ID, rootPath, rule)
160+
result, err := request.Post[scan.Result](p.client, "/api/v1/scan", domain.ScanReq{
161+
TaskID: task.ID,
162+
UserID: task.Data.UserID,
163+
Workspace: rootPath,
164+
Language: task.Data.Language,
165+
})
166+
156167
if err != nil {
157168
if err = p.securityRepo.Update(ctx, id, consts.SecurityScanningStatusFailed, &scan.Result{
158169
Output: err.Error(),
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package v1
2+
3+
import (
4+
"fmt"
5+
"log/slog"
6+
"net/http"
7+
"strings"
8+
9+
"github.com/GoYoko/web"
10+
11+
"github.com/chaitin/MonkeyCode/backend/domain"
12+
"github.com/chaitin/MonkeyCode/backend/pkg/scan"
13+
)
14+
15+
type ScannerHandler struct {
16+
logger *slog.Logger
17+
}
18+
19+
func NewScannerHandler(w *web.Web, logger *slog.Logger) *ScannerHandler {
20+
s := &ScannerHandler{
21+
logger: logger,
22+
}
23+
24+
w.POST("/api/v1/scan", web.BindHandler(s.Scan))
25+
26+
return s
27+
}
28+
29+
func (s *ScannerHandler) Scan(ctx *web.Context, req domain.ScanReq) error {
30+
rule := strings.ToLower(string(req.Language))
31+
result, err := scan.Scan(req.TaskID, req.Workspace, rule)
32+
if err != nil {
33+
s.logger.With("id", req.TaskID).With("error", err).ErrorContext(ctx.Request().Context(), "failed to scan")
34+
return fmt.Errorf("failed to scan: %w", err)
35+
}
36+
s.logger.With("id", req.TaskID).InfoContext(ctx.Request().Context(), "task done")
37+
return ctx.JSON(http.StatusOK, result)
38+
}

0 commit comments

Comments
 (0)