לדלג לתוכן

סביבות

סביבה היא עותק בעל שם של המודל המנוהל של ארגון. פיזית, העותק הוא סכמת PostgreSQL נפרדת: סכמה אמיתית, בלי עמודת הבחנה ובלי קידומת. לכן כל שאילתת מאגר קיימת נכונה בתוך סביבה בלי שתיכתב מחדש, ופרדיקט שנשכח לא יכול לאפשר לקרוא שורות של סביבה אחת מתוך סביבה אחרת.

כל ארגון מתחיל עם סביבה אחת בשם prod. לא ניתן למחוק אותה או לשנות את שמה. בקשה שאינה נוקבת בשם סביבה מוגשת על ידי prod; בקשה הנוקבת בשם סביבה שאינה קיימת נדחית.

סביבות זמינות לארגונים בתוכנית בתשלום.

כדי למלא סביבה שאינה סביבת ייצור בנתונים שבטוח להשתמש בהם, ראו בניית סביבות בדיקה.

שמות סביבות

שם חייב להתאים ל-[a-z][a-z0-9_]{1,31}: שניים עד שלושים ושניים תווים של אותיות קטנות, ספרות וקווים תחתונים, שמתחילים באות. prod ושמות שמתחילים ב-pg_ נדחים. האורך המרבי לארגון מסוים תלוי במזהה של הארגון. PostgreSQL קוטע בשקט מזהה שארוך מ-63 בתים, והמגבלה מגינה מפני שם הסכמה הארוך ביותר שסביבה גוזרת.

מה עותק נושא

כל טבלה בסכמת הארגון שייכת למחלקה אחת בדיוק. הסיווג הוא רשימת היתר: טבלה שנוספת מאוחר יותר לא עוברת עד שמישהו מציין כאן את המחלקה שלה, כך ששכחה של טבלה מתגלה כבדיקה אדומה.

מחלקה טבלאות מה קורה בהעתקה
CARRIED domains, naming_rules, registered_tables, table_columns, relationships, metrics, roles, rls_rules, tags, tag_param_values, tag_assignments, glossary terms, materialized_views, calendars, api_endpoints, tracked_functions, tracked_webhooks, table_meta_links מועתקות במלואן
IDENTITY_ONLY sources, api_sources, kafka_sources שדות זהות וממשל נודדים; ערכי חיבור נשארים מאחור (ראו קישורים)
SEEDED_AT_CREATION roles, user_role_assignments מועתקות רק כשסביבה נוצרת לראשונה; מיזוגים מאוחרים יותר משאירים אותן לנפשן
PARTIAL org_settings מועתקות לכל מפתח: הגדרות ממשל נודדות, מפתחות הנוקבים ביעד חיצוני או בזמן ריצה לכל סביבה נשארים מאחור
NEVER_SENSITIVE org_secrets, user_directory לעולם אינן מועתקות
NEVER_RUNTIME mv_refresh_log, relationship_candidates, admin_audit_log, ואחרות לעולם אינן מועתקות

‏SEEDED_AT_CREATION קיים כדי לפתור בעיה ספציפית אחת. סביבה חדשה זקוקה לתפקידים ולהקצאות אחרת היא נפתחת כשאיש אינו יכול לפעול. אבל מיזוג מאוחר יותר שהיה נושא את שורת ה-developer של prod היה דורס את הגרסה המוגבלת שענף מוגבל עשוי להזדקק לה, והיה הופך את נתיב הסקירה לדרך ההסלמה. לכן תפקידים והקצאות נודדים פעם אחת, ביצירה, ולאחר מכן הם התשובה של כל סביבה עצמה.

קישורים

קשירות הן העמודות שאומרות לאן מקור מצביע בפועל: host, port, database, username והשאר. הן לעולם לא עוברות בעותק. סביבה שעדיין לא נקשרה מסומנת unbound במקום להישאר ריקה, כי מארח ריק אינו כמו היעדר מארח, ובונה החיבורים היה קורא אותו כ-localhost:5432.

