Drupal‑ի CI-ով կառավարվող կոնֆիգուրացիայի կառավարում՝ Jenkins և GitLab CI օգտագործմամբ
1. Ինչու է CI-ով կառավարվող կոնֆիգուրացիայի կառավարումը կարևոր
Drupal-ի կոնֆիգուրացիայի համակարգը հարթակի ամենամեծ ուժեղ կողմերից մեկն է — և ամենահաճախ ցավ պատճառողներից մեկը։ Կայքի յուրաքանչյուր կոնֆիգուրացիայի մասի արտահանումն ու ներմուծումը YAML ֆայլերի տեսքով հզոր հնարավորություն է, բայց միայն այն դեպքում, երբ բոլորը համաձայն են, թե ով է պատասխանատու այդ ֆայլերը միջավայրերի միջև տեղափոխելու համար։ Թիմերի մեծ մասում այդ համաձայնությունը երբեք լիովին գոյություն չունի։
Դասական խնդիրները լավ հայտնի են յուրաքանչյուրին, ով թողարկել է Drupal կայք․
- Կոնֆիգուրացիայի շեղում (Config drift) — staging-ը շեղվում է production-ից, production-ը՝ local-ից, և ոչ ոք վստահ չէ, թե որ միջավայրն է հիմնականը։
- "Աշխատում է staging-ում, բայց ոչ production-ում" — որովհետև ինչ-որ մեկը staging-ում թարմացրել է view կամ field formatter և երբեք չի արտահանել այն։
- Ձեռքով
drush cim-ը կոտրում է բովանդակությունը — գիշերվա 11-ին կատարված շտապ ներմուծումը, որը ջնջել է content type-ի դաշտ, որը դեռևս օգտագործվում էր ակտիվ node-ների կողմից։
Այս բոլոր սցենարների հիմնական պատճառը նույնն է․ մարդն է որոշում՝ երբ և արդյոք կոնֆիգուրացիան պետք է տեղափոխվի։ Մարդիկ մոռանում են։ Սթրեսի տակ բաց են թողնում քայլեր։ Կայացնում են որոշումներ, որոնք հետո պարզվում է սխալ են։
CI-ն չի մոռանում։ Խողովակաշարը (pipeline) կամ անցնում է, կամ ձախողվում է։ Այն չունի standup-ի մասնակցելու անհրաժեշտություն։ Այն չգիտի, որ թողարկումը տեղի կունենա քսան րոպեից։ Այդ դետերմինիզմն է հենց այն, ինչ անհրաժեշտ է կոնֆիգուրացիայի կառավարմանը։
Այս հոդվածը խոստանում է ապահովել հետևյալը․
- Յուրաքանչյուր կոնֆիգուրացիայի փոփոխություն commit է արվում Git-ում՝ նախքան որևէ ընդհանուր միջավայր հասնելը։
- Խողովակաշարն է պատասխանատու կոնֆիգուրացիայի վավերացման և ներմուծման համար, ոչ թե ծրագրավորողը։
- Միջավայրերի միջև տեղափոխումը չի պահանջում ձեռքով քայլեր։
- Config drift-ը build-ի ձախողում է, ոչ թե Slack հաղորդագրություն։
2. Հիմնական սկզբունքներ՝ իրական նախագծերից ստացված
Կոնֆիգուրացիան՝ որպես կոդ
Եթե այն փոխում է կայքի վարքը, այն պետք է պահվի Git-ում։ Վերջակետ։ View, content type, performance setting, image style — այս ամենը կոդ է։ Կոնֆիգի ֆայլերին վերաբերվեք նույն կարգապահությամբ, ինչ PHP ֆայլերին․ վերանայեք դրանք, version-ավորեք, երբեք մի խմբագրեք անմիջապես ընդհանուր միջավայրում։
Ընդհանուր միջավայրերում ձեռքով drush cim — ոչ
Խողովակաշարն է ներմուծում կոնֆիգուրացիան, ոչ թե ծրագրավորողները։ Այս կանոնը ծայրահեղ է թվում, մինչև առաջին անգամ ինչ-որ մեկը գործարկի drush cim-ը production-ում՝ իր աշխատող թղթապանակում չcommit արված փոփոխություններով։
Խողովակաշարերը պետք է արագ ձախողվեն config drift-ի դեպքում
Կոնֆիգուրացիան ներմուծելուց և անմիջապես հետո այն արտահանելուց հետո չպետք է առաջանա որևէ diff։ Եթե առաջանում է, build-ը ձախողվում է։ Միայն այս կանոնը բռնում է ավելի շատ սխալներ, քան ցանկացած այլ ստուգում, որը մենք ավելացրել ենք։
core.extension.yml-ը չէր ներառվում արտահանումներում, որովհետև «մոդուլները միևնույն է կառավարվում են Composer-ով»։ Երեք ամիս անց hotfix-ը կրկին ակտիվացրեց մի մոդուլ, որը նպատակային անջատված էր production-ում։ Hotfix-ը ճիշտ էր — բայց հետագա config import-ը լուռ կրկին անջատեց մոդուլը։ Այդ միջադեպից հետո մենք core.extension.yml-ը համարում ենք ամենավտանգավոր ֆայլը, որը կարելի է անտեսել։3. Բարձր մակարդակի ճարտարապետություն
drush cex
config/sync
վավերացում + ներմուծում
Կոնֆիգուրացիան հոսում է միայն մեկ ուղղությամբ՝ ծրագրավորողի տեղական արտահանումից, Git-ի միջոցով, CI խողովակաշարով, և դեպի յուրաքանչյուր միջավայր։
Հիմնական գաղափարը պատասխանատվությունների բաժանումն է․
| Դերակատար | Պատասխանատվություն | Երբեք պատասխանատու չէ համար |
|---|---|---|
| Ծրագրավորող | Կոնֆիգի արտահանում, commit Git-ում, MR/PR-ի բացում | Կոնֆիգի ներմուծում որևէ ընդհանուր միջավայրում |
| CI խողովակաշար | Վավերացում, ներմուծում, ստուգում, տեղափոխում | Կոնֆիգի ֆայլերի ստեղծում կամ խմբագրում |
| Միջավայր | Կայքի գործարկում | Կոնֆիգի ստեղծում, պահպանում կամ արտահանում |
Միջավայրերը կոնֆիգուրացիայի սպառողներ են, երբեք արտադրողներ։ Այն պահից, երբ միջավայրը դառնում է կոնֆիգի ճշմարտության աղբյուր, շեղումն անխուսափելի է։
4. Պահոցի կառուցվածք, որը մասշտաբավորվում է
project-root/
├── composer.json
├── composer.lock
├── Jenkinsfile
├── .gitlab-ci.yml
│
├── ci/
│ ├── drupal-config-check.sh # Վերաօգտագործվող վավերացման սկրիպտ
│ ├── drupal-deploy.sh
│ └── drupal-install.sh
│
├── config/
│ ├── sync/ # Կոնֆիգը այստեղ է — commit արված Git-ում
│ │ ├── core.extension.yml
│ │ ├── system.site.yml
│ │ └── ...
│ └── splits/ # config_split override-ներ՝ ըստ միջավայրի
│ ├── development/
│ ├── staging/
│ └── production/
│
└── web/
├── sites/
│ └── default/
│ ├── settings.php # Commit արված, առանց գաղտնի տվյալների
│ ├── settings.local.php # Gitignore-ում, տեղական override-ներ
│ └── settings.env.php # Բեռնվում է CI-ի կողմից՝ env փոփոխականներից
└── ...Ինչ է տեղակայվում config/sync-ում
Բոլոր կոնֆիգուրացիայի YAML ֆայլերը, որոնք գեներացվում են drush cex-ի միջոցով։ Այս թղթապանակը կայքի կոնֆիգուրացիայի ճշմարտության միակ աղբյուրն է։ Այն commit է արվում, վերանայվում և տեղակայվում այնպես, ինչպես ցանկացած այլ կոդ։
Ինչը երբեք չպետք է ներառվի կոնֆիգում
- Միջավայրին հատուկ hostname-ներ, API key-եր կամ հավատարմագրեր — օգտագործեք միջավայրի փոփոխականներ և
settings.env.php։ - Ցանկացած տեսակի գաղտնի տվյալներ — ներարկեք ձեր CI գաղտնիքների պահոցից (Jenkins Credentials կամ GitLab CI Variables)։
- Բովանդակություն — մի օգտագործեք Default Content module-ը որպես լուծում այն բանի համար, ինչը պետք է լինի կոնֆիգ։
// settings.php — commit արված Git-ում, միջավայրից անկախ
$settings['config_sync_directory'] = DRUPAL_ROOT . '/../config/sync';
// Բեռնում է միջավայրին հատուկ արժեքները, որոնք ներարկվել են CI-ի կամ հոսթի կողմից։
if (file_exists($app_root . '/' . $site_path . '/settings.env.php')) {
include $app_root . '/' . $site_path . '/settings.env.php';
}
// Բեռնում է կամընտիր տեղական override-ները (gitignored)։
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
include $app_root . '/' . $site_path . '/settings.local.php';
}// Գեներացվում է CI-ի կողմից՝ միջավայրի փոփոխականներից — երբեք չի commit արվում։
$databases['default']['default'] = [
'driver' => 'mysql',
'host' => getenv('DB_HOST'),
'database' => getenv('DB_NAME'),
'username' => getenv('DB_USER'),
'password' => getenv('DB_PASS'),
'port' => getenv('DB_PORT') ?: 3306,
'prefix' => '',
];
$settings['hash_salt'] = getenv('DRUPAL_HASH_SALT');
// Տեղեկացնում ենք config_split-ին, թե որ միջավայրում ենք գտնվում։
$config['config_split.config_split.production']['status'] =
(getenv('APP_ENV') === 'production');5. Drupal-ի կոնֆիգուրացիայի աշխատանքային հոսք
5.1 Տեղական մշակում
Տեղական workflow-ը միակ վայրն է, որտեղ UI փոփոխությունների և կոնֆիգի արտահանման միջև հետադարձ կապը պետք է լինի արագ և սովորական։ Նախագծի յուրաքանչյուր ծրագրավորող հետևում է նույն կանոններին․
- Տեղական մակարդակում կատարեք UI կամ կոդի փոփոխություններ։
- Անմիջապես գործարկեք
drush cex— ոչ թե օրվա վերջում։ - Վերանայեք տարբերությունները
git diff config/sync-ով։ - Կամ commit արեք փոփոխությունները, կամ մերժեք դրանք՝ օգտագործելով
git checkout -- config/sync։ - Միջանկյալ վիճակ չի կարող գոյություն ունենալ։
# Drupal UI-ի միջոցով կամ install hook-երով կոնֆիգի փոփոխություն կատարելուց հետո՝
drush cex --yes
# Վերանայեք փոփոխությունները — վերաբերվեք դրան ինչպես ցանկացած կոդի փոփոխության․
git diff config/sync
# Stage արեք և commit՝ feature կոդի հետ միասին․
git add config/sync
git commit -m "feat(search): add fulltext search API index config"
# Կամ մերժեք, եթե փոփոխությունը փորձարարական էր և դեռ պատրաստ չէ․
git checkout -- config/syncՄենք դա պարտադրում ենք թեթև Git pre-commit hook-ով, որը զգուշացնում է (բայց չի արգելափակում), երբ PHP կամ template ֆայլերը stage են արված առանց համապատասխան փոփոխության config/sync-ում․
#!/bin/bash
# Զգուշացրեք, եթե module/theme կոդը փոփոխվել է, բայց config/sync-ը՝ ոչ։
CHANGED_CODE=$(git diff --cached --name-only | grep -E '\.(php|module|theme|install)$')
CHANGED_CONFIG=$(git diff --cached --name-only | grep '^config/sync')
if [[ -n "$CHANGED_CODE" ]] && [[ -z "$CHANGED_CONFIG" ]]; then
echo "⚠ Զգուշացում․ PHP/module ֆայլերը stage են արված, բայց config/sync փոփոխություններ չկան։"
echo " Գուցե մոռացել եք գործարկել՝ drush cex ?"
echo " Ամեն դեպքում շարունակվում է — բայց կրկնակի ստուգեք։"
fi
exit 05.2 Feature Branch-եր
Կոնֆիգուրացիան պահվում է նույն branch-ում և նույն pull/merge request-ում այն կոդի հետ, որը պահանջում է այն։ Նոր content type ավելացնող feature-ը պետք է ներառի և՛ PHP install hook-ը (եթե կա), և՛ այդ content type-ի YAML ֆայլերը նույն commit-ում։
6. CI-ի պատասխանատվությունները՝ ինչ պետք է վերահսկի խողովակաշարը
Յուրաքանչյուր խողովակաշար, որը շփվում է ընդհանուր Drupal միջավայրի հետ, պետք է հաջորդականորեն կատարի հետևյալ քայլերը․
- Տեղադրել կամ վերականգնել տվյալների բազան — մաքուր տեղադրում կամ production-ի սանիտարացված snapshot։
- Գործարկել տվյալների բազայի թարմացումները —
drush updb։ - Ներմուծել կոնֆիգուրացիան —
drush cim --yes։ - Վերաարտահանել կոնֆիգուրացիան —
drush cex --yes։ - Հաստատել, որ diff չկա — եթե որևէ YAML ֆայլ փոխվել է, build-ը պետք է ձախողվի։
4-րդ և 5-րդ քայլերը միասին ամենակարևորներն են։ Ներմուծումը և անմիջապես վերաարտահանումը պետք է հանգեցնեն դատարկ diff-ի։ Եթե դա այդպես չէ, ապա հետևյալներից մեկը ճիշտ է․
- Module-ը ներմուծման ընթացքում գեներացնում է կոնֆիգ (հաճախ module-ում առկա bug)։
- Կոնֆիգ entity-ի UUID-ը չի համապատասխանում տվյալների բազայում եղածին։
- Կոնֆիգի schema-ն ամբողջական չէ, որի պատճառով Drupal-ը նորմալացնում է արժեքները այլ կերպ, քան արտահանման ժամանակ։
- Ծրագրավորողը ձեռքով խմբագրել է կոնֆիգի ֆայլերը և առաջացրել անհամապատասխանություններ։
#!/bin/bash
set -euo pipefail
echo "=== Գործարկվում են Drupal տվյալների բազայի թարմացումները ==="
drush updb --yes
echo "=== Կոնֆիգուրացիայի ներմուծում config/sync-ից ==="
drush cim --yes
echo "=== Վերաարտահանում՝ սպասվող փոփոխությունների բացակայությունը ստուգելու համար ==="
drush cex --yes
echo "=== Config drift-ի ստուգում ==="
if ! git diff --exit-code config/sync; then
echo ""
echo "❌ ՍԽԱԼ։ Հայտնաբերվել է կոնֆիգուրացիայի շեղում!"
echo " Git-ում գտնվող կոնֆիգը չի համապատասխանում Drupal-ի կողմից import+export-ից հետո ստեղծվածին։"
echo " Տարբերությունները վերևում են։ Տեղականում ուղղեք 'drush cex'-ով և commit արեք։"
exit 1
fi
echo "✅ Կոնֆիգուրացիան մաքուր է — շեղում չի հայտնաբերվել։"7. Jenkins-ի իրականացում (փորձարկված մարտական պայմաններում)
7.1 Jenkinsfile կառուցվածք
Մենք օգտագործում ենք բացառապես դեկլարատիվ pipeline-ներ։ Scripted pipeline-ները առաջարկում են ավելի մեծ ճկունություն, բայց դեկլարատիվ pipeline-ները ավելի հեշտ են ընթեռնելի, ավելի հեշտ են lint-վում jenkins-cli declarative-linter-ով և ավելի հասկանալի են թիմի նոր անդամների համար։
pipeline {
agent { label 'drupal-php82' }
options {
buildDiscarder(logRotator(numToKeepStr: '20'))
timeout(time: 30, unit: 'MINUTES')
disableConcurrentBuilds()
}
environment {
DRUPAL_ROOT = "${WORKSPACE}/web"
COMPOSER_HOME = "${WORKSPACE}/.composer"
APP_ENV = 'ci'
DB_CREDS = credentials('drupal-ci-db') // Jenkins secret
}
stages {
stage('Checkout') {
steps {
checkout scm
sh 'git log --oneline -5'
}
}
stage('Composer Install') {
steps {
sh '''
composer install \
--no-interaction \
--prefer-dist \
--optimize-autoloader
'''
}
}
stage('Write Settings') {
steps {
// Generate settings.env.php from Jenkins credentials/env vars
sh '''
cat > web/sites/default/settings.env.php < 'mysql',
'host' => '127.0.0.1',
'database' => 'drupal_ci',
'username' => '${DB_CREDS_USR}',
'password' => '${DB_CREDS_PSW}',
'port' => 3306,
'prefix' => '',
];
\\$settings['hash_salt'] = '${DRUPAL_HASH_SALT}';
EOF
'''
}
}
stage('Site Install') {
steps {
sh '''
drush site-install minimal \
--yes \
--existing-config \
--account-name=admin \
--account-pass="${DRUPAL_ADMIN_PASS}"
'''
}
}
stage('Validate Config') {
steps {
sh 'bash ci/drupal-config-check.sh'
}
post {
failure {
sh 'git diff config/sync || true'
archiveArtifacts artifacts: 'config/sync/**/*.yml', allowEmptyArchive: true
}
}
}
stage('Deploy') {
when {
anyOf {
branch 'main'
branch 'release/*'
}
}
steps {
sh 'bash ci/drupal-deploy.sh'
}
}
}
post {
always {
sh 'drush cr || true'
cleanWs()
}
failure {
emailext(
subject: "[FAIL] ${JOB_NAME} #${BUILD_NUMBER}",
body: "Config validation failed. See: ${BUILD_URL}",
recipientProviders: [[$class: 'DevelopersRecipientProvider']]
)
}
}
}7.2 Jenkins-ին հատուկ նկատառումներ
Shared Libraries
Երբ կառավարում եք ավելի քան երկու կամ երեք Drupal կայք, Drupal pipeline-ի տրամաբանությունը տեղափոխեք Jenkins Shared Library-ի մեջ։ Յուրաքանչյուր նախագծի Jenkinsfile-ը դառնում է թեթև wrapper։
@Library('drupal-pipeline-lib@v2') _
drupalPipeline(
phpVersion: '8.2',
deployBranch: 'main',
dbCredentials: 'drupal-ci-db',
slackChannel: '#deployments'
)Workspace-ի մաքրում
Միշտ կանչեք cleanWs() ֆունկցիան post { always } բլոկում։ Jenkins agent-ները կուտակում են նախորդ build-երի վիճակը — նախորդ build-ի settings.env.php-ը կամ vendor թղթապանակը կարող են աննկատ ազդել ընթացիկ build-ի վրա։ Եղեք խիստ՝ մաքրեք workspace-ը։
8. GitLab CI-ի իրականացում
8.1 .gitlab-ci.yml կառուցվածք
# (CI կոնֆիգը անփոփոխ է թարգմանվում միայն մեկնաբանություններով)
# ── build stage
# ── test stage
# ── validate-config stage
# ── deploy stage8.2 GitLab CI-ի առավելությունները
GitLab CI-ն ունի մի շարք հնարավորություններ, որոնք այն դարձնում են հատկապես հարմար այս workflow-ի համար․
- Առաջին կարգի artifact-ներ — ձախողված կոնֆիգի արտահանումները ավտոմատ պահպանվում են և հասանելի են MR UI-ում առանց լրացուցիչ կոնֆիգուրացիայի։
- Բնական caching՝ հիմնված
composer.lock-ի վրա — առաջին գործարկումից հետո Composer install-ը դառնում է արագ։ - Merge Request pipeline-ի տեսանելիություն — ծրագրավորողները տեսնում են կոնֆիգի վավերացման կարգավիճակը անմիջապես MR-ում մինչև merge-ը։
- Services բլոկ — MySQL-ը գործարկվում է որպես sidecar՝ առանց ենթակառուցվածքային լրացուցիչ բարդության։
- Environments + manual gates — production deploy-ի վրա դրված
when: manual-ը ապահովում է մեկ սեղմումով տեղափոխում՝ մարդկային հաստատմամբ։
#!/bin/bash
set -euo pipefail
TARGET_ENV="${1:-staging}"
echo "=== Տեղակայում դեպի: ${TARGET_ENV} ==="
rsync -az --delete \
--exclude='.git' \
--exclude='web/sites/default/files' \
--exclude='web/sites/default/settings.env.php' \
./ "deploy@${TARGET_ENV}.example.com:/var/www/drupal/"
echo "=== Post-deploy հրամանների գործարկում ${TARGET_ENV}-ում ==="
ssh "deploy@${TARGET_ENV}.example.com" bash -s <<'REMOTE'
set -e
cd /var/www/drupal
drush updb --yes
drush cim --yes
drush cex --yes
git diff --exit-code config/sync || (echo "❌ Config drift թիրախում!"; exit 1)
drush cr
echo "✅ Տեղակայումն ավարտված է։"
REMOTE9. Միջավայրին հատուկ կոնֆիգուրացիա՝ առանց խաբելու
Ոչ բոլոր կոնֆիգուրացիոն արժեքները պետք է նույնը լինեն բոլոր միջավայրերում։ Search backend-ները, logging-ի մակարդակը, caching շերտերը և երրորդ կողմի API endpoint-ները լիովին կարող են տարբեր լինել։ Հարցն այն է, թե ինչպես կառավարել այդ տարբերությունները՝ առանց config pipeline-ի ամբողջականությունը խախտելու։
Ճիշտ գործիքներ՝ config_split և config_ignore
config_split-ը թույլ է տալիս սահմանել կոնֆիգուրացիայի հավաքածուներ, որոնք ակտիվ են միայն որոշակի միջավայրերում։
Իրական split օրինակներ
| Կոնֆիգի տարր | Dev split | Stage split | Prod split |
|---|---|---|---|
| Search API backend | Տվյալների բազա | Solr (փոքր) | Solr (արտադրական կլաստեր) |
| Error logging | dblog, մանրամասն | syslog | syslog + արտաքին APM |
| Performance modules | Անջատված | Միացված | Միացված + CDN կոնֆիգ |
| Mail transport | Mailhog / null mailer | Mailpit | SMTP / SendGrid |
Սխալ մոտեցումներ — մի արեք սա․
- Կոնֆիգուրացիայի ուղղակի խմբագրում production տվյալների բազայում։
settings.php-ում օգտագործելif ($settings['environment'] === 'prod')պայմանականներ՝ config արժեքները փոխելու համար։- Յուրաքանչյուր միջավայրի համար առանձին Git branch-երի պահպանում տարբեր config ֆայլերով։
10. Տեղափոխում միջավայրերի միջև
Promotion-ը deployment չէ։ Deployment-ը տեղափոխում է կոդը և կոնֆիգը միջավայր։ Promotion-ը տեղափոխում է վավերացված artifact — ինչ-որ բան, որն արդեն անցել է CI-ը — շղթայի հաջորդ միջավայր։
Գործնականում սա նշանակում է, որ նույն Git SHA-ն, որը վավերացվել է dev-ում, հասնում է production։ Վերջին պահին commit-ներ չկան։ CI-ը շրջանցող hotfix-ներ չկան։ Config ստուգումը շրջանցող cherry-pick-եր չկան։
feature branch / main-ում
auto-deploy merge-ից հետո
auto-deploy develop-ից
manual gate main-ում
Նույն վավերացված artifact-ը անցնում է միջավայրերով։ CI-ը գործարկվում է մեկ անգամ, արդյունքը՝ տարածվում։
Immutable build-երի փիլիսոփայությունը նշանակում է՝ այն, ինչ CI-ը վավերացրել է, հենց դա էլ տեղակայվում է։ Եթե իսկապես անհրաժեշտ է hotfix, այն անցնում է արագացված branch-ով՝ իր սեփական CI run-ով — այն չի շրջանցում վավերացումը։
main branch-ը պարտադիր pipeline status check-ով։ GitLab-ի "protected branches"-ը և Jenkins-ի "GitHub Branch Source" plugin-ը աջակցում են դրան։ Եթե pipeline-ը չի անցել, branch-ը չի կարող տեղակայվել production-ում։11. Սահմանի դեպքերի կառավարում (դուք բախվելու եք դրանց)
UUID անհամապատասխանություններ
Config entity-ները կրում են UUID-ներ։ Եթե տեղադրեք նոր կայք և փորձեք ներմուծել config այլ տեղադրումից, Drupal-ը կհրաժարվի UUID անհամապատասխանության սխալով։ Լուծումն է միշտ տեղադրել --existing-config-ով կամ տեղադրումից հետո սահմանել site UUID-ը։
# Կարդացեք UUID-ը commit արված config-ից և կիրառեք այն նոր տեղադրմանը՝
SITE_UUID=$(grep "^uuid:" config/sync/system.site.yml | awk '{print $2}')
drush config-set "system.site" uuid "$SITE_UUID" --yes
drush cim --yesModule enable/disable հերթականություն
Config-ի միջոցով նոր module միացնելիս, Drupal-ը ավտոմատ պահպանում է dependency-ի հերթականությունը drush cim-ի ընթացքում։ Սակայն, եթե module-ի install hook-ը գեներացնում է default config, որը հակասում է config/sync-ում եղածին, կարող է անհրաժեշտ լինել ջնջել այդ default config-ը և կրկին ներմուծել։ Pipeline-ը սա կբռնի որպես drift։
Բովանդակությունից կախված կոնֆիգուրացիա
Որոշ կոնֆիգներ հղում են կատարում բովանդակությանը — օրինակ՝ block, որը հղվում է menu item-ին ըստ ID-ի, կամ view, որը ֆիլտրում է taxonomy term-ով։ Այս հղումները կարող են տարբեր լինել միջավայրերի միջև, եթե բովանդակությունը տարբեր կերպ է ստեղծվել։ Լուծումն է կառավարել այդ բովանդակությունը migration-ների կամ default content module-ների միջոցով, ոչ թե կոնֆիգով։
Multisite առանձնահատկություններ
Multisite միջավայրում յուրաքանչյուր կայք ունի իր config sync թղթապանակը։ CI pipeline-ը պետք է գործարկի config ստուգում յուրաքանչյուր կայքի համար, ոչ միայն հիմնականի։ Օգտագործեք loop։
#!/bin/bash
set -euo pipefail
for SITE_DIR in web/sites/*/; do
SITE=$(basename "$SITE_DIR")
[[ "$SITE" == "default" ]] && continue
[[ "$SITE" == "simpletest" ]] && continue
echo "--- Կոնֆիգի ստուգում կայքի համար: $SITE ---"
drush --uri="${SITE}" updb --yes
drush --uri="${SITE}" cim --yes
drush --uri="${SITE}" cex --yes
CONFIG_DIR="config/${SITE}/sync"
if ! git diff --exit-code "${CONFIG_DIR}"; then
echo "❌ Config drift կայքում: $SITE"
exit 1
fi
done
echo "✅ Բոլոր կայքերը մաքուր են։"Drupal Core-ի թարմացում կոնֆիգի փոփոխություններով
Core-ի թարմացումները երբեմն ներառում են schema-ի փոփոխություններ, որոնք ազդում են առկա config-ի վրա։ Միշտ գործարկեք drush updb նախքան drush cim-ը և հետո՝ drush cex՝ schema-ի նորմալացված փոփոխությունները գրանցելու համար։ Commit արեք այդ փոփոխությունները core upgrade branch-ում։
12. Օպերացիոն անվտանգության ցանցեր
Read-Only Config Production-ում
Քննարկեք production-ում Config Readonly module-ի միացումը։ Այն արգելում է ցանկացած կոնֆիգի փոփոխություն admin UI-ի միջոցով — կոշտ արգելք, որը ամրապնդում է "ձեռքով փոփոխություններ՝ ոչ" կանոնը հավելվածի մակարդակում։
if (getenv('APP_ENV') === 'production') {
$settings['config_readonly'] = TRUE;
}Post-Deploy ստուգում
# Ստուգեք, որ deploy-ից հետո չկան սպասվող config փոփոխություններ՝
drush config-status 2>&1 | grep -v 'No differences' && { \
echo "❌ Անսպասելի config տարբերություններ deploy-ից հետո"; exit 1; \
} || echo "✅ Config կարգավիճակը մաքուր է"
drush cr
drush php-eval "echo \Drupal::state()->get('system.cron_last');"Rollback ռազմավարություն
Rollback-ը Git գործողություն է, ոչ թե տվյալների բազայի գործողություն։ Եթե deployment-ը խնդիր է առաջացնում՝
- Նշեք վերջին լավ commit SHA-ն։
- Գործարկեք pipeline-ը այդ SHA-ի վրա։
- Pipeline-ը կրկին տեղակայում է նախկինում վավերացված artifact-ը։
Կոնֆիգի ներմուծումը հետ շրջելու համար տվյալների բազայի ձեռքով փոփոխումը երբեք ճիշտ լուծում չէ։
Աուդիտ․ Ո՞վ փոխեց կոնֆիգը, ե՞րբ և ինչո՞ւ
Քանի որ յուրաքանչյուր config փոփոխություն անցնում է Git-ով, ձեր audit trail-ը Git պատմությունն է։ Օգտագործեք իմաստալից commit հաղորդագրություններ և ապահովեք դրանք commit-msg hook-ով կամ CI lint քայլով։
13. Սովորական սխալներ, որոնք այլևս չենք անում
| Սխալ | Ինչու է վնասակար | Լուծում |
|---|---|---|
Ձեռքով drush cim գործարկել staging կամ prod-ում | Ներմուծվում է անհայտ վիճակ | Միայն pipeline-ը ներմուծում է config-ը |
| UI փոփոխությունների թույլատրում staging-ում | Staging-ը դառնում է ճշմարտության աղբյուր | Միացնել config_readonly |
| Ծրագրավորողներին "հիշելու" վրա վստահելը | Սթրեսի տակ նրանք չեն հիշի | Pre-commit զգուշացում, CI ձախողում |
| Config drift-ի անտեսում | Կուտակվում է լուռ շեղում | drush cim → cex → git diff --exit-code պարտադիր է |
| Առանձին branch-եր միջավայրերի համար | Միավորման մղձավանջ | Մեկ config branch՝ config_split-ով |
drush updb-ի բացթողում մինչև drush cim | Schema թարմացումները կարող են առաջացնել սխալներ | Միշտ՝ updb → cim → cex → diff |
14. Արդյունքներ այս մոտեցման կիրառումից հետո
Այս մոտեցումը տարբեր Drupal կայքերում կիրառելուց հետո արդյունքները հետևողական էին։
drush cim production-ում 18 ամսումՄշակութային փոփոխությունն առավել կարևոր էր։ Config քննարկումները տեղափոխվում են Slack-ից դեպի Git պատմություն։
15. Վերջնական առաջարկություններ
- Սկսեք խիստ կանոններով, թուլացրեք միայն պատճառներով։
- Յուրաքանչյուր config diff դիտարկեք որպես build ձախողում։
- CI-ը deployment-ի ճշմարտության աղբյուրն է։
updb → cim → cex → diffհաջորդականությունը խախտելի չէ։- Օգտագործեք
config_splitիրական միջավայրային տարբերությունների համար։ - Միացրեք config_readonly-ը բոլոր shared միջավայրերում։
- Արխիվացրեք ձախողված config export-երը որպես CI artifact-ներ։
- Rollback-ը կատարեք Git-ի միջոցով, ոչ տվյալների բազայով։
Jenkins-ը և GitLab CI-ը հավասարապես ունակ են ապահովելու այս կարգապահությունը։
Նպատակը երբեք կոնֆիգի կառավարումը բարդացնելը չէ։ Նպատակն այն ձանձրալի դարձնելն է՝ գործընթաց, որը միշտ աշխատում է։
Ivan Abramenko, Principal Drupal Architect
ivan.abramenko@drupalbook.org
projects@drupalbook.orgprojects@drupalbook.org