deploy
This commit is contained in:
parent
1dd59249c5
commit
2589c81797
8 changed files with 245 additions and 2 deletions
23
.gitlab-ci.yml
Normal file
23
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
stages:
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
deploy_production:
|
||||||
|
stage: deploy
|
||||||
|
image: alpine:3.20
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
url: https://jobs-scraper.ai-assistant-bot.xyz
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
|
when: manual
|
||||||
|
allow_failure: false
|
||||||
|
before_script:
|
||||||
|
- apk add --no-cache openssh-client rsync
|
||||||
|
- mkdir -p ~/.ssh
|
||||||
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
|
||||||
|
- chmod 600 ~/.ssh/id_rsa
|
||||||
|
- ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||||
|
script:
|
||||||
|
- ssh "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /opt/apps/jobs-scraper"
|
||||||
|
- rsync -az --delete --exclude='.git' --exclude='.env' --exclude='.env.*' --exclude='.local.env' ./ "$DEPLOY_USER@$DEPLOY_HOST:/opt/apps/jobs-scraper/"
|
||||||
|
- ssh "$DEPLOY_USER@$DEPLOY_HOST" "cd /opt/apps/jobs-scraper/services/scraper-google && docker compose up -d --build"
|
||||||
47
services/scraper-google/.dockerignore
Normal file
47
services/scraper-google/.dockerignore
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Environment files (will be mounted or set via docker-compose)
|
||||||
|
.local.env
|
||||||
|
*.env
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
DOCKER_README.md
|
||||||
|
RECOMMENDED_MODELS.md
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
scraper-google
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
*_test.go
|
||||||
|
testdata/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Docker files (not needed in image)
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
|
.dockerignore
|
||||||
|
|
@ -12,5 +12,5 @@ OPENAI_API_KEY=sk-GtdLX9YBOCsBEgBL4rBONA
|
||||||
OPENAI_BASE_URL=https://hubai.loe.gg/v1
|
OPENAI_BASE_URL=https://hubai.loe.gg/v1
|
||||||
OPENAI_MODEL=gpt-4o-mini
|
OPENAI_MODEL=gpt-4o-mini
|
||||||
|
|
||||||
CV_AI_MODEL=your_ai_model
|
CV_AI_MODEL=alibaba/tongyi-deepresearch-30b-a3b:free
|
||||||
OPENROUTER_API_KEY=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
|
OPENROUTER_API_KEY=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
|
||||||
18
services/scraper-google/.env.example
Normal file
18
services/scraper-google/.env.example
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Database Configuration
|
||||||
|
DB_HOST=postgres
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=jobs_scraper
|
||||||
|
DB_USER=postgres
|
||||||
|
DB_PASSWORD=postgres
|
||||||
|
|
||||||
|
# OpenRouter Configuration (for job description extraction)
|
||||||
|
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
||||||
|
CV_AI_MODEL=google/gemini-flash-1.5
|
||||||
|
|
||||||
|
# Optional: OpenAI Configuration (alternative to OpenRouter)
|
||||||
|
# OPENAI_API_KEY=your_openai_api_key_here
|
||||||
|
# OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
|
|
||||||
|
# Chrome/Chromedp Configuration (usually defaults are fine)
|
||||||
|
CHROMEDP_DISABLE_GPU=true
|
||||||
|
CHROMEDP_NO_SANDBOX=true
|
||||||
40
services/scraper-google/Dockerfile
Normal file
40
services/scraper-google/Dockerfile
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Build stage
|
||||||
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache git
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# Copy go mod files
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# Copy the entire monorepo
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the scraper-google service
|
||||||
|
WORKDIR /build/services/scraper-google
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -o scraper-google .
|
||||||
|
|
||||||
|
# Runtime stage
|
||||||
|
FROM chromedp/headless-shell:latest
|
||||||
|
|
||||||
|
# Install ca-certificates for HTTPS requests
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the binary from builder
|
||||||
|
COPY --from=builder /build/services/scraper-google/scraper-google .
|
||||||
|
|
||||||
|
# Copy environment files if they exist (optional)
|
||||||
|
COPY --from=builder /build/services/scraper-google/.env* ./
|
||||||
|
|
||||||
|
# Expose any ports if needed (not required for this service)
|
||||||
|
# EXPOSE 8080
|
||||||
|
|
||||||
|
# Run the scraper
|
||||||
|
CMD ["./scraper-google"]
|
||||||
67
services/scraper-google/Makefile
Normal file
67
services/scraper-google/Makefile
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
.PHONY: help build up down logs restart clean rebuild
|
||||||
|
|
||||||
|
help: ## Show this help message
|
||||||
|
@echo 'Usage: make [target]'
|
||||||
|
@echo ''
|
||||||
|
@echo 'Available targets:'
|
||||||
|
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
build: ## Build the Docker images
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
up: ## Start all services
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
down: ## Stop all services
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
logs: ## View logs (use 'make logs service=scraper-google' for specific service)
|
||||||
|
@if [ -z "$(service)" ]; then \
|
||||||
|
docker-compose logs -f; \
|
||||||
|
else \
|
||||||
|
docker-compose logs -f $(service); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
restart: ## Restart all services
|
||||||
|
docker-compose restart
|
||||||
|
|
||||||
|
restart-scraper: ## Restart just the scraper service
|
||||||
|
docker-compose restart scraper-google
|
||||||
|
|
||||||
|
clean: ## Stop services and remove volumes (WARNING: deletes data)
|
||||||
|
docker-compose down -v
|
||||||
|
|
||||||
|
rebuild: ## Rebuild and restart services
|
||||||
|
docker-compose down
|
||||||
|
docker-compose build --no-cache
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
ps: ## Show running containers
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
stats: ## Show resource usage
|
||||||
|
docker stats
|
||||||
|
|
||||||
|
exec-db: ## Connect to PostgreSQL database
|
||||||
|
docker-compose exec postgres psql -U postgres -d jobs_scraper
|
||||||
|
|
||||||
|
backup-db: ## Backup the database
|
||||||
|
@mkdir -p backups
|
||||||
|
docker-compose exec postgres pg_dump -U postgres jobs_scraper > backups/backup_$(shell date +%Y%m%d_%H%M%S).sql
|
||||||
|
@echo "Database backed up to backups/backup_$(shell date +%Y%m%d_%H%M%S).sql"
|
||||||
|
|
||||||
|
restore-db: ## Restore database from backup (use 'make restore-db file=backup.sql')
|
||||||
|
@if [ -z "$(file)" ]; then \
|
||||||
|
echo "Error: Please specify backup file. Usage: make restore-db file=backup.sql"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
docker-compose exec -T postgres psql -U postgres jobs_scraper < $(file)
|
||||||
|
|
||||||
|
shell-scraper: ## Open shell in scraper container
|
||||||
|
docker-compose exec scraper-google sh
|
||||||
|
|
||||||
|
dev: ## Run in development mode with live logs
|
||||||
|
docker-compose up --build
|
||||||
|
|
||||||
|
test: ## Run tests (if you have any)
|
||||||
|
docker-compose exec scraper-google go test ./...
|
||||||
49
services/scraper-google/docker-compose.yml
Normal file
49
services/scraper-google/docker-compose.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
scraper-google:
|
||||||
|
build:
|
||||||
|
context: ../../
|
||||||
|
dockerfile: services/scraper-google/Dockerfile
|
||||||
|
container_name: jobs-scraper-google
|
||||||
|
environment:
|
||||||
|
DB_HOST: postgres
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_NAME: jobs_scraper
|
||||||
|
DB_USER: scraper_user
|
||||||
|
DB_PASSWORD: Cocowawa_12345
|
||||||
|
|
||||||
|
# OpenRouter Configuration
|
||||||
|
OPENROUTER_API_KEY: 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
|
||||||
|
CV_AI_MODEL: alibaba/tongyi-deepresearch-30b-a3b:free
|
||||||
|
|
||||||
|
# Optional: OpenAI Configuration
|
||||||
|
OPENAI_API_KEY: sk-GtdLX9YBOCsBEgBL4rBONA
|
||||||
|
OPENAI_BASE_URL: https://hubai.loe.gg/v1
|
||||||
|
OPEN_AI_MODEL: gpt-4o-mini
|
||||||
|
|
||||||
|
# Chrome/Chromedp Configuration
|
||||||
|
CHROMEDP_DISABLE_GPU: true
|
||||||
|
CHROMEDP_NO_SANDBOX: true
|
||||||
|
volumes:
|
||||||
|
- ./.env:/app/.env:ro
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- scraper-network
|
||||||
|
# Add resource limits to prevent runaway chrome instances
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 2G
|
||||||
|
cpus: "2"
|
||||||
|
reservations:
|
||||||
|
memory: 512M
|
||||||
|
cpus: "0.5"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
scraper-network:
|
||||||
|
driver: bridge
|
||||||
|
|
@ -53,7 +53,6 @@ func main() {
|
||||||
log.Fatalf("Failed to start scheduler: %v", err)
|
log.Fatalf("Failed to start scheduler: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process and save jobs immediately as they're scraped
|
|
||||||
go func() {
|
go func() {
|
||||||
for googleLink := range googleLinkStream {
|
for googleLink := range googleLinkStream {
|
||||||
htmlRaw, url, err := utils.GetHTMLRaw(ctx, googleLink)
|
htmlRaw, url, err := utils.GetHTMLRaw(ctx, googleLink)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue