204 lines
10 KiB
Markdown
204 lines
10 KiB
Markdown
# Runbook: Laravel 12 preparation steps, for every installation
|
|
|
|
Laravel 12 needs a few package changes that already work on Laravel 11. They reach `main` one step at a time, and every
|
|
installation (Timebank.cc, Uuro) takes them with its normal deploy. This runbook is the checklist per step: what changes,
|
|
how to deploy it, what to check afterwards and how to go back. Background: Phase 1 of
|
|
[plans/LARAVEL_UPGRADE_PLAN.md](plans/LARAVEL_UPGRADE_PLAN.md).
|
|
|
|
| | |
|
|
|---|---|
|
|
| From | Laravel 11.57 on `main` (every installation, since the 10 to 11 upgrade) |
|
|
| To | still Laravel 11.57, with Carbon 3, flatpickr in the app, unused packages removed, PHPUnit 11, Fortify 1.41 |
|
|
| Tool | `./deploy.sh -e server`, once per step |
|
|
| Duration | a normal deploy per step, no maintenance window |
|
|
| Database | no migrations in any step |
|
|
| Rollback | code only, to the tag of the previous step (see [Rollback](#rollback)) |
|
|
|
|
Laravel 12 itself comes after all five steps, with `scripts/upgrade.sh` and a runbook of its own.
|
|
|
|
## The steps
|
|
|
|
Each step is a tag on `main`. Timebank.cc deploys a step first and watches its log for two or three days; then the next
|
|
step goes to `main`. Take the steps in order, and preferably one at a time. When your installation is several steps
|
|
behind, a deploy brings them all at once: that works, but do the checks of every step it brought.
|
|
|
|
| Tag | Step | What changes | Visible to members |
|
|
|---|---|---|---|
|
|
| `l12-prep-0-start` | starting point | `main` before the first step; the rollback target of step 1 | - |
|
|
| `l12-prep-1-carbon3` | Carbon 3 | date library 2 -> 3; durations and timestamps keep their old behaviour | no (dates must look the same) |
|
|
| `l12-prep-2-flatpickr` | flatpickr into the app | the date picker component moves into the app, package `asdh/laravel-flatpickr` removed | no |
|
|
| `l12-prep-3-cleanup` | package clean-up | unused `robsontenorio/mary` and `laradumps/laradumps` removed, `config/mary.php` deleted, `psr/simple-cache` 1 -> 3 | no |
|
|
| `l12-prep-4-phpunit` | PHPUnit 11 | test tools only (PHPUnit 11.5, Collision 8.9) | no |
|
|
| `l12-prep-5-qrcode` | QR codes, Fortify 1.41 | QR codes made by the app itself (bacon 3), `simplesoftwareio/simple-qrcode` removed, Fortify 1.21 -> 1.41 | no (QR codes look the same) |
|
|
|
|
Start every terminal session by setting the application root once (the server's own path):
|
|
|
|
```bash
|
|
export APP=/var/www/CHANGE-ME # the application root on this server
|
|
```
|
|
|
|
---
|
|
|
|
## Once: is the installation on `main`'s history?
|
|
|
|
`main` was rewritten once, after the 10 to 11 upgrade. An installation that was deployed in between sits on a commit
|
|
that is not on `main` any more, and a routine deploy would then merge two histories. Check it once, read-only:
|
|
|
|
```bash
|
|
( cd "$APP" && git fetch -q origin main \
|
|
&& echo "branch: $(git rev-parse --abbrev-ref HEAD) HEAD: $(git log -1 --format='%h %s')" \
|
|
&& if git merge-base --is-ancestor HEAD origin/main; then echo "OK: on main's history, nothing to do"; \
|
|
else echo "NOT on main's history. Code that differs from origin/main (expect nothing):"; \
|
|
git diff --stat HEAD origin/main -- app bootstrap/app.php config database lang resources routes composer.json composer.lock package.json; fi )
|
|
```
|
|
|
|
- **OK**: go on with the steps.
|
|
- **NOT on main's history** and no code differs: move the installation onto `main` without changing any code (this
|
|
changes the installation; the tag keeps the old position):
|
|
|
|
```bash
|
|
( set -e; cd "$APP"
|
|
git diff --name-only HEAD origin/main | xargs -r git -c core.fileMode=false status --porcelain -- | grep . \
|
|
&& { echo "Local changes on files that differ: stop and ask"; exit 1; } || true
|
|
git tag "pre-realign-$(date +%F)" HEAD
|
|
git -c core.fileMode=false checkout -B main origin/main
|
|
git branch -u origin/main main
|
|
git status -sb | head -1 )
|
|
```
|
|
|
|
The last line must show `## main...origin/main` without "ahead" or "behind".
|
|
- **NOT on main's history** and code differs: stop and ask; do not deploy.
|
|
|
|
---
|
|
|
|
## Every step
|
|
|
|
### 1. Before the deploy (read-only)
|
|
|
|
```bash
|
|
( cd "$APP"; git fetch -q origin main --tags
|
|
echo "now: $(git describe --tags --always HEAD)"
|
|
echo "main: $(git describe --tags --always origin/main)"
|
|
git merge-base --is-ancestor HEAD origin/main && echo "fast-forward: yes" || echo "fast-forward: NO"
|
|
echo "steps this deploy brings: $(git tag -l 'l12-prep-*' --merged origin/main --no-merged HEAD | tr '\n' ' ')"
|
|
php -v | head -1; df -h "$APP" | tail -1
|
|
echo "local changes:"; git -c core.fileMode=false status --porcelain | head )
|
|
```
|
|
|
|
- `fast-forward: yes` must be there (otherwise see the section above).
|
|
- PHP 8.2 or newer; a few hundred MB free.
|
|
- Local changes (the last lines) are the ones `deploy.sh` asks about; on a server they are usually build files.
|
|
|
|
### 2. Deploy
|
|
|
|
```bash
|
|
cd "$APP" && ./deploy.sh -e server
|
|
```
|
|
|
|
As root, the way you always deploy. It installs the changed packages with `composer install`, clears the caches and
|
|
restarts the queue workers.
|
|
|
|
### 3. Check (read-only)
|
|
|
|
```bash
|
|
( cd "$APP" && echo "now: $(git describe --tags --always HEAD)" \
|
|
&& sudo -u www-data php artisan upgrade:verify \
|
|
&& sudo -u www-data php artisan about --only=environment | head -12 )
|
|
```
|
|
|
|
- `upgrade:verify` ends without failures.
|
|
- Then the checks of the step(s) this deploy brought, below, in the browser.
|
|
|
|
### 4. The next days: watch the log (read-only)
|
|
|
|
```bash
|
|
( cd "$APP"; for d in $(seq 0 2); do f=storage/logs/laravel-$(date -d "-$d day" +%F).log; [ -f $f ] && echo "== $f: $(grep -c '\.ERROR' $f) errors" && grep '\.ERROR' $f | cut -c1-160 | sed -E 's/\[[^]]*\] //' | sort | uniq -c | sort -rn | head -5; done )
|
|
```
|
|
|
|
An error type you have not seen before the deploy deserves a look. Report it, with the step and the log lines.
|
|
|
|
---
|
|
|
|
## Checks per step
|
|
|
|
### Step 1: Carbon 3 (`l12-prep-1-carbon3`)
|
|
Carbon 3 counts differences between dates with a sign and with fractions, and reads timestamps as UTC. The code now asks
|
|
for the old behaviour everywhere; these checks confirm it.
|
|
- [ ] A post and a profile show the same date and time as before the deploy (not 1 or 2 hours off).
|
|
- [ ] Chat: "online" / "last seen" and the typing indicator behave as before.
|
|
- [ ] Log in, stay idle longer than the platform's inactivity logout: you are logged out as before.
|
|
- [ ] The next morning: no errors from the scheduled commands (inactive profiles, bounce processing, expired chat
|
|
messages) in the log.
|
|
|
|
### Step 2: flatpickr into the app (`l12-prep-2-flatpickr`)
|
|
The `<x-flatpickr>` component and its views move into the app (`app/View/Components/Flatpickr.php`,
|
|
`resources/views/flatpickr/`); the package is removed. No view that uses the picker changed.
|
|
- [ ] The date pickers open and fill in on: the transactions page (period filter), a post's start and end date in
|
|
Posts (admin), creating and editing a call, a mailing's send date (admin), the date of birth in the profile settings
|
|
and the statistics period (admin).
|
|
- [ ] A chosen date and time is saved as chosen (not shifted by the timezone).
|
|
- [ ] Only if your platform folder overrides the picker's views (`platform/views/vendor/flatpickr/`): check that your
|
|
override still applies, and tell us.
|
|
|
|
### Step 3: package clean-up (`l12-prep-3-cleanup`)
|
|
Nothing visible changes. Removed: Mary (with `config/mary.php`; nothing used it), laradumps (development only); the
|
|
`psr/simple-cache` requirement moves from 1 to 3.
|
|
- [ ] Home page, search, a profile and the chat open without errors.
|
|
- [ ] Icons look as before (they come from WireUI, not from Mary).
|
|
|
|
### Step 4: PHPUnit 11 (`l12-prep-4-phpunit`)
|
|
Test tools only. Nothing changes for visitors.
|
|
- [ ] `upgrade:verify` passes; nothing else to check.
|
|
|
|
### Step 5: QR codes and Fortify 1.41 (`l12-prep-5-qrcode`)
|
|
The QR codes are made by the app itself now (the package used before does not work with Laravel 12's Fortify). They
|
|
look the same. Fortify, the login package, goes from 1.21 to 1.41; it adds no routes or tables.
|
|
- [ ] Pay page: the QR code appears.
|
|
- [ ] A transaction and an account statement (PDF): the QR code appears and can be scanned.
|
|
- [ ] The PDF of a post (and of a call, if your platform has calls): QR code present.
|
|
- [ ] Log in and out, the password reset mail, and two-factor authentication: turning it on shows a QR code that an
|
|
authenticator app accepts, and logging in with a code works.
|
|
|
|
---
|
|
|
|
## Rollback
|
|
|
|
No step has migrations, so a rollback only puts the code back. Use it when a step breaks something for members and a fix
|
|
is not available soon. It changes the installation:
|
|
|
|
```bash
|
|
( set -e; cd "$APP"
|
|
PREV=l12-prep-CHANGE-ME # the tag of the step BEFORE the one you leave, e.g. l12-prep-1-carbon3
|
|
git fetch -q origin --tags
|
|
git -c core.fileMode=false checkout -B main "$PREV"
|
|
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-interaction --prefer-dist --optimize-autoloader
|
|
php artisan optimize:clear
|
|
git log -1 --format='now: %h %s' )
|
|
```
|
|
|
|
Then restart the queue workers and Reverb the way `deploy.sh` does on your server (the `timebank-*` services), and run
|
|
the check of step 3 above.
|
|
|
|
**After a rollback, do not deploy** until the fix is on `main`: a deploy pulls `main` and brings the step back. Report
|
|
what broke; the fix comes as a new commit on `main`, and the next deploy fast-forwards as usual.
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Cause and fix |
|
|
|---|---|
|
|
| `Class "...MaryServiceProvider" not found` (or another removed package) right after the deploy | A stale package cache. `cd "$APP" && rm -f bootstrap/cache/packages.php bootstrap/cache/services.php && composer dump-autoload && php artisan optimize:clear` |
|
|
| `deploy.sh` stops: "main moves Laravel from 11 to 12" | Not one of these steps: Laravel 12 itself has reached `main`. Use its runbook and `scripts/upgrade.sh`. |
|
|
| `git pull` in `deploy.sh` wants to merge, or "divergent branches" | The installation is not on `main`'s history: see the first section. |
|
|
| Dates 1-2 hours off after step 1 | Report it with the page and the expected time: a `createFromTimestamp()` call without the app timezone. |
|
|
| A date picker is missing or unstyled after step 2 | `php artisan view:clear`, then reload; if it stays, report the page. |
|
|
|
|
## Record
|
|
|
|
| Step | Installation | Deployed (date) | `upgrade:verify` | Checks | Log quiet after 2-3 days |
|
|
|---|---|---|---|---|---|
|
|
| 1 Carbon 3 | | | | | |
|
|
| 2 flatpickr | | | | | |
|
|
| 3 clean-up | | | | | |
|
|
| 4 PHPUnit 11 | | | | | |
|
|
| 5 QR codes | | | | | |
|