סביבת פיתוח ופריסה

איך מריצים אתר WIZZO CMS מקומית מול עותק של ריפו הליבה, איך שינוי ב-api/core מגיע לאתר חי, ואיך מתבצע עדכון גרסה לצי האתרים.

⏱ 9 דק' קריאה 1597 מילים ערוך דף זה ב-GitHub

הדף מתאר את זרימת העבודה כפי שהיא היום: איפה כותבים קוד, איך הקוד מגיע לשרת, ומה קורה אחר כך באתרי הלקוחות. חלק מהזרימה פנימי ל-Wizzo (פריסה לשרת ה-master), וחלק פתוח לכל מפתח (אתר מקומי ו-PR). הדף מפריד ביניהם במפורש, ובסוף מראה מה המפה המומלצת לפיתוח חיצוני.

system/ בדף הזה הוא תיקיית הליבה הפרוסה באתר, ו-api/core/ היא אותה תיקייה בריפו. {admin} הוא CONFIG::$admin_url.

התמונה הכללית#

הליבה היא תיקייה אחת של קבצי PHP. אין שלב build: אין קומפילציה, אין minify מראש ואין composer install שמורץ על ידי הריפו. "בנייה" פירושה העתקת קבצים.

ריפו wizzo50_core               master (אתר Wizzo)               אתרי הלקוחות
─────────────────               ──────────────────               ─────────────
api/core/  ──העלאה (FTP/SFTP)──►  <site>/system/core  ◄──עדכון גרסה── {admin}/wizzo_update/get
api/js/    ──העלאה──────────────►  <site>/system/js      (הורדת ZIP של הליבה מה-master)
  • ריפו הליבה (wizzo-products/wizzo50_core): api/core/ הוא הליבה, api/js/ ארבעה קבצי JS משותפים. מבנה מלא ב-מבנה הריפו.
  • ה-master: אתר אחד של Wizzo שהליבה שלו היא "האמת". מקבצי הדיסק שלו נבנה ה-ZIP שאתרי הצי מורידים.
  • אתרי הלקוחות: כל אתר מחזיק עותק משלו של הליבה ב-system/core/, ומחליף אותו בעצמו דרך פאנל עדכון ליבה.
מי יכול לפרוס ל-master

ההעלאה ל-master נעשית עם פרטי FTP שמחזיקים רק אנשי Wizzo ומערכת הפריסה האוטומטית של Wizzo. מפתח חיצוני לא פורס ל-master: הוא מפתח מול אתר מקומי משלו ושולח Pull Request. מי שממזג, מפרסם ומקדם גרסה לצי הוא צוות Wizzo.

אתר פיתוח מקומי#

אין היום סביבת פיתוח "בלחיצה אחת": אין docker-compose, אין קובץ CONFIG_USER לדוגמה בריפו ואין קובץ סכימה (ראו מפת דרכים). אתר מקומי נבנה מחלקים, והדרך הבאה עובדת.

דרישות#

רכיבדרישה
PHP8.3 (composer.json של הליבה נועל platform.php = 8.3)
הרחבותpdo_mysql, curl, mbstring, zip, json, openssl, gd
מסד נתוניםMySQL או MariaDB
שרתApache עם mod_rewrite ו-.htaccess שמנתב כל בקשה ל-index.php
Composerלהרצה ידנית בתוך system/core/

פירוט הדרישות ב-דרישות מערכת.

השלבים#

  1. שכפול הריפו לצד תיקיית האתר:
git clone https://github.com/wizzo-products/wizzo50_core.git
  1. שלד אתר: תיקיית אתר רגילה עם index.php, application/ ו-themes/. מבנה התיקיות ב-מבנה התיקיות של אתר, והקמה מלאה ב-התקנת אתר חדש.
  2. הליבה כ-symlink: במקום להעתיק את api/core לאתר, מקשרים אותו. כל עריכה בריפו נראית באתר מיד.
mkdir -p mysite/system
ln -s "$PWD/wizzo50_core/api/core" mysite/system/core
ln -s "$PWD/wizzo50_core/api/js"   mysite/system/js
  1. תלויות Composer: הליבה דורשת system/core/vendor/autoload.php בזמן ריצה (למשל PAGE::is_mobile() טוען אותו). ה-vendor/ לא בריפו ואין composer.lock, ולכן מריצים ידנית:
cd wizzo50_core/api/core
composer install --no-dev
vendor הוא לא חלק מה-git
vendor/ נוצר בתוך api/core/ של העותק שלכם, ולכן הוא יופיע כקבצים לא ממוענים. אל תוסיפו אותו ל-commit. פרטים ב-חבילות Composer.

  1. index.php של האתר מגדיר את CONFIG_USER ואז טוען את הליבה. רשימת המפתחות המלאה ב-CONFIG_USER וב-קונפיגורציה:
<?php
class CONFIG_USER
{
    static $core_path      = __DIR__ . "/system/core";
    static $cache_folder   = "cache";
    static $models_folder  = "application/models";

    static $db_type        = "PDO";
    static $db_host        = "127.0.0.1";
    static $db_port        = 3306;
    static $db_dbname      = "wizzo_local";
    static $db_user        = "wizzo";
    static $db_password    = "local-password";
    static $db_prefix      = "CRM";

