- build runs go build under a spinner on a terminal and ends with 'Built bin/<name> in <time>'; make:* print 'Created <path>' per file - make:*, plugin:add, new, parity:*, docs:build, docs:sync and every delegate get long help and examples; delegates note that global options pass through to the application binary - make:* failures (no summer.yaml, invalid plugin ID or name, existing artifact, unknown plugin) explain themselves and suggest a command - docs:build and docs:sync return bonfire.Reported after the problem list - TestCommandsDocumented covers the tool commands too - docs: Upgrading to 0.4, delegates and global options, make: results and hints, the checklist for a finished command
13 KiB
title, description, section, order
| title | description | section | order |
|---|---|---|---|
| Upgrading | Move an application to a newer framework release, what the version numbers promise, and what to check before you take 0.2 and 0.4. | setup | 60 |
Upgrading
An application created by summer new builds against a framework checkout next to it; the update script moves that checkout to the newest release tag, reinstalls the summer tool and rebuilds the application (see Updating an application). An application or plugin that requires a tagged framework version in its go.mod moves with the go command instead:
go get git.golem15.com/golem15/summercms@v0.2.0
go mod tidy
Then rebuild, run migrate with the new binary and restart it.
Version numbers
SummerCMS is in the 0.x series, and the version tells you whether to read before you upgrade:
- The minor version (0.1 to 0.2) goes up when an upgrade can refuse a configuration that the previous release accepted, or changes a documented behaviour. Read the section for that version below before you deploy it.
- A patch version (0.2.0 to 0.2.1) is safe to take without reading: it fixes bugs and adds features, and an application that started on the previous patch starts on it too.
Applications pin exact versions, so a new release never reaches an application until it moves its go.mod or its checkout.
Upgrading to 0.4
0.4 rebuilds the console: Artisan-style list and help with examples, global options on every command, a logging pipeline with daily files, startup summaries and shutdown reports. Plugins compile unchanged. After you move the framework version, run summer build to regenerate main.go: the new generated main sets up logging before the configuration is read, parses the global options and returns the exit codes below. Then run bin/<app> list once with the new binary: it boots every plugin and runs the checks below.
Boot refusals
Duplicate command names. Two commands with the same name, from two plugins or from a plugin and the framework, stop the binary at start-up with bonfire.ErrDuplicateCommand naming the command. Remove or rename one of them; a plugin that appends centrifugo.Commands or flare.Commands must be the only one that does.
Reserved flag names. A command flag named like a global option (verbose, quiet, ansi, no-ansi, no-interaction, env, or the shorthands v, q, n) stops the binary with bonfire.ErrReservedFlag. Rename the flag.
Behaviour changes
- Daily log files. Logs go to the console and, from warnings up, to
storage/logs/summer-YYYY-MM-DD.log, kept for 14 days. The directory must be writable by the user that runs the binary; when it is not, the binary logs one warning and keeps logging to the console. To keep the old console-only behaviour, setlog.defaulttoconsole(SUMMER_LOG__DEFAULT=console). See Logging. - Component loggers. Every log record carries a
componentattribute. GORM's lines move to componentdband record-not-found is no longer logged; River's lines to componentriver(warnings and up by default). Raise or lower a component withlog.components, for examplecomponents: {db: debug}. - The request log is on by default. Every request writes one Info record
http requestfrom componenthttpwith the route pattern (never the path), status, duration andrequest_id. Silence it withcomponents: {http: warn}inconfig/log.yaml, or turn it off withhttp.access_log: false. serveprints a startup summary. On a terminal it is a block; off a terminalserveprints nothing on stdout and logs astartup summaryrecord and alistening on <addr>record on stderr instead, so a script that waits forlistening on 127.0.0.1:<port>in the combined output still finds it. Ctrl+C prints a shutdown report and exits 0; a failed drain exits 1.queue:workandschedule:rundo the same.- Exit codes. A failed command exits 1 and a usage error (an unknown command or flag, a wrong number of arguments) exits 2. Errors print as a block on stderr with a hint where the framework knows the fix, and
-vshows the wrapped errors. -qkeeps data.-qhides information and success lines, spinners and progress bars, but still prints what a command exists to produce: the token ofadmin:token:create, the key ofkey:generateand every--jsonoutput.- Production confirmation.
migrate,migrate:rollback,deferred:purgeandqueue:clearask before they run when the environment isproductionand they run on an interactive terminal;--forceskips the question. Off a terminal, as in deploy scripts over SSH, nothing changes. summer devrunsserve. It used to start the binary without a command, which printed the help and stopped; it now runsbin/<app> servewith the global options you givesummer dev.- Result lines.
summer buildends withBuilt bin/<app> in <time>, themake:commands printCreated <path>per file,migrateprintsApplied N migrationsorNothing to migrate, andqueue:clearprintsCleared N jobs from <queue>. Adjust scripts that matched the old lower-case lines.
Upgrading to 0.2
0.2 tightens two configuration checks so that settings which leaked credentials stop the start-up instead. Most applications are not affected: the first concerns applications that load an auth.cookie block, the second applications that send credentialed CORS answers. Start the new binary once in each environment before you switch traffic to it; a refused configuration fails serve at start-up with an error that names the key.
Boot refusals
A token cookie that is not Secure in production. In the production environment, bouncer.LoadCookieConfig refuses a token cookie whose Secure attribute resolves to false. That covers auth.cookie.secure: false and, since 0.2, an unset auth.cookie.secure with an http or empty app.url, from which the cookie inherited Secure=false before. The error names auth.cookie.secure and app.url.
It affects applications whose plugins load an auth.cookie block for a browser frontend (the cookie transport). To fix it, set app.url to the application's public https URL, or set auth.cookie.secure: true explicitly. See Cookie transport.
Credentialed CORS with a wildcard host or an unanchored pattern. With supports_credentials: true, globally under http.cors or in any profile under http.cors_profiles.<name>, these entries now fail the start-up, and the error names the key with its index, such as http.cors.allowed_origins[1] or http.cors_profiles.spa.allowed_origins_patterns[0]:
- an
allowed_originsentry with a*that is not the whole leftmost host label after a literal scheme, such ashttps://*,*://*,https://*example.comorhttp*://www.example.com(https://*.example.comstays valid); - an
allowed_origins_patternsentry not anchored with^and$, in every alternative of the expression; - any origin rule that matches an origin outside the configured domains, such as
https://*.comor^https?://.*$.
It affects applications that send credentialed CORS answers, to a browser frontend on another origin that calls the API with cookies. To fix it, list the frontend's exact origins, or write anchored patterns such as ^https://[a-z]+\.example\.com$. Without credentials these entries load as before. See CORS and CORS profiles.
Behaviour changes
These need no configuration change, but a test or an operator may notice them:
- Site-cache purges are queued. After an admin save commits, the purge request to the site is queued and sent by a background worker, with at most one request in flight per purger; saves committed meanwhile collapse into one follow-up request. The save no longer waits for the site. A test that asserts a purge calls
cooler.SiteCachePurger.Waitfirst, andservedrains the queue on shutdown. See Site cache purge. - Protected uploads need a private bucket. While
storage.uploads.public_urlis set,attach.Storerefuses a protected (is_publicfalse) upload withattach.ErrProtectedNeedsPrivateBucketbefore it writes anything, andservelogs one warning at start-up that the bucket must hold public files only. Keep protected relations on a bucket withoutpublic_url, or make the relation public. See Public URL base. - The Journal plugin's purge keys are deprecated.
golem15.journal.site_cache.purge_urlandgolem15.journal.site_cache.purge_tokenstill work as aliases of the framework'ssite_cache.purge_urlandsite_cache.purge_token, which win when both are set; the plugin logs a deprecation warning. Move the values to thesite_cachekeys. - Cookie defaults. A
bouncer.CookieConfigbuilt by hand with every field zero writesSameSite=LaxandSecure; a config with any field set keeps its ownSecurevalue. - The API documentation page at
/api-docsruns only scripts that carry the page's per-request nonce. See API documentation page. - Turnstile without a secret. When
turnstile.secretis empty and routes nameturnstile:openorturnstile:closed, the start-up logs one warning with the number of such routes. See Turnstile. - CORS profile headers on every answer. A route that names
cors:<profile>carries the profile's headers on every response, including refusals from guards, throttle, Turnstile and the body limit, and recovered panics.
What 0.2 adds since 0.1
The 0.1 series grew through many patch releases. These are the larger features that arrived after its first public releases, with the page that documents each:
- Caching with memory and Redis drivers, and a Redis store that shares
throttlecounters between instances: Caching, Rate limiting. - The site-cache purge after admin saves, including reorder saves through
pact.ReorderAfterSave: Site cache purge. - Token cookies with ready-made refresh and logout handlers, and Turnstile bot protection: Cookie transport, Turnstile.
- Credentialed CORS, per-route CORS profiles (
cors:<profile>) and the opt-in API documentation page: CORS, CORS profiles, API documentation page. - Go build tags in
summer.yaml(build.tags), S3 uploads buckets behind thesummercms_s3tag and a public URL base for a bucket or CDN: The summer.yaml manifest, S3 and S3-compatible buckets, Public URL base. - Serving uploads from the application and a per-request access log: Serving files, Request log.
- Plugin-provided admin field types: Plugin field types.
- Rich text, repeater, money, password and taglist fields, and dependent dropdowns: Rich text, Repeater, Money, Form-only fields, Taglist, Dependent dropdowns.
- Record reordering as a tree or a flat list: Tree reorder, Flat reorder.
- Singleton controllers, record actions and write-only settings secrets: Singleton controllers, Record actions, Write-only secrets.
- Personal API tokens for administrators and the
admin:token:*commands: API tokens, Admin accounts. - Menu item types that content plugins register for menus and sitemaps: Menu item types.
- New framework modules: cooler (caches, shared counters and the site-cache purge), seaglass (the rich text sanitizer), sieve (collection helpers) and signpost (the menu item type registry).