Jenkinsfile 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. // Helper function for database operations
  2. def executeDbQuery(String query, String description = null) {
  3. echo "SQL query: ${query} ### ${description}"
  4. sh """mysql -u ${DEPLOY_DB_USER} --password=${DEPLOY_DB_PWD} -D ${DEPLOY_DB_NAME} -h ${DEPLOY_DB_HOST} -e "${query}" """
  5. }
  6. // Helper function for database operations
  7. def executeDbMultiQuery(String queries, String description = null) {
  8. echo "SQL query: ${queries} ### ${description}"
  9. sh """mysql -u ${DEPLOY_DB_USER} --password=${DEPLOY_DB_PWD} -D ${DEPLOY_DB_NAME} -h ${DEPLOY_DB_HOST} << 'EOF'
  10. ${queries}
  11. EOF"""
  12. }
  13. pipeline {
  14. agent any
  15. options {
  16. buildDiscarder(logRotator(numToKeepStr: '10'))
  17. timeout(time: 60, unit: 'MINUTES')
  18. timestamps()
  19. }
  20. environment {
  21. // Node.js configuration
  22. PATH = "/var/lib/jenkins/.nvm/versions/node/v24.16.0/bin:$PATH"
  23. // Binary paths
  24. PHP = "/usr/bin/php8.3"
  25. GIT = "git"
  26. CURL = "curl"
  27. PHING = "/usr/bin/phing-3.1.0.phar"
  28. DOXYGEN = "/usr/bin/doxygen"
  29. COMPOSER_PHAR = "/usr/bin/composer.phar"
  30. // Modules to install
  31. MODULES = "bx_posts,bx_timeline,bx_contact,bx_developer,bx_antispam,bx_convos,bx_organizations,bx_notifications,bx_ether,bx_accounts,bx_albums,bx_facebook,bx_tricon,bx_oauth,bx_payment,bx_market,bx_groups,bx_intercom,bx_googlecon,bx_linkedin,bx_twitter,bx_mailchimp,bx_forum,bx_acl,bx_events,bx_files,bx_glossary,bx_googletagman,bx_photos,bx_polls,bx_profiler,bx_quoteofday,bx_smtp,bx_shopify,bx_snipcart,bx_se_migration,bx_spaces,bx_stripe_connect,bx_videos,bx_charts,bx_dolcon,bx_fontawesome,bx_channels,bx_attendant,bx_massmailer,bx_directory,bx_plyr,bx_ads,bx_lucid,bx_credits,bx_wiki,bx_tasks,bx_courses,bx_classes,bx_artificer,bx_donations,bx_feedback,bx_help_tours,bx_stream,bx_attendant,bx_messenger,bx_analytics,bx_reputation,bx_ru"
  32. // Test install parameters
  33. INSTALL_DB_NAME = "mainsite_virtual"
  34. INSTALL_DB_USER = "mainsite_una"
  35. INSTALL_DB_PWD = "*****"
  36. // Package parameters
  37. PACKAGE_PUBLISH_DIR = "/var/www/vhosts/mainsite/html/builds"
  38. PACKAGE_PUBLISH_LATEST_FILE = "${PACKAGE_PUBLISH_DIR}/latest-file.txt"
  39. PACKAGE_PUBLISH_LATEST_DATE = "${PACKAGE_PUBLISH_DIR}/latest-date.txt"
  40. PACKAGE_PUBLISH_LATEST_BUILD = "${PACKAGE_PUBLISH_DIR}/latest-build.txt"
  41. // Deploy parameters
  42. DEPLOY_PATH = "/var/www/vhosts/mainsite/html/test"
  43. DEPLOY_HTTP_HOST = "ci.una.io"
  44. DEPLOY_HTTP_PATH = "/test/"
  45. DEPLOY_DOC_ROOT = "/var/www/vhosts/mainsite/html"
  46. DEPLOY_DB_HOST = "127.0.0.1"
  47. DEPLOY_DB_NAME = "mainsite_una"
  48. DEPLOY_DB_USER = "mainsite_una"
  49. DEPLOY_DB_PWD = "*****"
  50. // Documentation parameters
  51. DOCS_OUTPUT = "/var/www/vhosts/mainsite/html/docs"
  52. // Environment flags
  53. UNA_HTTPS = "1"
  54. // Date stamp for package
  55. DSTAMP = sh(script: 'date +"%Y%m%d"', returnStdout: true).trim()
  56. ZIPFILE = "UNA-${DSTAMP}-${BUILD_NUMBER}.zip"
  57. // Demo users
  58. DEMO_USERS_PASS = "*****"
  59. DEMO_USERS_SALT = "*****"
  60. DEMO_S3_BUCKET = "una-ci"
  61. DEMO_S3_ENDPOINT = "us-east-1.linodeobjects.com"
  62. DEMO_S3_KEY = "*****"
  63. DEMO_S3_SECRET = "*****"
  64. DEMO_GOOGLE_MAPS_API_KEY = "*****"
  65. DEMO_MESSENGER_URL = "https://ci.una.io"
  66. DEMO_API_OAUTH_ID = "*****"
  67. DEMO_API_OAUTH_SECRET = "*****"
  68. DEMO_API_KEY = "*****"
  69. DEMO_SOCKETS_URL = "https://ci.una.io"
  70. DEMO_SOCKETS_APP_ID = "neo-ci"
  71. DEMO_SOCKETS_KEY = "neo-ci"
  72. DEMO_SOCKETS_SECRET = "*****"
  73. TEST_USER_ADMIN_PWD = "*****"
  74. TEST_USER_REGULAR_PWD = "*****"
  75. TEST_USER_TOM_PWD = "*****"
  76. }
  77. stages {
  78. stage('Prepare & worspace clean up') {
  79. steps {
  80. script {
  81. echo "Cleaning workspace before proceeding"
  82. // Clean up workspace
  83. cleanWs(
  84. cleanWhenAborted: true,
  85. cleanWhenFailure: true,
  86. cleanWhenNotBuilt: true,
  87. cleanWhenSuccess: true,
  88. cleanWhenUnstable: true,
  89. deleteDirs: true,
  90. disableDeferredWipeout: true
  91. )
  92. echo "NodeJS version:"
  93. sh 'node -v'
  94. echo "Starting UNA CI/CD Pipeline"
  95. echo "Build Number: ${BUILD_NUMBER}"
  96. echo "Package File: ${ZIPFILE}"
  97. }
  98. }
  99. }
  100. stage('Clone UNA repository') {
  101. steps {
  102. git branch: 'master',
  103. url: 'https://github.com/unacms/UNA/',
  104. credentialsId: '0043feeb-9df7-4494-9b2b-d6c8a1b8ca08'
  105. }
  106. }
  107. stage('Clone additional UNA modules') {
  108. parallel {
  109. /*
  110. stage('Clone: Media Manager') {
  111. steps {
  112. dir('modules/boonex/media') {
  113. git branch: 'master',
  114. url: 'git@github.com:unacms/media-manager.git',
  115. credentialsId: '0043feeb-9df7-4494-9b2b-d6c8a1b8ca08'
  116. }
  117. }
  118. }
  119. */
  120. stage('Clone: Messenger') {
  121. steps {
  122. dir('modules/boonex/messenger') {
  123. git branch: 'master',
  124. url: 'git@github.com:unacms/jot-client-una.git',
  125. credentialsId: '628aae6d-1c6a-437f-aa13-6f74c0167dfc'
  126. }
  127. }
  128. }
  129. }
  130. }
  131. stage('Build messenger') {
  132. steps {
  133. script {
  134. dir('modules/boonex/messenger') {
  135. echo "Building messenger"
  136. sh 'yarn && yarn build'
  137. }
  138. }
  139. }
  140. }
  141. stage('Install dependencies') {
  142. steps {
  143. script {
  144. echo "Cleaning some files"
  145. sh '${PHP} ${PHING} clean_install'
  146. echo "Install PHP and JS dependences"
  147. sh '${PHP} ${PHING} -verbose -Dphp=${PHP} -Dcomposer=${COMPOSER_PHAR} prepare'
  148. }
  149. }
  150. }
  151. stage('Test installation') {
  152. steps {
  153. script {
  154. echo "Setting up permissions"
  155. sh '${PHP} ${PHING} change_permissions'
  156. echo "Performing installation for testing"
  157. sh '''
  158. ${PHP} ${PHING} -verbose -debug \
  159. -Dphp=${PHP} \
  160. -Ddb_name=${INSTALL_DB_NAME} \
  161. -Ddb_user=${INSTALL_DB_USER} \
  162. -Ddb_password=${INSTALL_DB_PWD} \
  163. -Dmodules="${MODULES}" \
  164. install
  165. '''
  166. }
  167. }
  168. }
  169. stage('Unit tests') {
  170. steps {
  171. script {
  172. echo "Running PHP Unit Tests"
  173. def status = sh(
  174. script: "${PHP} plugins/bin/phpunit -c tests/phpunit.xml",
  175. returnStatus: true
  176. )
  177. echo "PHPUnit exit code: ${status}"
  178. }
  179. }
  180. post {
  181. always {
  182. // Publish test results if they exist
  183. archiveArtifacts artifacts: 'logs/junit.xml', allowEmptyArchive: true
  184. junit checksName: 'Unit-Tests', testResults: 'logs/junit.xml'
  185. }
  186. }
  187. }
  188. stage('Code Quality Analysis') {
  189. steps {
  190. script {
  191. echo "Running PHP Copy Paste Detector"
  192. sh '''
  193. ${PHP} -d memory_limit=512M /usr/bin/phpcpd.phar --min-lines 18 --log-pmd logs/phpcpd.xml \
  194. --exclude plugins \
  195. --exclude plugins_public \
  196. --exclude modules/boonex/xero/plugins \
  197. --exclude upgrade \
  198. --exclude cache \
  199. --exclude cache_public \
  200. --exclude storage \
  201. --exclude logs \
  202. --exclude tmp \
  203. --exclude samples \
  204. --exclude tests \
  205. --exclude modules/boonex/lucid/data \
  206. --exclude modules/boonex/decorous/data \
  207. --exclude modules/boonex/protean/data \
  208. --exclude modules/boonex/artificer/data \
  209. --exclude modules/boonex/membership_pricing \
  210. --exclude modules/boonex/se_migration \
  211. --exclude modules/boonex/dolphin_migration \
  212. --exclude modules/boonex/anon_follow \
  213. --exclude modules/boonex/plyr/updates \
  214. --exclude modules/boonex/classes/updates \
  215. --exclude modules/boonex/nexus/updates \
  216. --exclude modules/boonex/dolphin_migration/updates \
  217. --exclude modules/boonex/accounts/updates \
  218. --exclude modules/boonex/invites/updates \
  219. --exclude modules/boonex/files/updates \
  220. --exclude modules/boonex/intercom/updates \
  221. --exclude modules/boonex/oauth2/updates \
  222. --exclude modules/boonex/linkedin_connect/updates \
  223. --exclude modules/boonex/videos/updates \
  224. --exclude modules/boonex/market/updates \
  225. --exclude modules/boonex/russian/updates \
  226. --exclude modules/boonex/decorous/updates \
  227. --exclude modules/boonex/groups/updates \
  228. --exclude modules/boonex/lucid/updates \
  229. --exclude modules/boonex/api/updates \
  230. --exclude modules/boonex/fontawesome/updates \
  231. --exclude modules/boonex/spaces/updates \
  232. --exclude modules/boonex/elasticsearch/updates \
  233. --exclude modules/boonex/google_connect/updates \
  234. --exclude modules/boonex/froala/updates \
  235. --exclude modules/boonex/twitter_connect/updates \
  236. --exclude modules/boonex/payment/updates \
  237. --exclude modules/boonex/artificer/updates \
  238. --exclude modules/boonex/events/updates \
  239. --exclude modules/boonex/messenger/updates \
  240. --exclude modules/boonex/donations/updates \
  241. --exclude modules/boonex/google_tagmanager/updates \
  242. --exclude modules/boonex/contact/updates \
  243. --exclude modules/boonex/polls/updates \
  244. --exclude modules/boonex/developer/updates \
  245. --exclude modules/boonex/mailchimp/updates \
  246. --exclude modules/boonex/snipcart/updates \
  247. --exclude modules/boonex/chat_plus/updates \
  248. --exclude modules/boonex/persons/updates \
  249. --exclude modules/boonex/glossary/updates \
  250. --exclude modules/boonex/xero/updates \
  251. --exclude modules/boonex/charts/updates \
  252. --exclude modules/boonex/credits/updates \
  253. --exclude modules/boonex/acl/updates \
  254. --exclude modules/boonex/massmailer/updates \
  255. --exclude modules/boonex/ocean/updates \
  256. --exclude modules/boonex/markerio/updates \
  257. --exclude modules/boonex/english/updates \
  258. --exclude modules/boonex/profiler/updates \
  259. --exclude modules/boonex/shopify/updates \
  260. --exclude modules/boonex/timeline/updates \
  261. --exclude modules/boonex/forum/updates \
  262. --exclude modules/boonex/smtpmailer/updates \
  263. --exclude modules/boonex/albums/updates \
  264. --exclude modules/boonex/antispam/updates \
  265. --exclude modules/boonex/photos/updates \
  266. --exclude modules/boonex/courses/updates \
  267. --exclude modules/boonex/ads/updates \
  268. --exclude modules/boonex/posts/updates \
  269. --exclude modules/boonex/protean/updates \
  270. --exclude modules/boonex/wiki/updates \
  271. --exclude modules/boonex/facebook_connect/updates \
  272. --exclude modules/boonex/convos/updates \
  273. --exclude modules/boonex/dolphin_connect/updates \
  274. --exclude modules/boonex/tasks/updates \
  275. --exclude modules/boonex/help_tours/updates \
  276. --exclude modules/boonex/stripe_connect/updates \
  277. --exclude modules/boonex/stream/updates \
  278. --exclude modules/boonex/datafox/updates \
  279. --exclude modules/boonex/notifications/updates \
  280. --exclude modules/boonex/attendant/updates \
  281. --exclude modules/boonex/channels/updates \
  282. --exclude modules/boonex/analytics/updates \
  283. --exclude modules/boonex/una_connect/updates \
  284. --exclude modules/boonex/quoteofday/updates \
  285. --exclude modules/boonex/organizations/updates \
  286. --exclude modules/boonex/plyr/install/config.php \
  287. --exclude modules/boonex/classes/install/config.php \
  288. --exclude modules/boonex/nexus/install/config.php \
  289. --exclude modules/boonex/dolphin_migration/install/config.php \
  290. --exclude modules/boonex/accounts/install/config.php \
  291. --exclude modules/boonex/invites/install/config.php \
  292. --exclude modules/boonex/files/install/config.php \
  293. --exclude modules/boonex/intercom/install/config.php \
  294. --exclude modules/boonex/oauth2/install/config.php \
  295. --exclude modules/boonex/linkedin_connect/install/config.php \
  296. --exclude modules/boonex/videos/install/config.php \
  297. --exclude modules/boonex/market/install/config.php \
  298. --exclude modules/boonex/russian/install/config.php \
  299. --exclude modules/boonex/decorous/install/config.php \
  300. --exclude modules/boonex/groups/install/config.php \
  301. --exclude modules/boonex/lucid/install/config.php \
  302. --exclude modules/boonex/api/install/config.php \
  303. --exclude modules/boonex/fontawesome/install/config.php \
  304. --exclude modules/boonex/spaces/install/config.php \
  305. --exclude modules/boonex/elasticsearch/install/config.php \
  306. --exclude modules/boonex/google_connect/install/config.php \
  307. --exclude modules/boonex/froala/install/config.php \
  308. --exclude modules/boonex/twitter_connect/install/config.php \
  309. --exclude modules/boonex/payment/install/config.php \
  310. --exclude modules/boonex/artificer/install/config.php \
  311. --exclude modules/boonex/events/install/config.php \
  312. --exclude modules/boonex/messenger/install/config.php \
  313. --exclude modules/boonex/donations/install/config.php \
  314. --exclude modules/boonex/google_tagmanager/install/config.php \
  315. --exclude modules/boonex/contact/install/config.php \
  316. --exclude modules/boonex/polls/install/config.php \
  317. --exclude modules/boonex/developer/install/config.php \
  318. --exclude modules/boonex/mailchimp/install/config.php \
  319. --exclude modules/boonex/snipcart/install/config.php \
  320. --exclude modules/boonex/chat_plus/install/config.php \
  321. --exclude modules/boonex/persons/install/config.php \
  322. --exclude modules/boonex/glossary/install/config.php \
  323. --exclude modules/boonex/xero/install/config.php \
  324. --exclude modules/boonex/charts/install/config.php \
  325. --exclude modules/boonex/credits/install/config.php \
  326. --exclude modules/boonex/acl/install/config.php \
  327. --exclude modules/boonex/massmailer/install/config.php \
  328. --exclude modules/boonex/ocean/install/config.php \
  329. --exclude modules/boonex/markerio/install/config.php \
  330. --exclude modules/boonex/english/install/config.php \
  331. --exclude modules/boonex/profiler/install/config.php \
  332. --exclude modules/boonex/shopify/install/config.php \
  333. --exclude modules/boonex/timeline/install/config.php \
  334. --exclude modules/boonex/forum/install/config.php \
  335. --exclude modules/boonex/smtpmailer/install/config.php \
  336. --exclude modules/boonex/albums/install/config.php \
  337. --exclude modules/boonex/antispam/install/config.php \
  338. --exclude modules/boonex/photos/install/config.php \
  339. --exclude modules/boonex/courses/install/config.php \
  340. --exclude modules/boonex/ads/install/config.php \
  341. --exclude modules/boonex/posts/install/config.php \
  342. --exclude modules/boonex/protean/install/config.php \
  343. --exclude modules/boonex/wiki/install/config.php \
  344. --exclude modules/boonex/facebook_connect/install/config.php \
  345. --exclude modules/boonex/convos/install/config.php \
  346. --exclude modules/boonex/dolphin_connect/install/config.php \
  347. --exclude modules/boonex/tasks/install/config.php \
  348. --exclude modules/boonex/help_tours/install/config.php \
  349. --exclude modules/boonex/stripe_connect/install/config.php \
  350. --exclude modules/boonex/stream/install/config.php \
  351. --exclude modules/boonex/datafox/install/config.php \
  352. --exclude modules/boonex/notifications/install/config.php \
  353. --exclude modules/boonex/attendant/install/config.php \
  354. --exclude modules/boonex/channels/install/config.php \
  355. --exclude modules/boonex/analytics/install/config.php \
  356. --exclude modules/boonex/una_connect/install/config.php \
  357. --exclude modules/boonex/quoteofday/install/config.php \
  358. --exclude modules/boonex/organizations/install/config.php \
  359. . || true
  360. '''
  361. echo "Checking log files:"
  362. sh 'ls -la logs/'
  363. }
  364. }
  365. post {
  366. always {
  367. // Archive code quality reports
  368. // archiveArtifacts artifacts: 'logs/phpcpd.xml', allowEmptyArchive: true, followSymlinks: false
  369. recordIssues(
  370. sourceCodeRetention: 'LAST_BUILD',
  371. tools: [cpd(pattern: 'logs/phpcpd.xml')]
  372. )
  373. }
  374. }
  375. }
  376. stage('Install Composer production dependencies') {
  377. steps {
  378. script {
  379. echo "Installing Composer production dependencies"
  380. sh '''
  381. ${COMPOSER_PHAR} install \
  382. --no-dev \
  383. --no-interaction \
  384. --prefer-dist \
  385. --optimize-autoloader
  386. '''
  387. }
  388. }
  389. }
  390. stage('Package Build') {
  391. steps {
  392. script {
  393. echo "Creating package: ${ZIPFILE}"
  394. sh '${PHP} ${PHING} -Dpackage_file=${ZIPFILE} package'
  395. sh 'cp "packages/${ZIPFILE}" ${PACKAGE_PUBLISH_DIR}'
  396. // Update latest build info
  397. sh 'echo ${ZIPFILE} > ${PACKAGE_PUBLISH_LATEST_FILE}'
  398. sh 'date +"%Y.%m.%d" > ${PACKAGE_PUBLISH_LATEST_DATE}'
  399. sh 'echo ${BUILD_NUMBER} > ${PACKAGE_PUBLISH_LATEST_BUILD}'
  400. }
  401. }
  402. post {
  403. success {
  404. archiveArtifacts artifacts: "packages/${ZIPFILE}", fingerprint: true
  405. }
  406. }
  407. }
  408. stage('Deployment') {
  409. steps {
  410. script {
  411. echo "Cleaning up test site"
  412. sh '"${DEPLOY_PATH}/../../cleanup_test_site.sh"'
  413. echo "Deploying to test environment"
  414. sh '''
  415. ${PHP} ${PHING} \
  416. -Dphp=${PHP} \
  417. -Ddeploy_path=${DEPLOY_PATH} \
  418. -Dhttp_host=${DEPLOY_HTTP_HOST} \
  419. -Dhttp_path=${DEPLOY_HTTP_PATH} \
  420. -Ddoc_root=${DEPLOY_DOC_ROOT} \
  421. -Ddb_name=${DEPLOY_DB_NAME} \
  422. -Ddb_host=${DEPLOY_DB_HOST} \
  423. -Ddb_user=${DEPLOY_DB_USER} \
  424. -Ddb_password=${DEPLOY_DB_PWD} \
  425. -Dmodules="${MODULES}" \
  426. deploy
  427. '''
  428. }
  429. }
  430. }
  431. stage('Database Configuration') {
  432. steps {
  433. script {
  434. echo "Configuring database for UI tests"
  435. // Enable Lucid icons
  436. executeDbQuery(
  437. "UPDATE sys_options SET value = 'sys_lucide' WHERE name = 'sys_iconset_default'",
  438. "Enable Lucid icons"
  439. )
  440. // Maps API key
  441. executeDbQuery(
  442. "UPDATE sys_options SET value = '${DEMO_GOOGLE_MAPS_API_KEY}' WHERE name = 'sys_maps_api_key'",
  443. "Setting Google Maps API key"
  444. )
  445. // Messenger server
  446. executeDbQuery(
  447. "UPDATE sys_options SET value = '${DEMO_MESSENGER_URL}' WHERE name = 'bx_messenger_server_url'",
  448. "Configuring messenger server URL"
  449. )
  450. // SMTP mailer
  451. executeDbQuery(
  452. "UPDATE sys_options SET value = 'on' WHERE name = 'bx_smtp_on'",
  453. "Enabling SMTP mailer"
  454. )
  455. executeDbQuery(
  456. "UPDATE sys_options SET value = 'localhost' WHERE name = 'bx_smtp_host'",
  457. "Configuring SMTP mailer host"
  458. )
  459. executeDbQuery(
  460. "UPDATE sys_options SET value = '1025' WHERE name = 'bx_smtp_port'",
  461. "Configuring SMTP mailer port"
  462. )
  463. // Create test users
  464. echo "Creating test users"
  465. def users = ['agent', 'user', 'lily', 'eva', 'linda', 'emma', 'karen', 'ella', 'viky', 'mila', 'eric', 'luck', 'jack', 'rob', 'dave', 'tom', 'andy', 'ivan']
  466. users.each { user ->
  467. executeDbMultiQuery("""
  468. SET sql_mode = '';
  469. INSERT INTO sys_accounts (name, email, email_confirmed, receive_updates, receive_news, password, salt, role, added) VALUES
  470. ('${user}', '${user}@example.com', 1, 0, 0, SHA1(CONCAT(MD5('${DEMO_USERS_PASS}'), '${DEMO_USERS_SALT}')), '${DEMO_USERS_SALT}', 1, UNIX_TIMESTAMP());
  471. SET @iAccountId = LAST_INSERT_ID();
  472. INSERT INTO sys_profiles (account_id, type, content_id, status) VALUES
  473. (@iAccountId, 'system', @iAccountId, 'active');
  474. """, "Creating user: ${user}")
  475. }
  476. // Storage configuration
  477. echo "Configuring S3 storage"
  478. executeDbQuery(
  479. "UPDATE sys_options SET value = '${DEMO_S3_KEY}' WHERE name = 'sys_storage_s3_access_key'",
  480. "Setting S3 access key"
  481. )
  482. executeDbQuery(
  483. "UPDATE sys_options SET value = '${DEMO_S3_SECRET}' WHERE name = 'sys_storage_s3_secret_key'",
  484. "Setting S3 secret key"
  485. )
  486. executeDbQuery(
  487. "UPDATE sys_options SET value = '${DEMO_S3_BUCKET}' WHERE name = 'sys_storage_s3_bucket'",
  488. "Setting S3 bucket name"
  489. )
  490. executeDbQuery(
  491. "UPDATE sys_options SET value = '${DEMO_S3_ENDPOINT}' WHERE name = 'sys_storage_s3_endpoint'",
  492. "Setting S3 endpoint"
  493. )
  494. executeDbQuery(
  495. "UPDATE sys_objects_storage SET engine = 'S3'",
  496. "Switching storage engine to S3"
  497. )
  498. // SEO URI rewrites
  499. executeDbQuery(
  500. "INSERT INTO sys_seo_uri_rewrites SET uri_orig = 'view-persons-profile', uri_rewrite = 'u'",
  501. "Adding person profile URL rewrite"
  502. )
  503. executeDbQuery(
  504. "INSERT INTO sys_seo_uri_rewrites SET uri_orig = 'view-organization-profile', uri_rewrite = 'o'",
  505. "Adding organization profile URL rewrite"
  506. )
  507. // Enable subgroups
  508. executeDbQuery(
  509. "UPDATE sys_objects_privacy SET spaces = 'bx_events,bx_spaces,bx_groups' WHERE object = 'bx_groups_allow_view_to'",
  510. "Enabling subgroups functionality"
  511. )
  512. // Tmp fix for search via API
  513. executeDbQuery(
  514. "UPDATE sys_objects_search SET GlobalSearch = '0' WHERE ObjectName IN('sys_pages', 'bx_timeline')",
  515. "Tmp fix for search via API"
  516. )
  517. }
  518. }
  519. }
  520. stage('API Configuration') {
  521. parallel {
  522. stage('Old API Setup') {
  523. steps {
  524. script {
  525. echo "Configuring old OAuth API"
  526. executeDbMultiQuery("""
  527. INSERT INTO bx_oauth_clients (title, client_id, client_secret, redirect_uri, grant_types, scope, parent_id, user_id) VALUES
  528. ('nextjs', '${DEMO_API_OAUTH_ID}', '${DEMO_API_OAUTH_SECRET}', 'http://app.una.io:3000/', NULL, 'service', 0, 1);
  529. SET @iClientId = LAST_INSERT_ID();
  530. INSERT INTO bx_oauth_allowed_origins (client_id, url) VALUES
  531. (@iClientId, 'https://ci.una.io:3000');
  532. """, "Setting up OAuth client and allowed origins")
  533. }
  534. }
  535. }
  536. stage('New API Setup') {
  537. steps {
  538. script {
  539. echo "Configuring new API system"
  540. executeDbMultiQuery("""
  541. INSERT INTO sys_api_keys (title, `key`, `order`) VALUES
  542. ('NextJS', '${DEMO_API_KEY}', 1);
  543. INSERT INTO sys_api_origins (url, `order`) VALUES
  544. ('neo://app', 1),
  545. ('http://localhost:3000', 2),
  546. ('https://neo.vercel.app/', 4),
  547. ('https://neo.so/', 5),
  548. ('http://hihi.com', 6),
  549. ('https://hihi.com', 7),
  550. ('https://neo-ci.una.io', 8);
  551. UPDATE sys_options SET value = 'on' WHERE name = 'sys_api_enable';
  552. UPDATE sys_options SET value = '' WHERE name = 'sys_api_access_by_origin';
  553. UPDATE sys_options SET value = 'on' WHERE name = 'sys_api_access_by_key';
  554. UPDATE sys_options SET value = 'on' WHERE name = 'sys_session_auth';
  555. """, "Setting up new API keys, origins and enabling API features")
  556. }
  557. }
  558. }
  559. stage('Sockets Server Setup') {
  560. steps {
  561. script {
  562. echo "Configuring sockets server"
  563. executeDbMultiQuery("""
  564. UPDATE sys_options SET value = 'sys_sockets_soketi' WHERE name = 'sys_sockets_type';
  565. UPDATE sys_options SET value = '${DEMO_SOCKETS_URL}' WHERE name = 'sys_sockets_url';
  566. UPDATE sys_options SET value = '${DEMO_SOCKETS_APP_ID}' WHERE name = 'sys_sockets_app_id';
  567. UPDATE sys_options SET value = '${DEMO_SOCKETS_KEY}' WHERE name = 'sys_sockets_key';
  568. UPDATE sys_options SET value = '${DEMO_SOCKETS_SECRET}' WHERE name = 'sys_sockets_secret';
  569. """, "Configuring Soketi sockets server settings")
  570. }
  571. }
  572. }
  573. stage('AI Agents Setup') {
  574. steps {
  575. script {
  576. echo "Creating vector store file"
  577. sh '''
  578. mkdir -p -m 0777 "${DEPLOY_PATH}/storage/vector_stores/1"
  579. cp /var/lib/jenkins/neuron.store ${DEPLOY_PATH}/storage/vector_stores/1/data.store
  580. chmod 0666 "${DEPLOY_PATH}/storage/vector_stores/1/data.store"
  581. '''
  582. echo "Configuring AI agents"
  583. executeDbMultiQuery("""
  584. UPDATE `sys_agents_models` SET `active` = 1, `changed` = UNIX_TIMESTAMP() WHERE `type` = 'ollama' AND `model` = 'llama3.2:1b';
  585. UPDATE `sys_agents_models` SET `active` = 1, `changed` = UNIX_TIMESTAMP() WHERE `type` = 'ollama-embeddings' AND `model` = 'all-minilm';
  586. SET @model_embedding = (SELECT `id` FROM `sys_agents_models` WHERE `type` = 'ollama-embeddings' AND `model` = 'all-minilm');
  587. UPDATE `sys_agents_vector_store` SET `active` = 1, `changed` = UNIX_TIMESTAMP(), `embedding_provider_id` = @model_embedding WHERE `type` = 'file';
  588. SET @vector_store = (SELECT `id` FROM `sys_agents_vector_store` WHERE `type` = 'file');
  589. INSERT INTO `sys_agents_vector_store_data` (`id`, `vector_store_id`, `type`, `name`, `size`, `metadata`, `settings`, `content`, `status`, `added`) VALUES
  590. (NULL, @vector_store, 'custom', 'data_for_vector_store.md', 189, '', '{\"chunk_size\":512,\"delimeter\":\".\",\"overlap\":2}', 'Documentation is very important. UNACMS is modular CMS written in PHP and backed by MySQL database. UNA CMS features such modules as Posts, Discussions, Notifications, Timeline and others.\n', 'ready', UNIX_TIMESTAMP());
  591. SET @model = (SELECT `id` FROM `sys_agents_models` WHERE `type` = 'ollama' AND `model` = 'llama3.2:1b');
  592. SET @profile = (SELECT `p`.`id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON(`p`.`account_id` = `a`.id) WHERE `email` = '');
  593. INSERT INTO `sys_agents_agents` (`id`, `name`, `title`, `description`, `icon`, `model_id`, `profile_id`, `acl_levels`, `prompt_system`, `prompt_steps`, `prompt_output`, `prompt_tools`, `tools`, `tools_max_run`, `limit_message`, `chat_history_context`, `vector_store_id`, `trigger`, `async`, `alert`, `scheduler_cron`, `webhook_key`, `webhook_sample`, `form_object`, `form_input`, `agent_sample`, `message_profile_id`, `added`, `active`) VALUES
  594. (NULL, 'john-agent', 'John Agent', '', '', @model, @profile, 2147483647, 'You are real person. Your name is John. You can talk freely with anyone.', '', '', '', '', 0, '', 50000, @vector_store, 'message', 0, '', '', '', '', '', '', '', 0, UNIX_TIMESTAMP(), 1),
  595. (NULL, 'profile-description-agent', 'Profile Description Agent', '', '', @model, @profile, 2147483646, 'Write a biography from first person. ', '', '', '', '', 0, '', 0, @vector_store, 'form-input', 0, '', '', '', '', 'bx_person', 'description', '', 0, UNIX_TIMESTAMP(), 1);
  596. """, "Configuring local Ollama AI providers, embedder and agents")
  597. }
  598. }
  599. }
  600. }
  601. }
  602. stage('UI Tests') {
  603. steps {
  604. timeout(time: 6, unit: 'MINUTES') {
  605. script {
  606. echo "Creating cache directories"
  607. sh '''
  608. mkdir -p -m 0777 "${DEPLOY_PATH}/cache/CSS"
  609. mkdir -p -m 0777 "${DEPLOY_PATH}/cache/HTML"
  610. mkdir -p -m 0777 "${DEPLOY_PATH}/cache/URI"
  611. '''
  612. dir('una-ui-test3') {
  613. echo "Clone repository with tests"
  614. git branch: 'main',
  615. url: 'git@github.com:unacms/una-ui-test3.git',
  616. credentialsId: '628aae6d-1c6a-437f-aa13-6f74c0167dfc'
  617. // Create environment file
  618. sh '''
  619. cat > .env.local << EOF
  620. baseUrl=https://${DEPLOY_HTTP_HOST}${DEPLOY_HTTP_PATH}
  621. userAdminPwd=${TEST_USER_ADMIN_PWD}
  622. userRegularPwd=${TEST_USER_REGULAR_PWD}
  623. userTomPwd=${TEST_USER_TOM_PWD}
  624. EOF
  625. '''
  626. echo "Install dependences for UI tests"
  627. sh 'npm install'
  628. sh 'npx playwright install'
  629. echo "Running Playwright UI Tests"
  630. sh 'npm run test'
  631. }
  632. }
  633. }
  634. }
  635. post {
  636. always {
  637. // Archive test results
  638. archiveArtifacts artifacts: 'una-ui-test3/results/results.xml', allowEmptyArchive: true
  639. junit checksName: 'UI-Tests', testResults: 'una-ui-test3/results/results.xml'
  640. }
  641. }
  642. }
  643. // end
  644. }
  645. post {
  646. /*
  647. always {
  648. xunit checksName: 'UI-Tests', thresholds: [
  649. failed(failureNewThreshold: '0', failureThreshold: '0', unstableNewThreshold: '0', unstableThreshold: '0')
  650. ],
  651. tools: [
  652. JUnit(excludesPattern: '', pattern: 'una-ui-test3/results/results.xml', stopProcessingIfError: true)
  653. ]
  654. }
  655. */
  656. success {
  657. echo 'UNA CI/CD Pipeline completed successfully!'
  658. }
  659. failure {
  660. echo 'UNA CI/CD Pipeline failed!'
  661. script {
  662. emailext(
  663. subject: "Build Failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
  664. body: "Build failed!\nCheck console output at ${env.BUILD_URL}\n\nCommit author: ${env.CHANGE_AUTHOR ?: 'unknown'}",
  665. to: "${env.CHANGE_AUTHOR_EMAIL}"
  666. )
  667. slackSend(
  668. botUser: true,
  669. channel: '#unacms',
  670. color: '#ff4444',
  671. iconEmoji: '👮',
  672. message: "Build failed!\nCheck console output at ${env.BUILD_URL}\n\nCommit author: ${env.CHANGE_AUTHOR ?: 'unknown'}",
  673. notifyCommitters: true,
  674. tokenCredentialId: 'slack-jenkins-bot-token'
  675. )
  676. }
  677. }
  678. unstable {
  679. echo 'UNA CI/CD Pipeline completed with test failures!'
  680. }
  681. }
  682. }