pipeline { agent any options { timeout(time: 15, unit: 'MINUTES') timestamps() buildDiscarder(logRotator(numToKeepStr: '10')) disableConcurrentBuilds() } triggers { cron('H */6 * * *') } stages { stage('Checkout & Setup') { steps { checkout scm sh ''' python3 -m venv venv . venv/bin/activate pip install atproto fastfeedparser beautifulsoup4 httpx arrow charset-normalizer Pillow ''' } } stage('Process All RSS Feeds') { steps { // 🔐 Fetch the single set of EP credentials ONCE for all 26 feeds withCredentials([ string(credentialsId: 'BSKY_EP_HANDLE', variable: 'BSKY_EP_HANDLE'), string(credentialsId: 'BSKY_EP_USERNAME', variable: 'BSKY_EP_USERNAME'), string(credentialsId: 'BSKY_EP_APP_PASSWORD', variable: 'BSKY_EP_APP_PASSWORD') ]) { script { // 📍 The map only contains the hardcoded URLs def feeds = [ // Original 19 Feeds 'badalona': 'https://www.elperiodico.cat/ca/rss/badalona/rss.xml', 'barcelona': 'https://www.elperiodico.cat/ca/rss/barcelona/rss.xml', 'ciencia': 'https://www.elperiodico.cat/ca/rss/ciencia/rss.xml', 'cornella': 'https://www.elperiodico.cat/ca/rss/cornella/rss.xml', 'economia': 'https://www.elperiodico.cat/ca/rss/economia/rss.xml', 'educacio': 'https://www.elperiodico.cat/ca/rss/educacio/rss.xml', 'esports': 'https://www.elperiodico.cat/ca/rss/esports/rss.xml', 'extra': 'https://www.elperiodico.cat/ca/rss/extra/rss.xml', 'gent': 'https://www.elperiodico.cat/ca/rss/gent/rss.xml', 'hospitalet': 'https://www.elperiodico.cat/ca/rss/hospitalet/rss.xml', 'internacional': 'https://www.elperiodico.cat/ca/rss/internacional/rss.xml', 'medi-ambient': 'https://www.elperiodico.cat/ca/rss/medi-ambient/rss.xml', 'motor': 'https://www.elperiodico.cat/ca/rss/motor/rss.xml', 'oci-i-cultura': 'https://www.elperiodico.cat/ca/rss/oci-i-cultura/rss.xml', 'opinio': 'https://www.elperiodico.cat/ca/rss/opinio/rss.xml', 'politica': 'https://www.elperiodico.cat/ca/rss/politica/rss.xml', 'portada': 'https://www.elperiodico.cat/ca/rss/portada/rss.xml', 'que-fer': 'https://www.elperiodico.cat/ca/rss/que-fer/rss.xml', 'sabadell': 'https://www.elperiodico.cat/ca/rss/sabadell/rss.xml', // 7 New Feeds 'sanitat': 'https://www.elperiodico.cat/ca/rss/sanitat/rss.xml', 'santa-coloma': 'https://www.elperiodico.cat/ca/rss/santa-coloma/rss.xml', 'societat': 'https://www.elperiodico.cat/ca/rss/societat/rss.xml', 'tecnologia': 'https://www.elperiodico.cat/ca/rss/tecnologia/rss.xml', 'tele': 'https://www.elperiodico.cat/ca/rss/tele/rss.xml', 'temps': 'https://www.elperiodico.cat/ca/rss/temps/rss.xml', 'terrassa': 'https://www.elperiodico.cat/ca/rss/terrassa/rss.xml' ] def parallelTasks = [:] feeds.each { feedName, feedUrl -> parallelTasks[feedName] = { stage(feedName.capitalize()) { sh """ . venv/bin/activate # The hardcoded URL and updated EP credentials are used here python3 rss2bsky.py \\ "${feedUrl}" \\ "\$BSKY_EP_HANDLE" \\ "\$BSKY_EP_USERNAME" \\ "\$BSKY_EP_APP_PASSWORD" """ } } } // Execute all 26 feeds simultaneously parallel parallelTasks } } } } } }