Repository navigation
CourseForge 4.7.0
A course can be published into more than one BookStack
A course used to have one destination. Choosing a second one meant a second course: the same outline, the same brief, the same pages generated and paid for twice, and two things to keep in step by hand for the rest of their lives.
Course → Publish → Destinations is now a list. Add as many BookStack instances as the course's profile defines — a staging wiki and a live one, the wikis of two departments, a customer's install and your own — each with its own shelf. Publish everything goes to all of them; each one also has a button of its own, for the wiki that was behind.
A destination has a switch, and it is the difference between pausing one and removing one. Off keeps everything already published there on record and simply leaves it out of the next push. Removing forgets the book, so publishing to that instance again later would create a second book beside the first — the dialog says so before it does it, and pointing a destination at a different instance costs the same thing and asks the same question.
Each destination holds its own book, and that is not a detail: the books have different ids and different slugs, and a page's cross references point inside the wiki it is in, so the same page is written slightly differently into each. A push knows what it last sent to each wiki separately, so the wiki that was already current is skipped there and rewritten here, and nothing is ever duplicated anywhere.
A wiki that is down does not stop the others — its failure is named in the log, the rest still go out, and only a push where every destination failed is an error.
The counts fold across the destinations that are on, which is what makes them worth reading: published means published in every one of them, out of sync means at least one would be written to. Add a second destination to a finished course and the whole course lights up as work outstanding, because it is.
Over MCP
set_publish_targets writes the list, get_publish_status reports every destination with the book it holds and how much of the course is in it, and publish_course takes an instances list to push to some of them. update_course's bookstack_instance still works and still means what it meant in 4.6 — it replaces the course's first destination, so a client that switches from one wiki to another does not quietly end up publishing to both.
Upgrading
Nothing to do, and nothing is republished. Schema version 8 turns the destination each course already has into the first entry of its list, carrying its book, its shelf and its fingerprints, so the first push after the upgrade sends exactly what it would have sent before. The columns that destination used to live in are still written, as a copy of the first entry, so a rollback to 4.6 finds its book where it left it.
Fixes
Found by an adversarial review of this change:
- A refused save of the destinations list re-seeded the form from the server, throwing away the edit the person was being asked to correct — and the list stayed marked unsaved after a successful save, which left every button that waits for a saved list disabled.
- Switching a row's instance kept the previous wiki's shelf and name, and would have forgotten its book with no dialog at all.
update_coursetook a shelf for a course with no destination to put it on, wrote nothing, and reported it as changed.- A push naming only malformed target ids fanned out to every destination instead of failing;
PUT projects/{id}/targetsread a missing field as an empty list and deleted every destination. - The destinations list could not be saved at all once the profile stopped defining one of the instances it already published to.
- Clearing
bs_instance_iddeleted the destination and the record of its book. In 4.6 it was a pause, so it is now refused with the reason. - A paused destination reported zero pages published however many it held, and
get_publish_statuscounted a page published to one wiki of two as never published. publish_itemshad no index for its three cascades, so every deleted page scanned the table for the whole installation.
323 tests pass.