mirror of
https://github.com/langgenius/dify.git
synced 2026-07-20 09:38:32 +08:00
141 lines
5.3 KiB
Makefile
141 lines
5.3 KiB
Makefile
.PHONY: build clean test lint proto gen-cli-help integration integration-up integration-test integration-down
|
|
BIN_DIR := bin
|
|
PROTO_SRC := ../dify-agent/proto/dify/agent/stub/v1/agent_stub.proto
|
|
PROTO_OUT := gen
|
|
AGENT_CLI_HELP_JSON := ../dify-agent/src/dify_agent/layers/_agent_cli_help.json
|
|
|
|
build: $(BIN_DIR)/shellctl $(BIN_DIR)/shellctl-sanitize-pty $(BIN_DIR)/shellctl-runner-exit $(BIN_DIR)/shellctl-runner $(BIN_DIR)/dify-agent gen-cli-help
|
|
|
|
$(BIN_DIR)/shellctl: $(shell find cmd/shellctl internal -name '*.go')
|
|
go build -o $@ ./cmd/shellctl
|
|
|
|
$(BIN_DIR)/shellctl-sanitize-pty: $(shell find cmd/sanitize-pty internal/sanitize -name '*.go')
|
|
go build -o $@ ./cmd/sanitize-pty
|
|
|
|
$(BIN_DIR)/shellctl-runner-exit: $(shell find cmd/runner-exit internal/runner_exit -name '*.go')
|
|
go build -o $@ ./cmd/runner-exit
|
|
|
|
$(BIN_DIR)/shellctl-runner: $(shell find cmd/runner internal/landlock internal/cmdutil -name '*.go')
|
|
go build -o $@ ./cmd/runner
|
|
|
|
|
|
$(BIN_DIR)/dify-agent: $(shell find cmd/dify-agent-cli internal/agentcli internal/stubclient -name '*.go') $(shell find gen -name '*.go' 2>/dev/null)
|
|
go build -o $@ ./cmd/dify-agent-cli
|
|
|
|
# Regenerate the JSON help snapshot from the Go command tree. Runs as part of
|
|
# `build` so the checked-in data never drifts from the CLI.
|
|
gen-cli-help: $(BIN_DIR)/dify-agent
|
|
$(BIN_DIR)/dify-agent __dump-cli-help > $(AGENT_CLI_HELP_JSON)
|
|
|
|
test: lint
|
|
go test ./...
|
|
|
|
lint:
|
|
golangci-lint run ./...
|
|
|
|
proto:
|
|
@mkdir -p $(PROTO_OUT)
|
|
protoc \
|
|
--proto_path=../dify-agent/proto \
|
|
--go_out=$(PROTO_OUT) --go_opt=paths=source_relative \
|
|
--go-grpc_out=$(PROTO_OUT) --go-grpc_opt=paths=source_relative \
|
|
$(PROTO_SRC)
|
|
|
|
clean:
|
|
rm -rf $(BIN_DIR)
|
|
|
|
# --- Integration tests ---
|
|
#
|
|
# Container name and host port are randomised per invocation to avoid
|
|
# conflicts when multiple runs overlap or a previous run leaked a container.
|
|
#
|
|
# State is written to .integration-state so that separate make invocations
|
|
# (integration-up, integration-test, integration-logs, integration-down)
|
|
# can reference the same container. `make integration` runs the full
|
|
# lifecycle in a single invocation with automatic cleanup.
|
|
|
|
IMAGE_NAME := dify-agent-runtime:test
|
|
STATE_FILE := .integration-state
|
|
|
|
integration-up:
|
|
@echo "Building runtime image..."
|
|
docker build -t $(IMAGE_NAME) -f docker/Dockerfile .
|
|
$(eval TEST_ID := $(shell printf '%05d' $$((RANDOM % 100000))))
|
|
$(eval CONTAINER_NAME := sandbox-rt-$(TEST_ID))
|
|
$(eval HOST_PORT := $(shell python3 -c 'import socket; s=socket.socket(); s.bind(("",0)); print(s.getsockname()[1]); s.close()'))
|
|
$(eval AUTH_TOKEN := test-token-$(TEST_ID))
|
|
@echo "Starting runtime container $(CONTAINER_NAME) on port $(HOST_PORT)..."
|
|
docker run -d --name $(CONTAINER_NAME) \
|
|
-p $(HOST_PORT):5004 \
|
|
-e SHELLCTL_AUTH_TOKEN=$(AUTH_TOKEN) \
|
|
$(IMAGE_NAME)
|
|
@echo 'CONTAINER_NAME=$(CONTAINER_NAME)' > $(STATE_FILE)
|
|
@echo 'HOST_PORT=$(HOST_PORT)' >> $(STATE_FILE)
|
|
@echo 'AUTH_TOKEN=$(AUTH_TOKEN)' >> $(STATE_FILE)
|
|
@echo "Waiting for runtime to be ready..."
|
|
@for i in $$(seq 1 30); do \
|
|
if curl -sf http://localhost:$(HOST_PORT)/healthz > /dev/null 2>&1; then \
|
|
echo "Runtime is ready on port $(HOST_PORT)"; \
|
|
break; \
|
|
fi; \
|
|
if [ "$$i" -eq 30 ]; then \
|
|
echo "ERROR: runtime not ready after 60s" >&2; \
|
|
docker logs $(CONTAINER_NAME); \
|
|
docker rm -f $(CONTAINER_NAME) 2>/dev/null; \
|
|
rm -f $(STATE_FILE); \
|
|
exit 1; \
|
|
fi; \
|
|
sleep 2; \
|
|
done
|
|
$(eval CONTAINER_NAME_NOISO := sandbox-rt-noiso-$(TEST_ID))
|
|
$(eval HOST_PORT_NOISO := $(shell python3 -c 'import socket; s=socket.socket(); s.bind(("",0)); print(s.getsockname()[1]); s.close()'))
|
|
$(eval AUTH_TOKEN_NOISO := test-token-noiso-$(TEST_ID))
|
|
@echo "Starting no-isolation container $(CONTAINER_NAME_NOISO) on port $(HOST_PORT_NOISO)..."
|
|
docker run -d --name $(CONTAINER_NAME_NOISO) \
|
|
-p $(HOST_PORT_NOISO):5004 \
|
|
-e SHELLCTL_AUTH_TOKEN=$(AUTH_TOKEN_NOISO) \
|
|
-e SHELLCTL_ENABLE_PATH_ISOLATION=false \
|
|
$(IMAGE_NAME)
|
|
@echo 'CONTAINER_NAME_NOISO=$(CONTAINER_NAME_NOISO)' >> $(STATE_FILE)
|
|
@echo 'HOST_PORT_NOISO=$(HOST_PORT_NOISO)' >> $(STATE_FILE)
|
|
@echo 'AUTH_TOKEN_NOISO=$(AUTH_TOKEN_NOISO)' >> $(STATE_FILE)
|
|
@for i in $$(seq 1 30); do \
|
|
if curl -sf http://localhost:$(HOST_PORT_NOISO)/healthz > /dev/null 2>&1; then \
|
|
echo "No-isolation runtime is ready on port $(HOST_PORT_NOISO)"; \
|
|
break; \
|
|
fi; \
|
|
if [ "$$i" -eq 30 ]; then \
|
|
echo "ERROR: no-isolation runtime not ready after 60s" >&2; \
|
|
docker logs $(CONTAINER_NAME_NOISO); \
|
|
docker rm -f $(CONTAINER_NAME_NOISO) 2>/dev/null; \
|
|
exit 1; \
|
|
fi; \
|
|
sleep 2; \
|
|
done
|
|
|
|
integration-test:
|
|
@test -f $(STATE_FILE) || { echo "ERROR: run 'make integration-up' first" >&2; exit 1; }
|
|
@. ./$(STATE_FILE); \
|
|
SHELLCTL_GO_URL=http://localhost:$$HOST_PORT \
|
|
SHELLCTL_TEST_TOKEN=$$AUTH_TOKEN \
|
|
SHELLCTL_GO_URL_NO_ISOLATION=http://localhost:$$HOST_PORT_NOISO \
|
|
SHELLCTL_TEST_TOKEN_NO_ISOLATION=$$AUTH_TOKEN_NOISO \
|
|
go test -tags=integration -v -count=1 -timeout=300s ./tests/...
|
|
|
|
integration-logs:
|
|
@test -f $(STATE_FILE) || { echo "ERROR: no state file" >&2; exit 1; }
|
|
@. ./$(STATE_FILE); docker logs $$CONTAINER_NAME
|
|
|
|
integration-down:
|
|
@if [ -f $(STATE_FILE) ]; then \
|
|
. ./$(STATE_FILE); \
|
|
docker rm -f $$CONTAINER_NAME 2>/dev/null || true; \
|
|
docker rm -f $$CONTAINER_NAME_NOISO 2>/dev/null || true; \
|
|
rm -f $(STATE_FILE); \
|
|
fi
|
|
|
|
integration:
|
|
@$(MAKE) integration-up
|
|
@trap '$(MAKE) integration-down' EXIT; \
|
|
$(MAKE) integration-test
|