GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing wikitech.wikimedia.org — How to deploy code - Wikitech This article is mainly about deployment of changes to MediaWiki code to the Wikimedia cluster. Introduction
See also
Basic tips
Deployment requirementsAccess/rights needed to deploy
Other Prerequisites
Step 1: get the code in the deployment branchBefore you can deploy anything, it has to be in the deployment branch(es). Our deployment branches are named wmf/1.MAJOR-wmf.MINOR (e.g. wmf/1.27.0-wmf.7) where Note that in most cases the cluster will be running on two deployment branches, with some wikis running version N and some running version N+1. To see which wiki is running which version, consult the versions tool, inspect If your code or change needs to go live to all wikis, you will need to change all deployment branches that are in use. An easy way to see all of the versions currently in use is to log onto the deployment host and run scap wikiversions-inuse from the command line. You can also run scap wikiversions-inuse --withdb to see a wiki that is running each version. NOTE: All examples on this page assume there is a single deployment branch called wmf/1.27.0-wmf.1 checked out on the cluster in NOTE: Also, all git examples assume you have a clean working copy, that is, you have no uncommitted changes. To verify this, run Case 1a: core changesYou are deploying changes to MediaWiki core. This should be rare because core is updated from master every week, but in some cases it might be necessary. For core changes, you will simply need to push or submit changes to the wmf/1.27.0-wmf.1 branch in core. The most common use case is to take a commit that is already in the repository somewhere (usually in master, sometimes a commit that's still pending review) and cherry-pick it into the deployment branch, so only that case is documented below. To cherry-pick a commit into the deployment branch, do the following things locally: $ cd mediawiki/core # go to your checkout of mediawiki/core.git # Set up a local wmf/1.27.0-wmf.1 branch that tracks the remote # You only need to do this once for each branch; if you've already got a wmf/1.27.0-wmf.1 branch, you can skip this step # If you get an error, try 'git remote update' or 'git fetch' first $ git branch --track wmf/1.27.0-wmf.1 origin/wmf/1.27.0-wmf.1 Branch wmf/1.27.0-wmf.1 set up to track remote branch wmf/1.27.0-wmf.1 from origin. # Switch to the wmf/1.27.0-wmf.1 branch and update it from the remote $ git checkout wmf/1.27.0-wmf.1 $ git pull $ git submodule update --init --recursive # Cherry-pick a commit from master, identified by its patch set hash $ git cherry-pick ffb1b38ad83927606c539ac941e9f3eb2653a840 # If there are conflicts, this is how you fix them: # - run 'git status' to see which files are conflicted # - start fixing conflicted files using your favorite editor # - use 'git add filename' to tell git you've fixed the conflicts in a file # - once all conflicts are resolved, commit the result using 'git commit' # Submit your cherry-pick commit for review $ git review # If you don't want or need this to be reviewed, you can +2 your own # commit if you are in the wmf-deployment group Commit message for cherry picksIf a cherry-pick does not result in a merge conflict, then the commit message is automatically amended to reference the original patch. A line will be added in the commit message, after the Change-Id line, with the following content only: If a cherry-pick does result in a merge conflict, then you will have to resolve the conflict using git commands (typically, by editing the conflicting file(s), followed by Case 1b: extension/skin/vendor changesYou are deploying changes to an extension, but you don't just want to deploy master. Instead, you want to deploy the code that is currently deployed, plus your change. (If you do actually want to deploy master, see How to deploy current master branch of an extension.) Starting with 1.27.0-wmf.1, all deployed extensions have automatically-created Updating the deployment branchJust like in core, the most common use case for updating a deployment branch is to cherry-pick changes from master. You can do this using the Cherry Pick To button in Gerrit, or from the command line as follows: $ cd mediawiki/extensions/MyCoolExtension # go to your extension checkout # Set up a local wmf/1.27.0-wmf.1 branch that tracks the remote # You only need to do this once for each branch; if you've already got a wmf/1.27.0-wmf.1 branch, you can skip this step # If you get an error, try 'git remote update' or 'git fetch' first $ git branch --track wmf/1.27.0-wmf.1 origin/wmf/1.27.0-wmf.1 Branch wmf/1.27.0-wmf.1 set up to track remote branch wmf/1.27.0-wmf.1 from origin. # Switch to the wmf/1.27.0-wmf.1 branch and update it from the remote $ git checkout wmf/1.27.0-wmf.1 $ git pull # Cherry-pick a commit from master, identified by its patch set hash $ git cherry-pick 176ffdd3b71e463d3ebaa881a6e77b82acba635d # If there are conflicts, this is how you fix them: # run 'git status' to see which files are conflicted # start fixing conflicted files # use 'git add filename' to tell git you've fixed the conflicts in a file # once all conflicts are resolved, commit the result using 'git commit' # Submit your commit for review # Note: 'wmf/1.27.0-wmf.1' is the name of the remote branch you are pushing to, not the name of your local tracking # branch (although in this example they are the same). $ git review wmf/1.27.0-wmf.1 # If you don't want or need this to be reviewed, you can +2 your own # commit if you are in the wmf-deployment group and will be deploying this immediately You can repeat this process multiple times to commit or cherry-pick multiple changes. After you have submitted the updates to gerrit, you can either have them deployed in a Backport windows by adding the updates to the deployment schedule or deploy them yourself by following the other steps below. Updating the submoduleThis is only necessary for the edits to VisualEditor/VisualEditor. When you update VisualEditor, you'll need to update to use the latest version of the submodule. In that case, see /Core submodule update. Case 1c: new submodule (extension, skin, etc.)
You are adding an entirely new extension that wasn't deployed before, and you're deploying from master (if you need to deploy something other than the master state, that's possible, but it generally shouldn't be done for an initial deployment; master should just be clean and deployable). The easiest way to do this is to update Beta featureIf your extension creates a new beta feature, please refer to this checklist before deploying it. Step 2: configuration and other prep workIn certain cases, you'll have to change how Wikimedia sites are configured. We generally have the same codebase everywhere, but with different configurations for each wiki. Maybe you are just changing one configuration variable. Or, perhaps you are adding a brand-new extension, or activating an extension on some wiki where it's never been before. For all of these cases, and more, you'll have to make the changes to the config files to get the desired results. Configuration files live in their own revision-controlled repository operations/mediawiki-config. The big difference is the configuration files are not tied to releases — there is no 1.27.0-wmf.1 branch for configuration. This means you cannot commit a configuration change and have it "roll out" across wikis on the release train, it has to work with all branches in use. In general if you're not in operations you should make changes to a local copy of this repository (as explained in How to do a configuration change#In your own repo via gerrit), submit them for gerrit review with a -1 comment to avoid early deployment, then during your deployment window (often during backport windows) +2 them and get them on the deployment host. Everything that follows is just a convenient way to make config changes. If you're deploying an extension or feature that can be switched off, it's usually best to leave it switched off while you deploy and carefully switch it on after that using a simple configuration change (this is called a dark launch). Even if you do this, you should build any configuration infrastructure (e.g. For specific preparations, see the sections below as well as Creating new tables, How to do a schema change, and How to do a configuration change. Best to perform schema changes before making config changes. Add a configuration switch for an extensionIn if ( $wmgEnableMyExtension ) { require_once( "$IP/extensions/MyExtension/MyExtension.php" ); // Set config vars if needed // If you want to export config vars through InitialiseSettings.php, you need to set $wmgMyExtensionThingy there and do #$wgMyExtensionThingy = $wmgMyExtensionThingy; } In 'wmgEnableMyExtension' => array( 'default' => false, 'eswikibooks' => true, // etc. ), // If needed, set $wmgMyExtensionWhatever vars here too If your extension requires a large-ish amount of configuration, consider putting it in a separate file instead. Currently, AbuseFilter, LiquidThreads and FlaggedRevs do this. For more documentation on these files and their formats, see Configuration files. Add new extension to extension-list and release toolsBefore enabling a new extension, you need to make sure the extension code is present on the servers, i.e. it is a submodule in the current and previous deployment branch. Normally you can do this by adding the extension to the When adding a new extension, you need to add it to the Disabling an extensionConversely, when you disable an extension, remove it from Reedy commented:
When you disable a default extension, make sure it's gone from addWiki.php so that it doesn't cause issues next time someone creates a database. Step 3: synchronize the changes to the clusterMost changes are deployed using IMPORTANT: You'll need to start you@deployment-host:~$ tmux new -s "deployment" After starting a tmux session, you can start you@deployment-host:~$ scap backport '<gerrit-id-of-change>' For example, to sync the change you@deployment-host:~$ scap backport 1071890 You can sync multiple changes: you@deployment-host:~$ scap backport 1071890 1071891 1071892 # Syncs 3 changes This command:
Expand for specific instructions for
scap sync-file and scap sync-world🔽Small changes: sync individual files or directoriesIf you have a good reason to sync a single file or directory, you can use PITFALL: First, you'll need to #Manually_stage_changes then pull to mwdebug to test.
To sync a single file or a directory, run
When running you@deployment-host:/srv/mediawiki-staging$ scap sync-file php-1.27.0-wmf.1/api.php 'API security fix' No syntax errors detected in /srv/mediawiki-staging/php-1.27.0-wmf.1/api.php copying to apaches mw60: ssh: connect to host mw60 port 22: Connection timed out srv189: ssh: connect to host srv189 port 22: Connection timed out srv174: ssh: connect to host srv174 port 22: Connection timed out srv266: ssh: connect to host srv266 port 22: Connection timed out More complex changes: sync everythingIf you're adding directories, changing many files, changing i18n messages, or otherwise have a reason why you@deployment-host:/srv/mediawiki-staging$ scap sync-world 'Log message here' Checking syntax... Copying to deployment-host...Done. Updating serialized data files... Warning: messages are no longer serialized by this makefile. Updating ExtensionMessages-1.26.php... Updating ExtensionMessages-1.27.0-wmf.1.php... Updating LocalisationCache for 1.26... Updating LocalisationCache for 1.27.0-wmf.1... ...snip... Running Add / remove a dblist
Changing files in /staticThese may have to be purged from the CDN. See also Backport windows/Deployers#Purging. Manually stage changesThis is only necessary when using $ ssh deployment.eqiad.wmnet Once the code is merged in the deployment branch in Gerrit, we pull it down on the deployment host. Avoid plain deployment-host:~$ cd /srv/mediawiki-staging/php-X # Make sure there are no uncommitted changes. Submodule changes are OK (they usually mean security patches) deployment-host:/srv/mediawiki-staging/php-X/$ git status # Fetch remote git commits without updating working directory yet deployment-host:/srv/mediawiki-staging/php-X/$ git fetch # View local log deployment-host:/srv/mediawiki-staging/php-X/$ git log -n25 --oneline --decorate --graph # View remote log deployment-host:/srv/mediawiki-staging/php-X/$ git log HEAD..origin/wmf/X View the local log to ensure there are no local patches that shouldn't be there (e.g. security patches). You may want to alias that command to something convenient like The remote log shows the commits that would be added to the working copy when we rebase the local branch (e.g. "git pull"). If there are other changes besides yours, go yell at the culprit. Otherwise you're OK to pull your changes into the deployment directory. You must always rebase in case there are security patches locally committed on the deployment host. /srv/mediawiki-staging/php-X/$ git rebase origin/wmf/X If you are deploying a change for an extension, you can now simply update the extension submodule with: deployment-host:/srv/mediawiki-staging/php-1.27.0-wmf.1/$ git submodule update --init --recursive extensions/MyCoolExtension you should see the commit ID from your work in your local deployment Pre-deployment testing in productionThis is only necessary when using Part of the deployment process (for e.g. backports) is to first deploy changes to an mwdebug host. HTTP requests for any production site can be routed to this server. See WikimediaDebug#Staging changes for how to deploy and test changes there. Test and monitor your live codeIs it doing what you expected? Unfortunately, testwiki is not like a real wiki: extensions respond to a trigger hooks, CentralNotice or Common.js might effect the browser environment, etc. No one environment can simulate all the wikis that we operate, so test your change afterwards on a live wiki to confirm. test2.wikipedia.org is a test wiki that operates as a member of the cluster. Keep in mind also that different projects are configured differently, have different extensions enabled, use different alphabets, etc; it can be worthwhile to double check your changes on multiple projects, particularly to ensure that character encoding and right-to-left formatting is behaving as expected. Also remember that the caching infrastructure on the cluster is likely different than your local or testing environments; keep the different production caching layers/strategies in mind as you're assessing your changes in production. We use open-source tools such as Grafana, Prometheus, and Icinga to monitor our production cluster; you should review their output post-deploy for unexpected spikes. Use Logstash to query, aggregate and visualise runtime exceptions: All PHP error logs are routed to the current mwlog server in /a/mw-log. Exceptions and fatals happen constantly, so you need to get a sense of changes over time. For example, to see trends in "Maximum execution time exceeded" errors this month, you might run mwlog1002$ cd /srv/mw-log/archive mwlog1002$ zgrep -c 'Maximum execution time' fatal.log-201304* You can also run the logspam-watch script from the log server to watch for spikes in errors or warnings. For a summary of all of the logs in use, see Logs. Don't leave townEven if your deploy appears to be working, it's important to be reachable in the hours immediately following your deploy. Ideally, stay online and in IRC channels like #wikimedia-tech and #wikimedia-operations for a couple of hours. Update Deployments with what happened in your deployment window. If you must go offline, let people know how to reach you (and keep your mobile phone or other communications device on your person). You can use /away messages on IRC, or perhaps send a short email to the ops list. If you are on Wikimedia staff, now might be a great time to check if your contact info is up to date. If you aren't on staff, ask a staffer to add your contact info to that page, under "Important volunteers". A note on JavaScript and CSSSince we have ResourceLoader, there is no need to e.g manually do a "build" (to re-minify/re-cache static files). ResourceLoader does this automatically on-demand. Depending on when the timestamp cache gets a cache-miss, it can take up to five minutes for that to occur. ResourceLoader and l10n messagesIn the case of a localization update that affects JavaScript and is loaded via the ResourceLoader the live string may remain unchanged after running scap.
Security patchesThe last step in fixing security issues in MediaWiki before releasing the fixes publicly via a security release, is deploying the patches to the Wikimedia production cluster. This involves uploading the security patches to Please do not discuss the patches publicly (including on IRC or within public Phabricator tasks). In most cases the commit message and knowing the files the commit affected would be enough for a malicious person to figure out the vulnerability. When there are security patches in deployment, please rebase them on top of any changes you are deploying. This makes it easier to see what's been deployed (no more "Merge branch...." commits), and makes the fact that security patches are live immediately clear. The only times that these should interfere with your deployment is if the changes conflict. In this case, please contact someone from the Security Team or Release Engineering to work out the best way to handle the situation. Creating a Security PatchThis process applies to code irrespective of its canonical repository, be it Gerrit, GitHub or GitLab. Please contact [email protected] for further advice.
Before
Guidelines for creating patchesAs security changes initially bypass CI, they should be written and reviewed especially carefully. Run any relevant tests (including new ones you add) locally, and preferably also run PHPCS against all modified files – otherwise, the patch will take longer to get merged once it is published on Gerrit. Try to keep security patches small: they will have to be applied many times – rebased onto the master branch every week until the next security release, and then backported to supported release branches on Gerrit. Avoid refactoring affected files beyond what’s currently necessary; if it keeps the patch smaller, it may be worth temporarily skipping best practices such as Dependency Injection. (Such things can always be cleaned up after the patch has been published.) Please avoid altering i18n files and adding/significantly altering unit test files within your security patch. You can hard-code the messages as English text – after all, a security patch message isn’t going to be translated on translatewiki.net anyways (until the patch has been published) and unit tests won't be run either until the patch is public. Avoiding adding i18n and unit tests helps keep patches small and reduces the chances of merge conflicts. Feel free to provide a more complete version of the patch with i18n and unit test updates on the Phabricator task. The Security team will ensure the minimal version of the patch is what gets deployed and the complete version is published on Gerrit at release time. Deployment: ManualThis is the preferred method of deployment for the Wikimedia Security Team
Deployment: via scriptGet the patch to your home directory in deployment.eqiad.wmnet: scp /path/to/patch/TXXXXXX.patch deployment.eqiad.wmnet: Download the security deployment script: wget https://gitlab.wikimedia.org/repos/releng/release/-/raw/main/deploy_security.py
Then run it like this: python3 deploy_security.py /path/to/patch/T1234.patch REPO
python3 deploy_security.py --branch 1.38.0-wmf.12 --run /path/to/patch/T1234.patch core
After
Problem: Submodule security patches not committedSometimes you may find a security patch for an extension that has not been committed: [you@deploy1002 php-1.999.0-wmf.1 (wmf/1.999.0-wmf.1 * u)]$ git status On branch wmf/1.999.0-wmf.1 Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: extensions/InsecurityExtension (new commits) Submodules changed but not updated: * extensions/InsecurityExtension fffffff...eeeeeee (1): > SECURITY: Make the Insecurity extension secure no changes added to commit (use "git add" and/or "git commit -a") This is normal! The reason for this state is that subsequent updates to the submodules require human intervention to fix merge/rebase conflicts. Security mitigationsSometimes it is necessary to deploy application-layer security mitigations and secrets to Wikimedia production environments. At the MediaWiki layer, this is typically done via various configuration files that live within
If you are deploying a configuration secret that is used by application code, don't forget to also add the config variable to the Beta cluster. Make sure you use a different value. Also please document it in private/readme.php (which is not actually private!). Problem: undeployed codeIf you need to deploy something but you find undeployed changes or local changes that are not security fixes[2], revert all of them and !log your revert, then proceed to your deploy. If it's uncommitted live-hacks (as in, not even in gerrit), the polite thing is to stash them, so you don't erase someone's work forever. BackgroundRoan commented in October 2012: The problem is that sometimes, people merge things into a deployment branch and then don't deploy them. This is a terrible habit that should be squashed. If you merge something into a wmf branch, you have a responsibility to either deploy it yourself very soon, make sure that someone deploys it very soon, or revert it if you can't make those things happen. The deployment branch should reflect the current state of the cluster, except during those brief moments where something is about to be deployed or in the process of being deployed. If you are concerned about other commits being pulled in (which should never happen, unless someone has been naughty), then in Step 2 you can run git fetch followed by git log HEAD..@{upstream}. This will list the commits that would be pulled by 'git pull'. In that list, it should be easy to spot commits that aren't yours and identify the person to yell at. If you run git pull and it ends up pulling things you didn't expect, you can use git log to examine what happened, and git reflog (or the output of git pull) to find the hash of the commit you were at before pulling, so you can roll back to it if needed. But if this happens to you, feel free to start yelling at people and/or asking for help. Problem: file permissions errorsIf you encounter permission denied errors (errno 13) on local disk files under Emergency runbook for production config changesThis is the procedure for making an emergency MediaWiki production config change; it should not be necessary. Please liaise in security IRC if you think this is needed.
Footnotes
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |