From 971cdd4461a8e3e44c7379d3b0b8e97b9d73941f Mon Sep 17 00:00:00 2001 From: Michael DiLeo Date: Sun, 14 Dec 2025 19:51:36 +0100 Subject: [PATCH] add parts for odcker build and gitea action build --- .dockerignore | 37 ++++++++++++++ .gitea/workflows/README.md | 69 ++++++++++++++++++++++++++ .gitea/workflows/build-release.yml | 80 ++++++++++++++++++++++++++++++ Dockerfile | 58 ++++++++++++++++++++++ app.py | 1 + pyproject.toml | 10 +++- 6 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .gitea/workflows/README.md create mode 100644 .gitea/workflows/build-release.yml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..99c8355 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# Git +.git +.gitignore + +# Python +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +*.so +*.egg +*.egg-info +dist +build +.venv +venv +env + +# IDE +.vscode +.idea +*.swp +*.swo + +# Documentation +README.md +*.md + +# Config (user should provide their own) +config.yaml + +# Docs (user should mount their own) +docs/*.txt + +# CI/CD +.gitea diff --git a/.gitea/workflows/README.md b/.gitea/workflows/README.md new file mode 100644 index 0000000..7a390f8 --- /dev/null +++ b/.gitea/workflows/README.md @@ -0,0 +1,69 @@ +# Gitea Actions Workflows + +This directory contains Gitea Actions workflows for automated builds and releases. + +## Build and Release Workflow + +The `build-release.yml` workflow automatically builds Docker images and attaches them to Gitea releases. + +### Setup + +1. **Enable Gitea Actions**: Ensure Actions are enabled on your Gitea instance (Settings → Actions) + +2. **Configure Token**: The workflow uses `secrets.GITHUB_TOKEN` which Gitea provides automatically. If your Gitea version uses a different token name, you may need to: + - Update the workflow to use `secrets.GITEA_TOKEN` instead + - Or create a custom token secret in your repository settings + +3. **API URL**: The workflow uses `github.api_url` which Gitea Actions should provide. If you encounter issues, you may need to manually set the Gitea API URL in the workflow. + +### Usage + +**Automatic Release on Tag Push:** +```bash +git tag v1.0.0 +git push origin v1.0.0 +``` + +The workflow will: +1. Build a Docker image tagged with the version +2. Save it as a compressed tar file +3. Create or update a Gitea release +4. Attach the tar file to the release + +**Manual Trigger:** +You can also trigger the workflow manually from the Gitea Actions UI. The image will be saved as an artifact (not attached to a release). + +### Loading the Image + +After downloading the `.tar.gz` file from a release: + +```bash +# Load the image +docker load < automatic-linkedin-answer-ai-v1.0.0.tar.gz + +# Verify it's loaded +docker images | grep automatic-linkedin-answer-ai + +# Run the container +docker run -it \ + -v $(pwd)/config.yaml:/app/config.yaml \ + -v $(pwd)/docs:/app/docs \ + automatic-linkedin-answer-ai:v1.0.0 +``` + +### Troubleshooting + +**Workflow fails with authentication errors:** +- Check that Actions are enabled on your Gitea instance +- Verify the token secret is available (should be automatic with Gitea Actions) +- If using a self-hosted Gitea, ensure the API URL is accessible from the runner + +**Release not created:** +- Ensure you're pushing a tag that matches the pattern `v*` (e.g., `v1.0.0`) +- Check the workflow logs for specific error messages +- Verify you have write permissions to the repository + +**Image too large:** +- The workflow compresses the image with gzip +- Consider using multi-stage builds in the Dockerfile to reduce image size +- You may need to adjust Gitea's upload size limits if the image is very large diff --git a/.gitea/workflows/build-release.yml b/.gitea/workflows/build-release.yml new file mode 100644 index 0000000..9a3e92f --- /dev/null +++ b/.gitea/workflows/build-release.yml @@ -0,0 +1,80 @@ +name: Build Docker Image and Release + +on: + push: + tags: + - 'v*' # Triggers on version tags like v1.0.0 + workflow_dispatch: # Allows manual triggering + +jobs: + build-and-release: + runs-on: ubuntu-latest + permissions: + contents: write # Required to create/update releases + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract version from tag + id: tag_version + run: | + if [[ "${{ github.ref }}" == refs/tags/* ]]; then + VERSION=${GITHUB_REF#refs/tags/} + echo "version=$VERSION" >> $GITHUB_OUTPUT + else + VERSION="latest-$(date +%Y%m%d-%H%M%S)" + echo "version=$VERSION" >> $GITHUB_OUTPUT + fi + + - name: Build Docker image + run: | + docker build -t automatic-linkedin-answer-ai:${{ steps.tag_version.outputs.version }} \ + -t automatic-linkedin-answer-ai:latest . + + - name: Save Docker image as tar + run: | + docker save automatic-linkedin-answer-ai:${{ steps.tag_version.outputs.version }} \ + | gzip > automatic-linkedin-answer-ai-${{ steps.tag_version.outputs.version }}.tar.gz + ls -lh automatic-linkedin-answer-ai-*.tar.gz + + - name: Create or update release (Gitea API) + if: startsWith(github.ref, 'refs/tags/') + run: | + TAG_NAME=${GITHUB_REF#refs/tags/} + RELEASE_NAME="Release $TAG_NAME" + IMAGE_FILE="automatic-linkedin-answer-ai-$TAG_NAME.tar.gz" + + # Check if release exists + RELEASE_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "${{ github.api_url }}/repos/${{ github.repository }}/releases/tags/$TAG_NAME" \ + | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) + + if [ -z "$RELEASE_ID" ]; then + # Create new release + curl -X POST \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"$TAG_NAME\",\"name\":\"$RELEASE_NAME\",\"draft\":false,\"prerelease\":false}" \ + "${{ github.api_url }}/repos/${{ github.repository }}/releases" > /tmp/release.json + + RELEASE_ID=$(grep -o '"id":[0-9]*' /tmp/release.json | head -1 | cut -d':' -f2) + fi + + # Upload asset + curl -X POST \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/gzip" \ + --data-binary "@$IMAGE_FILE" \ + "${{ github.api_url }}/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$IMAGE_FILE" + + - name: Upload image artifact (for manual builds) + if: github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: docker-image + path: automatic-linkedin-answer-ai-*.tar.gz + retention-days: 30 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..508a4ac --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +# Use Python 3.11 as base image +FROM python:3.11-slim + +# Install system dependencies required for browser automation and other tools +RUN apt-get update && apt-get install -y \ + wget \ + curl \ + git \ + build-essential \ + chromium \ + chromium-driver \ + fonts-liberation \ + libappindicator3-1 \ + libasound2 \ + libatk-bridge2.0-0 \ + libatk1.0-0 \ + libcups2 \ + libdbus-1-3 \ + libdrm2 \ + libgbm1 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libx11-xcb1 \ + libxcomposite1 \ + libxdamage1 \ + libxrandr2 \ + xdg-utils \ + && rm -rf /var/lib/apt/lists/* + +# Install uv for fast Python package management +RUN pip install --no-cache-dir uv + +# Set working directory +WORKDIR /app + +# Copy dependency files +COPY pyproject.toml uv.lock ./ + +# Install dependencies using uv +RUN uv sync --frozen + +# Copy application code +COPY app.py ./ + +# Create docs directory (user should mount their own config.yaml and docs) +RUN mkdir -p docs + +# Set Python path to use uv's virtual environment +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONUNBUFFERED=1 + +# Set Chrome/Chromium path for browser automation +ENV CHROMIUM_PATH=/usr/bin/chromium +ENV CHROME_PATH=/usr/bin/chromium + +# Default command (user should override with their own config.yaml) +CMD ["python", "app.py"] diff --git a/app.py b/app.py index 4b9e2c3..2e077cb 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,7 @@ import asyncio import logging import os +import time import yaml from browser_use import Agent diff --git a/pyproject.toml b/pyproject.toml index 7b6cb40..e04a171 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,4 +4,12 @@ version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.8" -dependencies = [] +dependencies = [ + "browser-use", + "langchain", + "langchain-community", + "langchain-openai", + "langchain-text-splitters", + "python-dotenv", + "pyyaml", +] -- 2.49.1