סביבה שנוצרת בכל אופן מלבד Unbound מעתיקה את החיבור של כל מקור מההורה שלה, בדיוק כפי שההורה כתב אותו: הפניית ${secret:...} או ${env:...} מועתקת כאותה הפניה, לעולם לא נפתרת. לאחר היצירה העותק הוא השורה של הסביבה עצמה, הניתנת לעריכה בעמוד המקורות, ודבר אינו נפתר דרך ההורה כשה-runtime של הסביבה נבנה. השדה binding של כל מקור אומר מאיפה הגיע החיבור שלו: copied, own (ניתן בסביבה זו) או unbound. עריכת חיבור מועתק הופכת אותו ל-own. העתקה מחדש מההורה (POST /admin/orgs/{org}/environments/{name}/sources/recopy) מעתיקה שוב את החיבורים של ההורה. מיזוג או פריסה אינם נושאים חיבורים, ולכן מקור שהם מכניסים מגיע כ-unbound.

הטלת ה-git

כל כתיבה למודל מבצעת commit של התוצאה לענף ה-git של הסביבה. פריסה של עץ דורשת קריאה מפורשת: pull request שמוזג במארח ה-git לא פורס את עצמו.

כל ישות מקבלת קובץ אחד. הנתיב הוא כתובת ה-provisa:// של הישות בלי הסכמה והארגון: provisa://acme/sales/tables/Order הופך ל-sales/tables/Order.yaml. מקורות נכנסים ל-sources/, commands ל-commands/ ומדדים ל-metrics/. שורות-ילד שתלויות בהורה (עמודות, קשרים, כללי RLS) נכתבות בתוך הקובץ של ההורה, בלי קבצים משלהן.

פקודות והקצאות התגיות שלהן שורדות את מסע הלוך ושוב. תגית על פקודה מנותבת לקובץ של הפקודה עצמה (commands/<name>.yaml); תגית שאינה שייכת לשום קובץ נעלמת מן ההטלה ותימחק בפריסה הבאה של אותו עץ.

אף מפתח חלופי לא מגיע לקובץ. registered_tables.id הוא מספר שלם שעולה אוטומטית, כך שאותו מודל מקבל מספרים שונים בשתי סביבות, ושפיכה תמימה הייתה שונה מעצמה. כל מפתח חלופי מושמט, וכל הפניה אליו נכתבת כנתיב של היעד.

הסריאליזציה דטרמיניסטית. מפתחות נפלטים לפי סדר אלפביתי, אוספי בת ממוינים לפי כתובתם, וסגנון ה-YAML קבוע. שתי סביבות המחזיקות באותו מודל מייצרות עצים זהים בית-בבית.

מיזוג

מיזוג המודל של סביבה אחת לסביבה אחרת מעדכן לפי זהות: כל אובייקט שיש במקור נוצר או מתעדכן ביעד. אובייקטים שכבר אין במקור מוסרים רק כשהקורא מבקש הסרות במפורש. מיזוג הוא טרנזקציה אחת, ולכן אם הוא נכשל באמצע, היעד נשאר כמו שהיה.

לפני היישום, קראו לנקודת קצה התצוגה המקדימה (GET /{name}/merge-preview) או העבירו dry_run: true. התצוגה המקדימה מריצה את אותו נתיב קוד שהמיזוג משתמש בו; זו נקודת קצה GET כך שסקריפט CI שטועה בדגל אינו יכול ליישם בטעות את המיזוג שהתכוון לבחון.

מיזוג משאיר את הקישורים, התפקידים והסודות של היעד בדיוק כפי שהיו. סביבת פיתוח אינה מאבדת את חיבורי מסד הנתונים שלה עצמה כשהיא לוקחת מודל חדש יותר מ-prod. ‏prod אינו רוכש את ההרשאות של dev.

במה הדוח נוקב

דוח המיזוג מפרט, לפי נתיב, מה נוסף, מה השתנה, מה הוסר ומה נשאר כמו שהיה. הוא גם מציין קונפליקטים: אובייקטים ששני הצדדים שינו מאז ה-commit המשותף האחרון שלהם. קונפליקט מדווח, והמקור גובר, כי זו המשמעות של מיזוג אל יעד. Provisa לא מציע פתרון קונפליקטים, סימוני מיזוג או בחירה לפי אובייקט. הערך של רשימת הקונפליקטים הוא באות: שני אנשים ערכו את אותו אובייקט בלי לדעת.

כששני הצדדים שינו אובייקט לאותו ערך, הם מסכימים, ואין קונפליקט. כששתי הסביבות לא חולקות שום אב קדמון, הבסיס בדוח הוא None, ורשימת קונפליקטים ריקה פירושה ששום דבר לא הושווה, ולא ששום דבר לא התנגש.

