pipeline { agent any options { timeout(time: 20, unit: 'MINUTES') timestamps() buildDiscarder(logRotator(numToKeepStr: '10')) disableConcurrentBuilds() } triggers { cron('H/30 * * * *') } environment { VENV_DIR = 'venv' PIP_CACHE_DIR = "${WORKSPACE}/.pip-cache" PYTHONUNBUFFERED = '1' } stages { // ───────────────────────────────────────────── // 1. Checkout // ───────────────────────────────────────────── stage('Checkout Code') { steps { checkout scm } } // ───────────────────────────────────────────── // 2. Python env + dependencies // ───────────────────────────────────────────── stage('Setup Python & Install Dependencies') { steps { sh ''' set -euxo pipefail # Create venv python3 -m venv "${VENV_DIR}" # Upgrade pip toolchain "${VENV_DIR}/bin/python" -m pip install --upgrade pip wheel setuptools # Install all required packages "${VENV_DIR}/bin/pip" install \ --cache-dir "${PIP_CACHE_DIR}" \ -U \ atproto \ playwright \ playwright-stealth \ yt-dlp \ httpx \ arrow \ python-dotenv \ moviepy \ beautifulsoup4 \ charset-normalizer \ Pillow \ grapheme # ── Sanity checks ────────────────────────────────── "${VENV_DIR}/bin/python" -c "import moviepy; print('moviepy OK')" "${VENV_DIR}/bin/python" -c "import atproto; print('atproto OK')" "${VENV_DIR}/bin/python" -c "import playwright; print('playwright OK')" "${VENV_DIR}/bin/python" -c "import playwright_stealth; print('playwright_stealth OK')" "${VENV_DIR}/bin/python" -c "import yt_dlp; print('yt_dlp OK')" # ── System tools ─────────────────────────────────── ffmpeg -version | head -1 ffprobe -version | head -1 # ── Playwright browser binaries (no sudo needed) ─── "${VENV_DIR}/bin/python" -m playwright install chromium ''' } } // ───────────────────────────────────────────── // 3. Run the bot // ───────────────────────────────────────────── stage('Run Script') { steps { withCredentials([ string( credentialsId: 'TIKTOK_JIJANTESFC_HANDLE', variable: 'TIKTOK_JIJANTESFC_HANDLE' ), string( credentialsId: 'BSKY_JIJANTESFC_HANDLE', variable: 'BSKY_JIJANTESFC_HANDLE' ), string( credentialsId: 'BSKY_JIJANTESFC_APP_PASSWORD', variable: 'BSKY_JIJANTESFC_APP_PASSWORD' ), // Secret File: upload tiktok_cookies.json once via // Jenkins → Manage Credentials → Secret file // ID: TIKTOK_COOKIES_JSON file( credentialsId: 'TIKTOK_COOKIES_JSON', variable: 'TIKTOK_COOKIES_FILE' ) ]) { sh ''' set -euxo pipefail # Inject the secret cookies file into the workspace cp "$TIKTOK_COOKIES_FILE" tiktok_cookies.json "${VENV_DIR}/bin/python" tiktok2bsky.py \ --tiktok-handle "$TIKTOK_JIJANTESFC_HANDLE" \ --bsky-handle "$BSKY_JIJANTESFC_HANDLE" \ --bsky-password "$BSKY_JIJANTESFC_APP_PASSWORD" \ --bsky-base-url https://eurosky.social \ --bsky-langs es \ --cookies-path tiktok_cookies.json ''' } } } } // ───────────────────────────────────────────── // Post actions // ───────────────────────────────────────────── post { always { // Archive logs, state, and any CAPTCHA screenshots archiveArtifacts( artifacts: '*.log, *.json, screenshot_*.png', allowEmptyArchive: true ) // Clean up the injected cookies file from workspace // so it is never left on disk between runs sh 'rm -f tiktok_cookies.json || true' } success { echo '✅ Sync cycle completed successfully.' } failure { echo '❌ Sync cycle failed — check archived logs and screenshots.' } unstable { echo '⚠️ Sync cycle finished with warnings.' } } }