    static $admin_url      = "wizzocms";
    static $default_module = "home";
    static $allow_cache    = false;
}

require __DIR__ . "/system/core/core.php";
הדוגמה מוסקת מהקוד

שמות המפתחות מאומתים מול api/core/collections/CONFIG.php ושאר הליבה. אין קובץ דוגמה רשמי, ולכן מפתח שחסר ב-CONFIG_USER מפיל את הבקשה עם Access to undeclared static property. אם נתקלתם בזה, הוסיפו את המפתח עם ערך ריק.

  1. טבלאות בסיס: ה-boot קורא SELECT * FROM CRM_platforms בכל בקשה, ולכן הטבלה חייבת להיות קיימת עם שורה אחת לפחות. שאר הטבלאות הנדרשות ב-boot מפורטות ב-SQL להקמה וב-סכמת הטבלאות.

מלכודות של סביבה מקומית#

מלכודתלמה זה קורה
ה-login לא נשמרCOOKIES::set() שולח תמיד secure=true ו-domain של . + שם המארח. על http:// או על מארח בלי נקודה (localhost) הדפדפן עלול לא לשמור את העוגייה. עדיף HTTPS מקומי ושם מארח כמו mysite.test.
דומיין לא מזוההCONFIG::init() בוחר שורה ב-CRM_platforms לפי $_SERVER['SERVER_NAME']. שם שלא נמצא נופל בשקט לשורה הראשונה בטבלה.
נתיבים שבורים בהרצה לא רגילהCONFIG::$base_path נגזר מהסקריפט הראשי של הבקשה (debug_backtrace()). php -S עם router script או include מסקריפט אחר ישנה את כל הנתיבים.
תאריכים בשעון ישראלCONFIG::preinit() קובע Asia/Jerusalem בלי קשר להגדרות ה-PHP שלכם.
קריאות החוצהחלק מהכלים פונים לשירותי Wizzo Market. על אתר מקומי הם יחזרו שגיאה, וזה צפוי.

משימות cron מקומית#

משימות הרקע רצות מ-CLI עם שורה אחת ב-crontab. MISC::cli_check() הופך כל key=value מה-argv ל-$_GET, ואת url= ל-REQUEST_URI:

* * * * * /usr/bin/php /path/to/mysite/index.php url=system/cron_runner tk=<cron_runner_token>

הטוקן נשמר ב-CRM_params תחת cron_runner_token. פרטים ב-מנהל משימות.

מ-api/core לאתר חי#

שינוי קובץ וצפייה בו#

כשהליבה מקושרת ב-symlink, שמירת קובץ ב-api/core/ משנה את האתר המקומי מיד. אם allow_cache דלוק, או שהשינוי נוגע ב-SCSS, ב-JS מקובץ או בטבלה שנשמרת במטמון, צריך לנקות מטמון: ראו ניקוי ותחזוקה. מטמון הפלטפורמות והפרמטרים נשמר ל-30 יום, ולכן שינוי ב-CRM_platforms או ב-CRM_params לא נראה עד לניקוי.

סקריפטי הפריסה (publish_scripts)#

התיקייה publish_scripts/ בריפו מכילה סקריפטי Node להעלאת קבצים לשרת. אלה הרלוונטיים לליבה:

פקודה (מריצים משורש הריפו)מה עושה
npm run watch:apiצופה בתיקיית api/ (chokidar) ומעלה או מוחק ב-FTP כל קובץ שהשתנה. מצב העבודה היומיומי של צוות Wizzo.
npm run publish:apiמעלה את api/ ל-API_FTP_PATH: מלא, או רק קבצים שהשתנו כש-WIZZOAGENT_CHANGED_FILES מוגדר.
npm run publish:dir <dir> [dev|prod]אותו סקריפט לכל תיקייה. קידומת משתני הסביבה נגזרת משם התיקייה (api נותן API_FTP_*).
npm run wizzoagent_deployהפריסה האוטומטית אחרי merge: מריצה npm run publish:api production.
npm run build:site, npm run publish:siteבנייה והעלאה של אתר התיעוד (תיקיית website/), לא של הליבה.

משתני הסביבה נקראים מקובץ .env בשורש הריפו (או .env.development ו-.env.production). לכל תיקייה יעד חמישה משתנים:

API_FTP_HOST=ftp.example.com
API_FTP_USER=deploy-user
API_FTP_PASSWORD=...
API_FTP_PATH=/site/system/
API_FTP_SCHEME=sftp

API_FTP_PORT אופציונלי (ברירת מחדל 21, או 22 ב-sftp). API_FTP_PATH מצביע על תיקיית system/ של האתר היעד: api/core נוחת ב-system/core ו-api/js ב-system/js.

watch:api מעלה כל שמירה לשרת חי

כשמכוונים אותו ל-master, כל Ctrl+S בעורך משנה קובץ בליבה שאתרי הצי מורידים בעדכון הבא. אין staging ואין rollback ל-master. לפני הרצה ודאו ש-.env מצביע לסביבת פיתוח, ולא תשמרו קבצים ששבורים תחבירית.