המיזוג נוחת כ-commit מאוחד אחד בענף של היעד. הודעת ה-commit היא חובה ואינה יכולה להיות ריקה, כי היא התיאור היחיד של טווח העבודה שה-commit המאוחד מייצג. ה-commits של המקור נשארים במקומם, ואפשר עדיין לפרוס אותם לפי SHA אחר כך.

משיכה

משיכה לוקחת את מה שה-remote מחזיק עבור סביבה והופכת אותו למודל. היא אינה מקדמת את הענף המקומי ישירות ב-fast-forward; היא מיישמת את העץ שהובא דרך נתיב הפריסה הרגיל, כך שאותו אימות ואותה ביקורת הממשלים פריסה ידנית ממשלים משיכה.

כמו מיזוג, pull מדווח מה הוא דרס: אובייקטים שהעץ הנכנס שינה ושגם הסביבה המקומית שינתה מאז ה-commit המשותף האחרון של שני הקווים. שינוי מקומי שמעולם לא עבר commit הופך את הסביבה לסוטה (ראו היסטוריה בהמשך), ו-pull מציין אותו בדוח כשינוי רגיל.

pull נדחה כששני הקווים התפצלו, כלומר לכל אחד יש commits שאין לשני. הדחייה מפרטת את האובייקטים ששני הצדדים נגעו בהם, כדי שמי שצריך עכשיו להחליט של מי העבודה נשארת יידע באילו אובייקטים להסתכל.

היסטוריה

כל פריסה מזיזה קדימה את הסמן של הסביבה לאורך קו ה-commits שלה. ביטול חוזר commit אחד אחורה, ושחזור מתקדם שוב לכיוון הנקודה שממנה הביטול יצא. אף אחד מהם לא מסיר commit: צעד אחורה מוסיף מיקום ומשאיר את ההיסטוריה כמו שהיא.

ענף נזרע בקצה הסביבה שממנה נוצר, ולכן ביטול עוצר בנקודת הזריעה ההיא ואינו הולך אל הקומיטים של סביבת ההורה.

הדגלים can_undo ו-can_redo מגיעים עם התשובה של רשימת הסביבות. שניהם מחזירים false כשההיטל לא מחזיק את ה-commit שמישור הבקרה מציין, מצב שהתכנון מתיר וקורא לו סוטה. צומת שמאגר הקבצים שלו מעולם לא קיבל commit מסוים עדיין מציג את הסביבות שלו; רק התשובות על ההיסטוריה משתנות.

הרשאה

סביבות ממושלות על ידי שתי זכויות. אף אחת מהן אינה של אנליסט כברירת מחדל.

זכות מי מחזיק בה (זרוע) במה היא ממשלת
environment_management org_admin, developer יצירה ומחיקה של סביבות
environment_switch org_admin, developer להיות מוגש על ידי כל סביבה שאינה prod

prod לא דורש שום זכות. הוא זה שמגיש בקשה שלא מציינת סביבה, וסירוב אליו היה סירוב לכל בקשה.

הבדיקה מתבצעת במקום שבו בוחרים את הסביבה, לפני שמגיעים לאיזשהו נתיב. חבר בלי environment_switch נדחה בכל המשטחים בבת אחת (HTTP, GraphQL, SQL ופרוטוקולי החיבור), כי הסביבה נקשרת ב-middleware ולא במטפלים בודדים.

אנליסט שאינו נושא זכות סביבה יכול לשאול את prod ואינו יכול לראות את מחליף הסביבות. קבלן שקיבל את תפקיד האנליסט אינו רואה משטח סביבות ואינו יכול ליצור סביבה כלשהי שאינה ייצור ולא לעבור אליה.

סמכות בעלי הסביבה

יצירת סביבה היא הדרך היחידה שבה חבר עם הרשאת קריאה בלבד מקבל זכויות לעריכת המודל. בתוך סביבה שהוא יצר, היוצר מחזיק ביכולות של התפקיד developer, בלי זכויות הנתונים (write, full_results, usage): זכויות לבנות את המודל, בלי זכויות על הנתונים.

ההענקה נגזרת מ-environments.created_by בזמן ההרשאה, ולעולם אינה נכתבת לטבלת הענקות. מחיקת הסביבה מסירה אותה באותו מעשה.

חברות בדומיין עדיין מגבילה את מה שהבעלים רשאי לשנות. הסתעפות משנה את מה שחבר רשאי לעשות; היא לעולם אינה משנה לאילו דומיינים הוא רשאי לעשות זאת.

סביבות מוגנות

ניתן להגן על סביבה. מיזוג או פריסה לתוך סביבה מוגנת אינם מיושמים כשהם מתבקשים; הם מוצעים, ומישהו שאינו המבקש חייב לאשר אותם.

prod הופך למוגן אוטומטית ברגע שיש בארגון יותר מחבר אחד. ארגון עם חבר יחיד לא יכול לקיים "מישהו אחר מלבד המבקש", ולכן הכלל לא חל שם; הוא היה הופך מיזוג ל-prod לבלתי אפשרי. org_admin יכול לסמן כל סביבה כמוגנת.

בקשת מיזוג היא שורה שנשמרת, ושום חלון אישור לא מחליף אותה. המאשר הוא מעצם ההגדרה מישהו אחר מלבד המבקש, והוא לא נוכח ברגע הבקשה. אישור חולף היה מכריח אישור בתוך הסשן של המבקש, וזה בדיוק הסידור שהכלל אוסר.

שורת הבקשה נושאת את דוח המיזוג לצד הודעת המבקש. התיישנות נגזרת בזמן הקריאה, לעולם אינה מאוחסנת: תכנון מחדש בזמן הקריאה והשוואה מול הדוח המאוחסן היא הגרסה היחידה שאינה יכולה להיות שגויה. בקשה מיושנת חייבת להתבקש מחדש. המבקש אינו יכול לאשר את בקשתו שלו.

מצבי מחזור החיים של בקשה: ‏requested → approved/rejected → applied. stale נגזר.

פריסות מ-ref של מאגר עוברות דרך אותה דלת, והבקשה מקבעת את ה-SHA בזמן ההצעה. אם ה-ref זז בין ההצעה להחלטה, המאשר קורא את הדוח של ה-commit המקובע, ולא של החדש.

Note

ממשק בקשות המיזוג נמצא תחת הלשונית Merge requests בפאנל הסביבות. העמודה Report מציגה מה היה משתנה לפי ספירה; השורה נפתחת כדי להציג פירוט לכל אובייקט.

פקודות ה-CLI ‏env

provisa env deploy שולח את המודל שב-ref לתוך סביבה. הוא מסתיים ב-0 כשהפריסה הוחלה או הייתה ריצת ניסיון, וב-2 כשהסביבה מוגנת והפריסה רק הוצעה. צינור שמתייחס לאישור ממתין כאל פריסה ששוחררה היה טועה, וקוד היציאה מבחין בין השניים.

provisa env deploy --org acme --env prod --ref main --token <token> --api <url>

‏provisa env fetch מביאה את ענפי ה-remote של הארגון אל המאגר המקומי. פריסה יכולה אז לנקוב ב-origin/<branch>.

provisa env fetch --org acme --api <url> --token <token>

שתי הפקודות מקבלות --api (כתובת ה-URL של ה-API של Provisa) ו---token ‏(אסימון bearer). קבעו PROVISA_API_URL ו-PROVISA_API_TOKEN בסביבה כדי להימנע מהעברתם בכל קריאה.

צינור ה-CI הטיפוסי עבור זרימת עבודה מגובת-מאגר:

provisa env fetch --org acme --api "$PROVISA_API_URL" --token "$PROVISA_API_TOKEN"
provisa env deploy --org acme --env prod --ref "origin/main" \
  --message "release: $GIT_COMMIT_MSG" \
  --api "$PROVISA_API_URL" --token "$PROVISA_API_TOKEN"

ראו גם

  • פריסה — כיצד להקים את מישור הבקרה שאליו סביבות מתחברות
  • פקודות — פונקציות ו-webhooks נמעקבים המופיעים בעץ של כל סביבה
  • בניית סביבות בדיקה — פרופיילינג של סביבת הייצור, הצהרה על נתונים מזויפים, יצירת נתונים סינתטיים לסביבה שאינה סביבת ייצור
  • שיטות נתונים מזויפים — כל סוג של נתון מזויף וכל שיטה שעמודה יכולה להצהיר