1# PHP Release Process 2 3A release manager's role includes making packaged source code from the canonical 4repository available according to the release schedule. 5 6The release schedule for each version is published on the 7[PHP wiki](https://wiki.php.net): 8 9- [PHP 8.3](https://wiki.php.net/todo/php83) 10- [PHP 8.2](https://wiki.php.net/todo/php82) 11- [PHP 8.1](https://wiki.php.net/todo/php81) 12 13The PHP project publishes builds every two weeks. 14 15We publish [general availability][] (GA) releases for major and minor versions of 16PHP on the fourth Thursday of November each year. Following the GA release, we 17publish patch-level releases every four weeks, with at least one release 18candidate (RC) published two weeks before each patch-level release. 19 20Each major and minor version undergoes a 24-week pre-release cycle before GA 21release. The pre-release cycle begins on the second Thursday of June with the 22first alpha release of the new major/minor version. The pre-release cycle 23consists of at least: 24 25- 3 alpha releases 26- 3 beta releases 27- 6 release candidates 28 29Feature freeze for the next major/minor occurs with the first beta release. 30 31We refer to alpha, beta, and RC as *non-stable releases*, while GA are *stable*. 32 33The process of making packaged source available and announcing availability is 34explained in detail below. The process differs slightly for non-stable and 35stable releases. 36 37New release managers should review [New release manager 38checklist](#new-release-manager-checklist) at the end of this document. This 39section explains the procedures for getting ready to begin work on managing PHP 40releases. 41 42 43## General notes and tips 44 451. Do not release on Fridays, Saturdays, or Sundays as this gives poor lead 46 time for downstream consumers adhering to a typical work week. 47 48 Our general procedure is to release on Thursdays, whenever possible. 49 502. Package two days before a release. 51 52 If the release is to be on Thursday, package on Tuesday. Think about 53 timezones as well. 54 553. Ensure that the relevant tests on CI are green. 56 57 - https://cirrus-ci.com/github/php/php-src 58 - https://github.com/php/php-src/actions 59 60 > **Tip** \ 61 > We recommend checking the build status a couple of days before packaging day 62 > to allow enough time to investigate failures, communicate with the authors, 63 > and commit any fixes. 64 > 65 > Check the CI status for your branch periodically and resolve the failures 66 > ASAP. 67 > 68 > See more in https://wiki.php.net/rfc/travis_ci. 69 704. Follow all steps to the letter. 71 72 > **Tip** \ 73 > When you are unsure about anything, ask a previous RM before proceeding. 74 > Ideally, make sure a previous RM is available to answer questions during 75 > the first few releases of your version. For the steps related to the 76 > `web-php`, `web-qa`, and `web-php-distributions` repositories, try to have 77 > someone from the webmaster team on hand. 78 795. Verify the tags to be extra sure everything was tagged properly. 80 816. There is a PHP release Docker image https://github.com/sgolemon/php-release 82 with forks available to help with releases. 83 847. Communicate with release managers via release-managers@php.net. 85 868. References to repositories in this document refer to the canonical source 87 located at https://github.com/php. 88 899. It might be helpful to name your remote repositories something other than 90 "origin" to avoid accidentally pushing changes to "origin" with [muscle 91 memory][]. 92 9310. It might also be helpful to set up conditional includes in your global 94 `~/.gitconfig` to set the proper `user.name`, `user.email`, and 95 `user.signingKey` values to use with your local PHP repositories. See 96 [Conditional Includes For Git Config][] for more information. 97 98 99## Packaging a non-stable release (alpha/beta/RC) 100 101All releases during the pre-release cycle (alpha/beta/RC) leading up to the GA 102release for a version are *non-stable* releases. Following the GA release, all 103RCs are *non-stable* releases. 104 105All non-stable releases follow a similar pattern, though pre-GA releases have 106slightly different steps. We'll call attention where the steps differ. 107 1081. Check that CI is passing (see above). 109 1102. Run `./scripts/dev/credits` in php-src and commit the changes to the credits 111 files in `ext/standard`. 112 113 > **Hint** \ 114 > It's rare this script will make any changes, so if you run `git diff` 115 > and do not see anything, there's no need to panic. That means there are no 116 > changes to the credits files. 117 1183. Check out the *release branch* for this release from the *version branch*. 119 120 > **Non-stable version branches: pre-GA** \ 121 > There is no *version branch* for alpha or beta releases. Instead, treat the 122 > main branch as the version branch. You will create a local-only release 123 > branch from the main branch. Do not push it! 124 > 125 > ```shell 126 > git checkout -b php-X.Y.0alpha1-local-release-branch upstream/master 127 > ``` 128 > 129 > During the first RC release, you will create (and push!) the version 130 > branch for the pre-GA release, e.g., `PHP-8.2`. See 131 > "[Forking a new version branch](#forking-a-new-version-branch)" below. 132 > From this point forward, all pre-GA release branches will be created from 133 > this version branch. Again, these release branches are local-only. Do not 134 > push them! 135 > 136 > ```shell 137 > git checkout -b php-X.Y.0beta2-local-release-branch upstream/PHP-X.Y 138 > ``` 139 140 > **Non-stable version branches: post-GA** \ 141 > After GA, you will create (and push) a new *patch-level version branch* 142 > along with each non-stable release. For example, if you are building a 143 > release for PHP 8.2.8 RC1, you will create the `PHP-8.2.8` patch-level 144 > version branch from the `PHP-8.2` version branch. 145 > 146 > ```shell 147 > git checkout -b PHP-X.Y.Z upstream/PHP-X.Y 148 > git push upstream PHP-X.Y.Z 149 > ``` 150 > 151 > We will use the patch-level version branch to commit any critical bug or 152 > security fixes before this version's GA. 153 > 154 > Then, from the patch-level version branch, you will create another 155 > local-only release branch. Do not push this one! 156 > 157 > ```shell 158 > git checkout -b php-X.Y.ZRC1-local-release-branch upstream/PHP-X.Y.Z 159 > ``` 160 1614. Using your local-only release branch, bump the version numbers in 162 `main/php_version.h`, `Zend/zend.h`, `configure.ac`, and possibly 163 `NEWS`. 164 165 For examples, see [Update versions for PHP 8.1.0beta3][] (for a pre-GA 166 example) or [Update versions for PHP 8.1.6RC1][] along with 167 [Update NEWS for PHP 8.1.6RC1][] (for a post-GA example). 168 169 > ⚠️ **Important** \ 170 > Do not use abbreviations for alpha or beta. Do not use dashes as 171 > separators. 172 > 173 > Do this: 174 > 175 > ```c 176 > #define PHP_VERSION "7.4.22RC1" 177 > ``` 178 > 179 > Not this: 180 > 181 > ```c 182 > #define PHP_VERSION "7.4.22-RC1" 183 > ``` 184 185 > **Note** \ 186 > We update `Zend/zend.h` only when preparing RC and GA releases. We do not 187 > update `ZEND_VERSION` for alpha or beta releases. 188 189 > **API version bump for pre-GA** \ 190 > When releasing the *first release candidate* of a pre-GA release, you must 191 > also bump the API version numbers in `Zend/zend_extensions.h`, 192 > `Zend/zend_modules.h`, and `main/php.h`. See [Prepare for PHP 8.1.0RC1][], 193 > for example. 194 > 195 > The API versions between the alpha, beta, and X.Y.0RCn releases may remain 196 > the same, or be bumped as little as possible because PHP extensions need to 197 > be rebuilt with each bump. 198 > 199 > Do *not* bump the API versions after RC1. 200 2015. Compile and run `make test`, with and without ZTS (Zend Thread Safety), using 202 the correct Bison and re2c versions, e.g., for PHP 7.4, Bison 3.0.0 and re2c 203 0.13.4 are required, as a minimum. 204 205 For example: 206 207 ```shell 208 # With ZTS 209 make distclean || \ 210 ./buildconf --force \ 211 && ./configure --enable-zts --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ 212 && make -j$(nproc) \ 213 && make test TEST_PHP_ARGS="-q -j$(nproc)" \ 214 || ./sapi/cli/php -v 215 216 # Without ZTS 217 make distclean || \ 218 ./buildconf --force \ 219 && ./configure --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ 220 && make -j$(nproc) \ 221 && make test TEST_PHP_ARGS="-q -j$(nproc)" \ 222 || ./sapi/cli/php -v 223 ``` 224 2256. After each build, check the output of `./sapi/cli/php -v` to ensure the 226 versions match the release. 227 2287. If all is correct, commit the changes to your local-only release branch. 229 230 ```shell 231 git add -p 232 git commit --gpg-sign=YOURKEYID -m "Update versions for PHP X.Y.ZRCn" 233 ``` 234 2358. Tag your local-only release branch with the release version. 236 237 ```shell 238 git tag -s -u YOURKEYID php-X.Y.ZRCn -m "Tag for php-X.Y.ZRCn" 239 ``` 240 2419. **For pre-GA releases only,** switch back to the `master` (for alphas and betas), 242 or `PHP-X.Y` (for RCs), and update a `NEWS` for the new version. See 243 [Update NEWS for PHP 8.2.0 alpha2][] and [Update NEWS for PHP 8.2.0RC6][] for a real example. 244 245 Commit the changes to the `master` (or `PHP-X.Y`) branch. 246 247 ```shell 248 git add -p 249 git commit --gpg-sign=YOURKEYID -m "[ci skip] Update NEWS for PHP X.Y.Z alpha2" 250 ``` 251 252 **For post-GA releases only,** switch back to the *version branch* for 253 your release (e.g., `PHP-8.2`) and bump the version numbers in 254 `main/php_version.h`, `Zend/zend.h`, `configure.ac` and `NEWS`. This prepares 255 the version branch for the next version. 256 257 For example, if the RC is `8.2.1RC1` then the version numbers in the version 258 branch should be bumped to `8.2.2-dev`. We do this regardless of whether we 259 build a new RC to make sure `version_compare()` works correctly. See 260 [Bump for 8.1.8-dev][] for a real example. 261 262 Commit the changes to the version branch. 263 264 ```shell 265 git add -p 266 git commit --gpg-sign=YOURKEYID -m "PHP-X.Y is now for PHP X.Y.Z-dev" 267 ``` 268 269 > **Tip** \ 270 > Version branches (e.g. `PHP-8.1`) will *always* have version numbers in 271 > `main/php_version.h`, `Zend/zend.h`, and `configure.ac` that end in `-dev`. 272 > Patch-level version branches (e.g. `PHP-8.1.7`) will also *always* have 273 > version numbers that end in `-dev` in these files. The main branch (i.e. 274 > `master`) will *always* have version numbers that end in `-dev` in these 275 > files. 276 > 277 > Only release tags should have version numbers in these files that do not 278 > end in `-dev` (e.g., `8.1.7`, `8.1.7RC1`, `8.2.0alpha1`, etc.). 279 28010. Push the changes to the `php-src`. 281 282 ```shell 283 git push upstream php-X.Y.ZRCn # tag name 284 git push upstream PHP-X.Y.Z # patch-level version branch (post-GA only) 285 git push upstream PHP-X.Y # version branch 286 ``` 287 288 > **Attention** \ 289 > Do not push with `--tags`, as this will push all local tags, including 290 > tags you might not wish to push. 291 > 292 > Local-only release branches should not be pushed! 293 29411. Run the following using the release tag to export the tree, create the 295 `configure` script, and build and compress three tarballs (`.tar.gz`, 296 `.tar.bz2` and `.tar.xz`). 297 298 ```shell 299 ./scripts/dev/makedist php-X.Y.ZRCn 300 ``` 301 30212. Run the following using the release tag and your GPG key ID to sign the 303 tarballs and save the signatures to `php-X.Y.ZRCn.manifest`, which you can 304 upload to GitHub and include in the announcement emails. 305 306 ```shell 307 ./scripts/dev/gen_verify_stub X.Y.ZRCn YOURKEYID > php-X.Y.ZRCn.manifest 308 ``` 309 31013. If you have the [GitHub command line tool][] installed, run the following to 311 create a public Gist for the manifest file: 312 313 ```shell 314 gh gist create --public php-X.Y.ZRCn.manifest 315 ``` 316 317 Or you may go to https://gist.github.com to create it manually. 318 31914. Copy the tarballs (using scp, rsync, etc.) to your `public_html/` folder on 320 downloads.php.net. 321 322 ```shell 323 scp php-X.Y.ZRCn.tar.* downloads.php.net:~/public_html/ 324 ``` 325 326 > **Hint** \ 327 > If you do not have a `public_html` directory, create it and set its 328 > permissions to `0755`. 329 33015. Now the tarballs and signatures may be found at 331 `https://downloads.php.net/~yourname/`, e.g. https://downloads.php.net/~derick/. 332 33316. Once the release is tagged, contact the release-managers@php.net distribution 334 list so that Windows binaries can be created. Once those are made, they may 335 be found at https://windows.php.net/qa/. 336 337 Here is an example "ready for builds" message to release-managers@php.net: 338 339 ```text 340 Subject: PHP 8.1.6RC1 ready for builds 341 342 Hi, all! 343 344 Tag: php-8.1.6RC1 345 Tarballs: https://downloads.php.net/~ramsey/ 346 Manifest: https://gist.github.com/ramsey/5d73f0717effb6d8d17699381361e4b1 347 348 Cheers, 349 Ben 350 351 << PASTE FULL MANIFEST CONTENTS HERE >> 352 ``` 353 354 355## Announcing a non-stable release (alpha/beta/RC) 356 3571. Switch to your local clone of the `web-qa` repository and update the 358 information in the `$QA_RELEASES` array in `include/release-qa.php`. 359 360 Follow the documentation in the file for editing the QA release information. 361 See also [Announce 8.1.0RC3][] and [8.1.6RC1][] for examples. 362 363 Add, commit, and push your changes, when finished. 364 365 ```shell 366 git add -p 367 git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.ZRCn" 368 git push upstream master 369 ``` 370 3712. **For pre-GA releases only,** add a short notice to `web-php` stating 372 there is a new release, and highlight the major changes (e.g., security 373 fixes). 374 375 To help produce the files for this, use the `bin/createNewsEntry` tool. When 376 you run it, it will ask several questions (see below). For pre-GA non-stable 377 releases, use only the "frontpage" category. 378 379 ```shell 380 cd /path/to/repos/php/web-php 381 ./bin/createNewsEntry 382 # Please type in the title: PHP X.Y.0 Alpha n available for testing 383 # Categories: 384 # 0: PHP.net frontpage news [frontpage] 385 # 1: New PHP release [releases] 386 # 2: Conference announcement [conferences] 387 # 3: Call for Papers [cfp] 388 # Please select appropriate categories, separated with space: 0 389 # Will a picture be accompanying this entry? no 390 # And at last; paste/write your news item here. 391 # To end it, hit <enter>.<enter> 392 # 393 # [[ Here you will paste the full HTML of the post. ]] 394 # . 395 # 396 git add -p 397 git add archive/entries/*.xml 398 git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.0RCn" 399 git push upstream master 400 ``` 401 402 Each news entry for pre-GA releases will be similar, though we change the 403 text slightly to indicate progression through the pre-release cycle. For 404 example, here are all the news posts for the pre-GA releases of PHP 8.1.0: 405 406 * [Announce 8.1.0alpha1](https://github.com/php/web-php/commit/57b9675c8d8550493289fa1fba77427c93cdd472) 407 * [Announce 8.1.0alpha2](https://github.com/php/web-php/commit/cec044fc0763f5cfa77d0e79479f8b6279023570) 408 * [Announce 8.1.0alpha3](https://github.com/php/web-php/commit/5c480765f444a3fddfd575e01fe0be3fcfdde05b) 409 * [Announce 8.1.0beta1](https://github.com/php/web-php/commit/40840e3c3f89d6dd95baa4b8cdf22d6f206f86c2) 410 * [Announce 8.1.0beta2](https://github.com/php/web-php/commit/7bf6acdadd4940bd9db711bf3f9d5a4054dc0722) 411 * [Announce 8.1.0beta3](https://github.com/php/web-php/commit/38c8a872700fb0c2ebde49e2eae3374257ba6d08) 412 * [Announce 8.1.0RC1](https://github.com/php/web-php/commit/6e4bf3d0228ce113728d5f1a769ed42e0d63ca10) 413 * [Announce 8.1.0RC2](https://github.com/php/web-php/commit/1ae95f4b686a5d614a94a664a7466ee0e5cd21eb) 414 * [Announce 8.1.0RC3](https://github.com/php/web-php/commit/3091246d77a3f445fcc593587597d0abcab8c373) 415 * [Announce 8.1.0RC4](https://github.com/php/web-php/commit/fbaeb9403f4e2856115889946d3f63751e183c7b) 416 * [Announce 8.1.0RC5](https://github.com/php/web-php/commit/46473ccccfb5f7fedc3f169c55fb7c22a596b55d) 417 * [Announce 8.1.0RC6](https://github.com/php/web-php/commit/cacaef9c41352b5dbf3fbbf44702cc6c0cbfb478) 418 419 > ⚠️ **Important** \ 420 > In your announcement news entry, be sure to include the following text or 421 > text similar to the following: 422 > 423 > > Please DO NOT use this version in production, it is an early test version. 424 425 > **Note** \ 426 > When a version is in its post-GA phase, we do not post news entries for 427 > non-stable releases. 428 4293. Wait for the web and qa sites to update with the new information before 430 sending announcements. This could take up to an hour. 431 4324. Send *separate* announcement emails to: 433 434 * `internals@lists.php.net` 435 * `php-general@lists.php.net` 436 * `php-qa@lists.php.net` 437 438 In the announcement message, point out the location of the release and the 439 possible release date of either the next RC or the final release. Also 440 include the manifest generated by `gen_verify_stub` when you packaged the 441 build. 442 443 Here are a few examples of non-stable release announcement emails: 444 445 * [PHP 8.1.0alpha1 is available for testing](https://news-web.php.net/php.qa/69043) 446 * [PHP 8.1.0beta3 available for testing](https://news-web.php.net/php.qa/69079) 447 * [PHP 8.1.0RC6 available for testing](https://news-web.php.net/php.qa/69117) 448 * [PHP 8.1.7RC1 Ready for testing](https://news-web.php.net/php.qa/69163) 449 450 > **Send separate emails!** \ 451 > Do *not* send a single email message with all addresses in the `To`, `Cc`, 452 > or `Bcc` headers. If a user replies to one of these messages, we do not 453 > want their email client to automatically send the reply to each list, as 454 > often occurs. 455 456 > **Hint** \ 457 > We send emails to the followers of these mailing lists to notify them of 458 > new releases, so they can make sure their projects keep working and can 459 > report any potential bugs that should be fixed before the upcoming GA 460 > release. 461 4625. **For pre-GA *RCs* only,** coordinate with the social media team (i.e., 463 Derick) to post a tweet with the RC release announcement and link to the news 464 entry on php.net. ([@official_php](https://twitter.com/official_php)) 465 466 467## Packaging a stable release 468 4691. Check out the *patch-level version branch* for the release 470 (e.g., `PHP-8.1.7`). 471 472 > **Hint** \ 473 > You should have created this branch when packaging the non-stable release 474 > candidate for this version. If it is for a PHP-X.Y.0 version, then just 475 > create and push this branch. 476 4772. If a CVE commit needs to be merged to the release, have it committed to 478 the base branches and [merged upwards as usual][] (e.g. commit the CVE fix 479 to 7.2, merge to 7.3, 7.4, etc.). Then, you can cherry-pick it into the 480 patch-level version branch for this release. 481 482 Commit these changes and push the patch-level version branch. Ensure 483 that CI is still passing (see above). 484 485 > **Tip** \ 486 > Don't forget to update `NEWS` manually in an extra commit to the 487 > patch-level version branch. 488 4893. Run the `./scripts/dev/credits` script in the patch-level version branch, 490 and commit the changes in the credits files in `ext/standard`. 491 492 > **Note** \ 493 > It's very rare this will make changes at this point, but we run it here 494 > in case the credits changed as a result of a bug fix that was 495 > cherry-picked into this branch. 496 4974. Create a local-only release branch for this release from the *patch-level 498 version branch*. 499 500 ```shell 501 git checkout -b php-X.Y.Z-local-release-branch upstream/PHP-X.Y.Z 502 ``` 503 5045. Using your local-only release branch, bump the version numbers in 505 `main/php_version.h`, `Zend/zend.h`, `configure.ac`, and possibly 506 `NEWS`. 507 508 For example, if you're releasing a stable version for PHP 8.1.8, then all 509 the version numbers in the patch-level version branch should be 510 `8.1.8-dev`. In your local-only release branch, you will change them all to 511 `8.1.8`. 512 513 See [Update versions for PHP 8.1.7][] and [Update NEWS for PHP 8.1.7][] for 514 an example. 515 5166. Compile and run `make test`, with and without ZTS (Zend Thread Safety), using 517 the correct Bison and re2c versions, e.g., for PHP 7.4, Bison 3.0.0 and re2c 518 0.13.4 are required, as a minimum. 519 520 For example: 521 522 ```shell 523 # With ZTS 524 make distclean || \ 525 ./buildconf --force \ 526 && ./configure --enable-zts --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ 527 && make -j$(nproc) \ 528 && make test TEST_PHP_ARGS="-q -j$(nproc)" \ 529 || ./sapi/cli/php -v 530 531 # Without ZTS 532 make distclean || \ 533 ./buildconf --force \ 534 && ./configure --disable-all --enable-debug --enable-opcache --enable-opcache-jit \ 535 && make -j$(nproc) \ 536 && make test TEST_PHP_ARGS="-q -j$(nproc)" \ 537 || ./sapi/cli/php -v 538 ``` 539 5407. After each build, check the output of `./sapi/cli/php -v` to ensure the 541 versions match the release. 542 5438. If all is correct, commit the changes to your local-only release branch. 544 545 ```shell 546 git add -p 547 git commit --gpg-sign=YOURKEYID -m "Update versions for PHP X.Y.Z" 548 ``` 549 5509. Tag your local-only release branch with the release version and push the tag. 551 552 ```shell 553 git tag -s -u YOURKEYID php-X.Y.Z -m "Tag for php-X.Y.Z" 554 git push upstream php-X.Y.Z 555 ``` 556 55710. Run the following using the release tag to export the tree, create the 558 `configure` script, and build and compress three tarballs (`.tar.gz`, 559 `.tar.bz2` and `.tar.xz`). 560 561 ```shell 562 ./scripts/dev/makedist php-X.Y.Z 563 ``` 564 565 > **Hint** \ 566 > Check if the PEAR files are updated (Phar). 567 568 > **Tip** \ 569 > On some systems the behavior of GNU tar can default to produce POSIX 570 > compliant archives with PAX headers. As not every application is 571 > compatible with that format, creation of archives with PAX headers should 572 > be avoided. When packaging on such a system, the GNU tar can be influenced 573 > by defining the environment variable `TAR_OPTIONS='--format=gnu'`. 574 57511. Run the following using the release tag and your GPG key ID to sign the 576 tarballs and save the signatures to `php-X.Y.Z.manifest`, which you can 577 upload to GitHub and include in the announcement emails. 578 579 ```shell 580 ./scripts/dev/gen_verify_stub X.Y.Z YOURKEYID > php-X.Y.Z.manifest 581 ``` 582 58312. If you have the [GitHub command line tool][] installed, run the following to 584 create a public Gist for the manifest file: 585 586 ```shell 587 gh gist create --public php-X.Y.Z.manifest 588 ``` 589 590 Or you may go to https://gist.github.com to create it manually. 591 59213. Switch to your local clone of the `web-php-distributions` repository and 593 copy the tarballs and signature files into the repository. Add, commit, and 594 push them. 595 596 ```shell 597 cd /path/to/repos/php/web-php-distributions 598 mv /path/to/repos/php/php-src/php-X.Y.Z.tar.* . 599 git add php-X.Y.Z.tar.* 600 git commit --gpg-sign=YOURKEYID -m "Add tarballs for php-X.Y.Z" 601 git push upstream master 602 ``` 603 60414. Switch to your local clone of the `web-php` repository and update the 605 `web-php-distributions` submodule. 606 607 ```shell 608 cd /path/to/repos/php/web-php 609 git pull --rebase upstream master 610 git submodule init 611 git submodule update 612 cd distributions 613 git fetch --all 614 git pull --rebase upstream master 615 cd .. 616 git commit distributions -m "X.Y.Z tarballs" 617 git push upstream master 618 ``` 619 620 > **Hint** \ 621 > This fetches the last commit ID from `web-php-distributions` and pins the 622 > "distributions" submodule in `web-php` to this commit ID. 623 > 624 > When the website syncs, which should happen within an hour, the tarballs 625 > will be available from `https://www.php.net/distributions/php-X.Y.Z.tar.gz`, 626 > etc. 627 62815. Once the release is tagged, contact the release-managers@php.net distribution 629 list so that Windows binaries can be created. Once those are made, they may 630 be found at https://windows.php.net/qa/. 631 632 > ⚠️ **Important** \ 633 > Do *not* send this announcement to any public lists. 634 635 Here is an example "ready for builds" message to release-managers@php.net: 636 637 ```text 638 Subject: PHP 8.1.6 ready for builds 639 640 Hi, all! 641 642 Tag: php-8.1.6 643 Tarballs: web-php-distributions 644 Manifest: https://gist.github.com/ramsey/432fcf8afcbfb1f1de6c3ab47d82e366 645 646 Cheers, 647 Ben 648 649 << PASTE FULL MANIFEST CONTENTS HERE >> 650 ``` 651 652 653## Announcing a stable release 654 6551. This steps applies only for releases after PHP-X.Y.0. 656 657 Switch to your local clone of `web-php` and add the information for the 658 previous release to `include/releases.inc`. 659 660 For example, if you are preparing to announce version 8.2.2, then the 661 previous release is 8.2.1, so you will add the information for 8.2.1 to this 662 file. Most of the time, you can do this using the `bin/bumpRelease` tool. 663 664 ```shell 665 ./bin/bumpRelease 8 2 666 ``` 667 668 The first number is the major version, and the second number is the minor 669 version. In this example, we're bumping the release information for version 670 8.2. There is no need to provide the patch level. 671 672 > **Tip** \ 673 > If this fails for any reason, you can manually copy the information 674 > for the previous release from `include/version.inc` into 675 > `include/releases.inc`. 676 6773. Update the version information for the new release in `include/version.inc`. 678 679 Find the part of the `$data` array that is related to your version (e.g., 680 `$data['8.2']` for 8.2.x releases) or create a new section if releasing 681 PHP-X.Y.0 version, and make the following edits / additions: 682 683 * Set `version` to the full version number (e.g. '8.2.1') 684 * Set `date` to the release date in `j M Y` format (e.g. '5 Jan 2021') 685 * Update the `tags` array to include `'security'` if this is a security release 686 * Set the `sha256` array with the hashes for each of the release tarballs 687 6885. Create the release file and news entry for the new version. 689 690 ```shell 691 ./bin/createReleaseEntry -v X.Y.Z -r # --security for security releases 692 ``` 693 694 This will create a release file (i.e., `releases/X_Y_Z.php`) and a news entry 695 file (i.e., `archive/entries/YYYY-MM-DD-n.xml`), while also updating 696 `archive/archive.xml`. 697 698 Within these files, it will generate standard messages for the new version. 699 You may edit the generated files to expand on the base message, if needed. 700 701 The edits are necessary for PHP-X.Y.0 version where the format is different. 702 See for example [PHP-8.2 announcement](https://github.com/php/web-php/commit/c966868202caafa880213055f4e3e97c0483119b) 703 7047. Update the ChangeLog file for the given major version (e.g., `ChangeLog-8.php`). 705 706 If PHP-X.Y.0 is released, modify the `ChangeLog-X.php` (where `X` is the major 707 version) file manually first. The `$MINOR_VERSIONS` field needs to be extended 708 with the new version and initial anchor (e.g. `<a id="PHP_8_4"></a>` if added 709 for PHP 8.4) added above the first anchor of the previous version. 710 711 ```shell 712 ./bin/news2html 'https://github.com/php/php-src/raw/php-X.Y.Z/NEWS' 'X.Y.Z' 'ChangeLog-X.php' 713 ``` 714 7159. Review all the changes in `web-php`, commit, and push them. 716 717 ```shell 718 git add -p 719 git add archive/entries/*.xml releases/*.php 720 git commit --gpg-sign=YOURKEYID -m "Announce PHP X.Y.Z" 721 git push upstream master 722 ``` 723 724 See [Announce PHP 8.1.6][] for an example commit. 725 72610. Switch to your local clone of the `web-qa` repository and update the 727 information in the `$QA_RELEASES` array in `include/release-qa.php`. 728 729 The array probably contains information about the RC released two weeks ago 730 in preparation for the current release. Since the current release is now GA, 731 it's time to remove the RC build from the QA website. 732 733 It is sufficient to set the `number` property for the release to `0` to 734 stop displaying the RC build on the QA website. You may also remove the 735 sha256 hashes for the RC tarballs, but it's not necessary. For an example, 736 see [PHP 8.1.6 released][]. 737 738 Add, commit, and push your changes, when finished. 739 740 ```shell 741 git add -p 742 git commit --gpg-sign=YOURKEYID -m "PHP X.Y.Z released" 743 git push upstream master 744 ``` 745 74611. **Before sending announcement emails, check to make sure the websites have 747 synced.** 748 749 * Make sure the tarballs are available from, e.g., 750 `https://www.php.net/distributions/php-X.Y.Z.tar.gz` 751 * Check the "downloads" page to make sure the new version appears: 752 https://www.php.net/downloads 753 * Does the news entry show up on the home page? https://www.php.net 754 * Do the updates to the ChangeLog appear? 755 e.g., https://www.php.net/ChangeLog-8.php 756 * Is there a release page for the new version? 757 e.g., `https://www.php.net/releases/X_Y_Z.php` 758 * Does the RC for this version still appear on the QA home page? 759 https://qa.php.net 760 761 Keep in mind it may take up to an hour for the websites to sync. 762 76311. Please note down the sha256 and the PGP signature (.asc). These *must* be 764 included in the release mail. 765 76612. Send *separate* announcement emails to: 767 768 * `php-announce@lists.php.net` 769 * `php-general@lists.php.net` 770 * `internals@lists.php.net` 771 772 Release announcement emails must include the manifest generated when 773 packaging the build, along with links to the sources, Windows binaries, and 774 changelog. Here are a few examples of stable release announcement emails: 775 776 * [PHP 8.1.0 Released](https://news-web.php.net/php.announce/321) 777 * [PHP 8.1.3 Released](https://news-web.php.net/php.announce/325) 778 * [PHP 8.1.6 Released](https://news-web.php.net/php.announce/331) 779 780 > ⚠️ **Important** \ 781 > For standard patch-level releases, we will note "This is a bugfix release." 782 > If it is a security release, we must note "This is a security release." 783 784 > **Send separate emails!** \ 785 > Do *not* send a single email message with all addresses in the `To`, `Cc`, 786 > or `Bcc` headers. If a user replies to one of these messages, we do not 787 > want their email client to automatically send the reply to each list, as 788 > often occurs. 789 79013. Coordinate with the social media team (i.e., Derick) to 791 [create a PR request](https://github.com/derickr/toot-together/blob/main/toots/README.md) 792 for posting the release announcement to Mastodon. Posts need to be 793 approved. 794 795## Re-releasing the same version or a patch-level (i.e., `-plN`) 796 797While unlikely, there may be times we need to re-release the same version. This 798might happen if the tarballs have a corrupted file, for example. 799 800Should this occur *before* announcing the release, you may choose to delete the 801tag and go through the full packaging process again, as described above. 802 803> **Hint** \ 804> This is one of the reasons we package releases two days before announcing 805> them. 806 807If this happens *after* announcing the release, you may choose to tag, package, 808and release a patch-level (i.e., *pl*) release. If it is not critical and/or 809affects a very limited subset of users, then you may choose to wait until the 810next release. 811 812If you choose to create a patch-level release, follow these steps: 813 8141. Commit the new binaries to `web-php-distributions` 815 8162. Update $data['X.Y'] in `web-php:/include/version.inc` 817 (X.Y=major.minor release, e.g. '8.0'): 818 819 * `version` to the full version number (e.g. '8.0.1-pl1') 820 * `date` to the release date in `j M Y` format (e.g. '9 Jan 2021') 821 * `tags` array should include `security` if this is a security release 822 * `sha256` array and sub-elements for all SHA256 sums 823 8243. Add a short notice to `web-php` stating that there is a new release, and 825 highlight the major important things (security fixes) and when it is 826 important to upgrade. 827 828 * Call `php bin/createReleaseEntry -v <version> [ --security ]` in your 829 local web-php checkout. 830 8314. Commit all the changes (`include/version.inc`, `archive/archive.xml`, 832 `archive/entries/YYYY-MM-DD-N.xml`). 833 8345. Wait an hour or two, then send a mail to php-announce@lists.php.net, 835 php-general@lists.php.net and internals@lists.php.net with a text similar to 836 the news entry. 837 838 Please make sure that the mail to php-announce@ is its own completely 839 separate email. This is to make sure that replies to the announcement on 840 php-general@ or internals@ will not accidentally hit the php-announce@ 841 mailinglist. 842 843 844## Feature freeze 845 846A major/minor version [feature freeze][] occurs with the first beta release. 847Specifically, it occurs when the first beta release is packaged, which means the 848feature freeze occurs two days before the first beta release. 849 850The feature freeze for `php-src` means that we will not accept any new features 851after the date of the feature freeze. For any RFCs to be included in the new 852version, they should be discussed and have the voting polls closed no later than 853the feature freeze date. However, this does not mean the new feature must have a 854complete implementation by this date. 855 856Following the feature freeze, the focus of work for the new version will be on 857fixing bugs, writing tests, and completing/polishing all accepted features. 858 859As a courtesy to the community, the release managers should remind others about 860the upcoming feature freeze by posting reminders to internals@lists.php.net at 8614-weeks, 3-weeks, 2-weeks, and 1-week prior to the feature freeze. This is a 862recommendation and the intervals may vary based on work load. 863 864 865## Forking a new version branch 866 867When the new version has reached the first RC, it is time to create a new 868version branch. This frees up the main branch (i.e., `master`) for any new 869feature development that cannot go into the new version. 870 8711. One week prior to tagging `X.Y.0RC1`, warn internals@ that your version's 872 branch is about to be created. Be specific about when the branch creation 873 will occur. For example: https://news-web.php.net/php.internals/99864 874 8752. Just prior to tagging `X.Y.0RC1`, create the new version branch locally, 876 i.e. `PHP-X.Y`. 877 8783. Add a commit on the main branch (i.e., `master`) after the branch point. 879 880 This commit should: 881 882 * clear the `NEWS`, `UPGRADING`, and `UPGRADING.INTERNALS` files; 883 * update the version numbers in `configure.ac`, `main/php_version.h`, 884 `Zend/zend.h`, and `win32/build/confutils.js`; 885 * update the API version numbers in `Zend/zend_extensions.h`, 886 `Zend/zend_modules.h`, and `main/php.h`; and 887 * add the new branch to the list in `CONTRIBUTING.md`. 888 889 See [Prepare for PHP 8.2][] and [Prepare for PHP 8.2 (bis)][] for an example 890 of what this commit should include. 891 8924. Push the new version branch and the changes to the `master` branch, with an 893 appropriate commit message (e.g., "master is now for PHP 8.3.0-dev"). 894 8955. Immediately notify internals@ of the new branch and advise on the new merging 896 order. For example: https://news-web.php.net/php.internals/99903 897 8986. Update `web-php:git.php` and https://wiki.php.net/vcs/gitworkflow to reflect 899 the new branch. 900 901 For example: 902 903 * [Add PHP-8.1 to the Git steps page][] 904 * [Changes to the wiki][] 905 906> **Hint** \ 907> We create the new version branch at the first release candidate rather than at 908> feature freeze to allow a period of time where the focus is on making the new 909> version ready for RC and GA. During this time, the main branch is *only* for 910> minor improvements and bug fixes. All major improvements and new features must 911> wait. 912 913 914## Preparing for the initial stable version (PHP X.Y.0) 915 9161. When you release the first pre-GA RC, remind the documentation team 917 (phpdoc@lists.php.net) to write the [migration guide][]. Make sure the guide 918 is available before releasing the initial stable version, since you should 919 link to it in the release announcements. 920 9212. Timely get used to the differences in preparing and announcing a stable 922 release. 923 9243. Before releasing X.Y.0, merge the `NEWS` entries of the pre-releases, so that 925 there is only a single section about PHP X.Y.0, instead of individual 926 sections for each pre-release. 927 928 All the changes that are already present in the previous version NEWS should be 929 removed. It means all bug fixes that went to the previous version as well should 930 have their entries removed. It is possible to use `grep` to compare the changes. 931 For example if `82/NEWS` is NEWS for PHP 8.2 and `83/NEWS` is NEWS file for PHP 8.3, 932 then following command will show changes present in both files: 933 934 ```sh 935 grep -Fxf 82/NEWS 83/NEWS 936 ``` 937 938 9395. On the announcement day for the initial stable version (or shortly before), 940 update the `Expires` field in the <https://www.php.net/.well-known/security.txt> 941 file. The `Expires` field should be set to the expected date of the next X.Y.0 942 release (following the one currently being prepared), which is usually the 943 fourth Thursday of November in the next year. 944 945 Following the recommendation of [RFC 9116](https://www.rfc-editor.org/rfc/rfc9116), 946 we maintain an `Expires` time of about a year for our security policies. This 947 provides security researchers with confidence they are using our most 948 up-to-date reporting policies. 949 950 The `security.txt` file is located in the [web-php repository](https://github.com/php/web-php) 951 under the `.well-known/` directory. We may make changes to this file at other 952 times, as needed, but we will always advance the `Expires` timestamp on a 953 yearly cadence, coinciding with our X.Y.0 releases. 954 955 Please see the instructions for 956 [making changes to security.txt][security-txt]. 957 958 959## Prime the selection of release managers for the next version 960 961About three months prior to the scheduled release of the first alpha release of 962the next minor or major version (around March 1st or shortly thereafter), the 963release managers for the latest version branch should issue a call for 964volunteers to begin the selection process for the next release managers. 965 9661. Issue the call for volunteers on internals@lists.php.net on or around March 967 1st. See, for example: https://news-web.php.net/php.internals/113334 968 969 There is no rule for how long the call for volunteers must remain open. We 970 should aim to select the release managers by early April, so announcing the 971 call in early March gives people about a month to decide whether they wish to 972 volunteer. 973 9742. There should be two or more volunteers. Typically, one should be a veteran 975 release manager (having previously served as a `php-src` release manager), 976 while the other one (or two) should be rookies. Hold a vote if necessary (see 977 https://wiki.php.net/rfc/releaseprocess#release_managers_selection). 978 9793. Help the new release managers with their first steps. 980 981 982## New release manager checklist 983 9841. Request membership to the 985 [release managers group](https://github.com/orgs/php/teams/release-managers) on GitHub. 986 9872. Subscribe to the php-announce@lists.php.net mailing list by emailing 988 php-announce+subscribe@lists.php.net 989 9903. Email systems@php.net to get setup for access to downloads.php.net, to be 991 added to the release-managers@php.net distribution list, and to be added to 992 the moderators for php-announce@lists.php.net so you are able to moderate 993 your release announcements. 994 995 Provide the following information in a single email: 996 997 - Preferred Unix username (will also become part of location to download RCs, 998 such as `https://downloads.php.net/~derick/`). 999 - An SSH public key, preferably a new unique one for PHP systems and 1000 projects. 1001 - Read [Machine Access](https://wiki.php.net/systems#machine_access) to set 1002 up access to downloads.php.net through jump hosts, and provide a 1003 `.google_authenticator` file for 2FA. 1004 - Your @php.net email address to use for the release-managers@php.net 1005 distribution list and php-announce@lists.php.net moderator address. This 1006 should preferably not forward to a Gmail address. 1007 - Your GitHub account name, so that your membership to the release managers 1008 group may be approved. 1009 1010 A system admin will then contact you to go through with steps 5 through 8 of 1011 [2FA setup instructions](https://wiki.php.net/systems#fa_setup_instructions). 1012 1013 > **Hint** \ 1014 > To send email from your @php.net address, you will need to use a custom 1015 > SMTP server. If you use Gmail, you may 1016 > "[Send emails from a different address or alias][]." 1017 1018 10194. Create a [GPG key][] for your @php.net address. 1020 1021 > **Tip** \ 1022 > If you're new to GPG, follow GitHub's instructions for 1023 > [Generating a new GPG key][]. 1024 1025 Publish your key by editing `include/gpg-keys.inc` in the `web-php` 1026 repository. Add a `case` for your username to the `gpg_key_get()` function, 1027 and paste the output from `gpg --fingerprint`. You may also need to update 1028 the `$branches` array in the `gpg_key_get_branches()` function to include 1029 your username alongside your branch. 1030 1031 ```console 1032 ❯ gpg --fingerprint ramsey@php.net 1033 pub rsa4096 2021-04-26 [SC] [expires: 2025-11-24] 1034 39B6 4134 3D8C 104B 2B14 6DC3 F9C3 9DC0 B969 8544 1035 uid [ultimate] Ben Ramsey <ramsey@php.net> 1036 sub rsa4096 2021-04-26 [E] [expires: 2025-11-24] 1037 ``` 1038 1039 Have one or more of the other RMs [sign your GPG key][], and publish your 1040 public key to a keyserver: 1041 1042 ```shell 1043 gpg --keyserver keys.openpgp.org --send-keys YOURKEYID 1044 gpg --keyserver keyserver.ubuntu.com --send-keys YOURKEYID 1045 ``` 1046 1047 Add your public key to `php-keyring.gpg` in `web-php-distributions`. To do 1048 this, you will need to import all keys from the current PHP keyring file to 1049 your local GPG keyring. You will need to take note of the key IDs for each of 1050 the release managers listed in `php-keyring.gpg`. Then, you will export, 1051 specifying your key ID in addition to the key IDs of every other release 1052 manager. Save this export back to `php-keyring.gpg`, commit the changes, 1053 and push. 1054 1055 ```shell 1056 cd /path/to/repos/php/web-php-distributions 1057 gpg php-keyring.gpg # lists all keys in the keyring 1058 gpg --import php-keyring.gpg # imports all keys to your local keyring 1059 gpg --export \ 1060 --export-options export-minimal \ 1061 --armor \ 1062 YOURKEYID F9C39DC0B9698544 DBDB397470D12172 MORE RM KEY IDS ... \ 1063 > php-keyring.gpg 1064 gpg php-keyring.gpg # verify all the keys are present, including yours 1065 git add -p 1066 git commit --gpg-sign=YOURKEYID -m "Update PHP release manager keyring" 1067 git push 1068 ``` 1069 1070 `web-php-distributions` is a submodule of `web-php`. You'll now have to update 1071 the commit reference to reflect the change made in web-php-distributions. 1072 1073 ```shell 1074 cd /path/to/repos/php/web-php 1075 git submodule update 1076 cd distributions # This is the submodule referring to web-php-distributions 1077 git pull origin master 1078 cd .. 1079 git add distributions 1080 git commit --gpg-sign=YOURKEYID -m "Update php-keyring.gpg in distributions" 1081 git push 1082 ``` 1083 10845. Make sure you have the following repositories cloned locally: 1085 1086 * https://github.com/php/php-src 1087 * https://github.com/php/web-php 1088 * https://github.com/php/web-qa 1089 * https://github.com/php/web-php-distributions 1090 1091 1092[general availability]: https://en.wikipedia.org/wiki/Software_release_life_cycle#General_availability_(GA) 1093[muscle memory]: https://en.wikipedia.org/wiki/Muscle_memory 1094[Conditional Includes For Git Config]: https://motowilliams.com/2017-05-11-conditional-includes-for-git-config/ 1095[Update versions for PHP 8.1.0beta3]: https://github.com/php/php-src/commit/3edd1087c70bee2ec21f0fbec1a575d78a500f15 1096[Update versions for PHP 8.1.6RC1]: https://github.com/php/php-src/commit/40e8ced23898e3069340ca03ea5febc5361015ad 1097[Update NEWS for PHP 8.1.6RC1]: https://github.com/php/php-src/commit/a4fdeaebe419b88e3b4a1f5aba845c2d4e81fd4e 1098[Prepare for PHP 8.1.0RC1]: https://github.com/php/php-src/commit/5764414eb8900ae98020a3c20693f4fb793efa99 1099[Update NEWS for PHP 8.2.0 alpha2]: https://github.com/php/php-src/commit/418f7211f71658d79d934861be20f277db96fe2c 1100[Update NEWS for PHP 8.2.0RC6]: https://github.com/php/php-src/commit/4ccc414961a70200d638ca281a35f893226d74e2 1101[Bump for 8.1.8-dev]: https://github.com/php/php-src/commit/3b6ee1eb19c14c3339ebfcf5c967065a9f828971 1102[GitHub command line tool]: https://cli.github.com 1103[Announce 8.1.0RC3]: https://github.com/php/web-qa/commit/f264b711fd3827803b79bbb342959eae57ea502b 1104[8.1.6RC1]: https://github.com/php/web-qa/commit/e6d61ad7a9d8be0b1cd159af29f3b9cbdde33384 1105[merged upwards as usual]: https://wiki.php.net/vcs/gitworkflow 1106[Update versions for PHP 8.1.7]: https://github.com/php/php-src/commit/d35e577a1bd0b35b9386cea97cddc73fd98eed6d 1107[Update NEWS for PHP 8.1.7]: https://github.com/php/php-src/commit/b241f07f52ca9f87bf52be81817f475e6e727439 1108[Announce PHP 8.1.6]: https://github.com/php/web-php/commit/9f796a96c65f07e45845ec248933bfb0010b94a9 1109[PHP 8.1.6 released]: https://github.com/php/web-qa/commit/bff725f8373cf6fd9d97ba62a8517b19721a4c2e 1110[feature freeze]: https://en.wikipedia.org/wiki/Freeze_(software_engineering) 1111[Prepare for PHP 8.2]: https://github.com/php/php-src/commit/1c33ddb5e5598c5385c4c965992c6e031fd00dd6 1112[Prepare for PHP 8.2 (bis)]: https://github.com/php/php-src/commit/a93e12f8a6dfc23e334339317c97aa35356db821 1113[Add PHP-8.1 to the Git steps page]: https://github.com/php/web-php/commit/1fcd78c2817cf1fbf1a1de2ddec1350be4e26491 1114[Changes to the wiki]: https://wiki.php.net/vcs/gitworkflow?do=diff&rev2%5B0%5D=1617123194&rev2%5B1%5D=1654728193&difftype=sidebyside 1115[migration guide]: https://www.php.net/manual/en/migration81.php 1116[GPG key]: https://en.wikipedia.org/wiki/GNU_Privacy_Guard 1117[Generating a new GPG key]: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key 1118[sign your GPG key]: https://carouth.com/articles/signing-pgp-keys/ 1119[Send emails from a different address or alias]: https://support.google.com/mail/answer/22370?hl=en 1120[security-txt]: https://github.com/php/policies/blob/main/security-policies.rst#making-changes-to-securitytxt 1121