פרמטר הסביבה מזהה רק dev ו-prod
publish.generic.js מזהה את הפרמטר השני רק אם הוא בדיוק dev או prod. production (כפי ש-wizzoagent_deploy.js מעביר) מתעלם בשקט. כשקיימים גם .env.development וגם .env.production, הסקריפט מעלה לשניהם ברצף.

עוד שלושה דברים שחשוב לדעת על ההעלאה:

  • לא נמחק כלום בשרת. העלאה מלאה או חלקית לא מוחקת קובץ שהוסר מהריפו, כך שקבצים ישנים נשארים בשרת ובכל ZIP שנבנה ממנו. מחיקה ידנית נדרשת (או watch:api, שכן מוחק).
  • FTP רגיל אינו מוצפן. ברירת המחדל היא ftp עם secure: false. העדיפו API_FTP_SCHEME=sftp.
  • סקריפטי המובייל (build.ps1, build_publish.ps1, build-publish-ios.sh, publish-android.js) וסקריפטי vue-cli-service ב-package.json שייכים לאפליקציה שאינה בריפו. אין להם שימוש בעבודה על הליבה.

מה קורה ב-master אחרי ההעלאה#

אין hook ואין build. הקבצים פשוט יושבים ב-system/core של ה-master. כשאתר כלשהו שואל מה הגרסה העדכנית (check_version/get), ה-master מחשב טביעת אצבע (md5 של נתיב, גודל וזמן עדכון של כל קובץ בליבה, בלי check_version.php). אם אין ZIP שמתאים לטביעה, הוא בונה backups/core-<version>-<fingerprint>.zip ומגיש אותו.

מכאן שני דברים:

  1. כל שינוי בקובץ בליבת ה-master יוצר ZIP חדש, גם בלי לשנות את version.txt. אתר יוריד אותו רק אם מספר הגרסה עלה (ראו גרסאות).
  2. ה-ZIP נבנה מהדיסק החי. קובץ debug או קובץ זמני ששכחתם בתיקיית הליבה של ה-master יגיע לכל האתרים.

controllers/check_version.php עצמו לא נארז ב-ZIP בכוונה: שינוי בו מגיע לאתרים רק בהעלאה ידנית, כדי ש-master פגום לא יוכל לשבש את כל הצי.

עדכון גרסה באתר#

בפאנל הניהול של כל אתר יש מסך "עדכון גרסה" ({admin}/wizzo_update). הפעולה get מבצעת את הרצף הבא (ממומש ב-admin/wizzo_update.php):

  1. בדיקות מקדימות (preflight): גרסת PHP מספקת (php_floor מה-master), הרחבת zip, מקום פנוי בדיסק (לפחות 64MB או פי ארבעה מגודל ה-ZIP) וחיבור למסד הנתונים. כשל מפסיק את העדכון לפני שנגע בכל קובץ.
  2. הורדה ואימות: ה-ZIP יורד לשורש האתר ומאומת מול sha256 שה-master מצהיר עליו.
  3. פריסה בצד: החילוץ נעשה ל-system/core_new_<timestamp>, ונבדק שיש בו core.php ו-version.txt.
  4. החלפה: שני rename ברצף. הליבה הישנה הופכת ל-system/core_bup_<timestamp> והחדשה נכנסת במקומה.
  5. בדיקה אחרי החלפה (postflight): הבקשה /system/core_ping לאתר עצמו. אם היא מחזירה 5xx, תשובה לא תקינה, db:false או גרסה שונה מהצפויה, הליבה החדשה מועברת ל-core_failed_<timestamp> והישנה חוזרת.
  6. סנכרון שאר החלקים (תמיד, גם כשהליבה כבר עדכנית): מבנה הטבלאות (update_db), הפאנלים (update_panel), משימות המערכת של ה-cron (update_cron_system) וקבצי system/js (update_js), והעלאת attaches_version כדי לרענן נכסים.

האתר שומר חמש גרסאות גיבוי אחרונות (core_bup_*). ההיסטוריה נרשמת בטבלה CRM_wizzo_update_log.

כשל &quot;שקט&quot; בבדיקה שאחרי ההחלפה

אם האתר לא מצליח לפנות לעצמו בבקשת HTTP (למשל שרת בלי hairpin NAT), postflight מחזיר הצלחה, ולכן החזרה האוטומטית לא תופעל. בדקו את core_ping ידנית אחרי עדכון על סביבה כזו.

התהליך המלא, כולל ערוצי latest ו-stable, בדף עדכון ליבה.

בדיקה שהליבה חיה#

/system/core_ping מחזיר JSON קטן בלי מטמון, ושימושי גם לבדיקת עשן בסביבה שלכם:

{"ok": true, "version": "5.0.115", "db": true, "php": "8.3.0"}

db: false אומר שהליבה עלתה אבל מסד הנתונים לא ענה לשאילתה SELECT 1. לדיבוג ניתוב של כתובת בודדת מוסיפים ?__router_trace=1 (ראו דיבוג ניתוב), ולדיבוג שאילתות דיבוג SQL.

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.