[{"author":"lrivallain","date":"2026-08-18T07:43:49+00:00","message":"Answer conditional requests on the RSS feeds (#34)\n\nA subscribed reader polls the same feed URL every few minutes, forever, and\nthe answer only changes when a new commit lands. Every poll was rebuilding\nand resending an identical document.\n\nThe feeds now carry an ETag, a Last-Modified date and a Cache-Control header,\nand the view answers a matching If-None-Match or If-Modified-Since with an\nempty 304.\n\nFor the ETag to be stable between polls the body has to be reproducible, so\nthe rendering became a pure function of its arguments: feeds no longer reads\nthe Flask request context, and the view passes the feed and logo URLs in.\nThat also makes the serialized body cacheable, keyed on the commits it\npublishes, which removes the repeated rebuild.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: e6778dd0-0b33-4f13-b014-53a54aae7627","sha":"f2d1e69cd25cf60f4c03af4df53fccc8a00c2a13","url":"https://github.com/lrivallain/azure_docs_watcher/commit/f2d1e69cd25cf60f4c03af4df53fccc8a00c2a13"},{"author":"lrivallain","date":"2026-08-18T07:14:17+00:00","message":"Human shrink","sha":"16a6f497a5b0331ae4b05eb1fe8fc32c206c792d","url":"https://github.com/lrivallain/azure_docs_watcher/commit/16a6f497a5b0331ae4b05eb1fe8fc32c206c792d"},{"author":"lrivallain","date":"2026-08-18T07:07:36+00:00","message":"Merge pull request #33 from lrivallain/lrivallain-readme-repo-cleanup\n\nTrim the README and changelog, and remove dead files","sha":"b6b09ebd7cc49970c7a675f253a238b580349789","url":"https://github.com/lrivallain/azure_docs_watcher/commit/b6b09ebd7cc49970c7a675f253a238b580349789"},{"author":"lrivallain","date":"2026-08-18T07:05:33+00:00","message":"Tighten the changelog to what a reader needs\n\nThe 2.0.0 entry recorded how each change was implemented as much as what\nchanged: the Bootstrap `!important` cascade behind the card shadows, the\nrecipe for the table row halo, the shared template macro behind the icons.\nThat reasoning already lives where it is actionable, in the comments of\nstatic/app.css and templates/_macros.html, so the entry now records the\nuser-visible outcome instead. Where a fact was a bug report in disguise it\nwas moved to Fixed: repository cards showed no hover highlight and commit\ncards showed two.\n\nThe ad-hoc \"Removed the need for any GitHub credential\" heading became a\nlead paragraph over the standard Removed, Breaking changes, Added, Fixed and\nChanged sections, which the rest of the file already used.\n\nEvery identifier, environment variable and issue number in the entry was\nchecked to still be there afterwards.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 8d82c73e-0c71-4c9c-8543-aeaff2ecc8bf","sha":"f1c7e1ab62ac5d2221b475ad321f1ad548e477b1","url":"https://github.com/lrivallain/azure_docs_watcher/commit/f1c7e1ab62ac5d2221b475ad321f1ad548e477b1"},{"author":"lrivallain","date":"2026-08-18T07:00:46+00:00","message":"Trim the README and remove the cookiecutter and history leftovers\n\nThe README documented how the application got here rather than what it is:\nthe rationale for dropping the access token, the \"not a regression\" note on\nthe 20 commit cap, and the issue numbers behind each feature. It also inlined\nthe twenty watched repositories, which config.py and the home page already\nown. It is now 90 lines describing the current state, with the history left\nto HISTORY.md.\n\nThe same pass removed what no longer carries its weight:\n\n* utils.py held a single function resolving a repository against the list in\n  config.py, so it moved next to that list.\n* GITHUB_WEB_BASE and GITHUB_API_BASE were undocumented env overrides nobody\n  set, tests included; they are plain constants again.\n* python-dotenv only serves `flask run`, so it is a dev dependency now. The\n  production install was verified to still import the app without it.\n* pyproject.toml ignored SLF001 for tests, a rule the select list never\n  enabled.\n* AUTHORS.md (\"Contributors: None yet\"), an unreferenced favicon.png and a\n  committed .impeccable tool cache pointing at another worktree are gone, and\n  .gitignore dropped the Django, Scrapy, SageMath and Jupyter blocks while\n  gaining the .ruff_cache it was missing.\n* CONTRIBUTING.md repeated a line verbatim, installed the wrong requirements\n  file and pinned a single Python version the CI matrix disagreed with.\n\nHISTORY.md dated releases 1.0.0 to 1.3.0 in 2021, but the repository has no\ncommit that year: they all shipped in November 2022, which is also why 0.1.0\nappeared to postdate them.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 8d82c73e-0c71-4c9c-8543-aeaff2ecc8bf","sha":"261030460c46332e373cc69cd9d9a28a345b49f7","url":"https://github.com/lrivallain/azure_docs_watcher/commit/261030460c46332e373cc69cd9d9a28a345b49f7"},{"author":"lrivallain","date":"2026-08-18T06:48:09+00:00","message":"Merge pull request #32 from lrivallain/fix-python-310-runtime\n\nFix 500 on all commit views: datetime.UTC needs Python 3.11","sha":"508acb9c9c7e4222cb30c12c7a96e5e7bfb4f251","url":"https://github.com/lrivallain/azure_docs_watcher/commit/508acb9c9c7e4222cb30c12c7a96e5e7bfb4f251"},{"author":"lrivallain","date":"2026-08-18T06:41:16+00:00","message":"Fix the 500 on every commit view and pin the runtime contract\n\n`datetime.UTC` is an alias introduced in Python 3.11. The Azure App Service\nruns Python 3.10, so parsing a commit date raised\n\n    AttributeError: module 'datetime' has no attribute 'UTC'\n\non every request that listed commits. Pages that do not parse a date, the home\npage and the section index, kept working, which is why the failure looked like\nit was limited to one repository.\n\nThe alias was not written by hand: ruff's UP017 rewrote the portable\n`datetime.timezone.utc` into it, because `target-version` claimed 3.13 while\nproduction had 3.10. The CI installed 3.13 too, so nothing ever exercised the\nruntime that actually serves the application.\n\nThree changes, so this class of failure cannot come back:\n\n* the portable `datetime.timezone.utc` spelling is used again, which runs on\n  both versions and makes the runtime bump safe to land in either order;\n* the tests run on the deployed runtime as well as the target one, and UP017 is\n  disabled until the App Service has been bumped;\n* the README documents that the App Service runtime, the CI matrix and the\n  linter target have to be kept in step, with the command to raise the runtime.\n\nVerified on a real 3.10 interpreter: the reported URL and every other commit\nview answer 200, the suite passes on 3.10 and 3.13, and reintroducing the alias\nfails 17 tests on 3.10.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"7d42b7111301aefda42ca2df1c18e4d7f295d00d","url":"https://github.com/lrivallain/azure_docs_watcher/commit/7d42b7111301aefda42ca2df1c18e4d7f295d00d"},{"author":"lrivallain","date":"2026-08-17T15:14:57+00:00","message":"Merge pull request #30 from lrivallain/lrivallain-urban-waddle\n\nRun without any GitHub credential, and modernize the app","sha":"a31f721b3ec8865a672660d2a46aa70e02281c35","url":"https://github.com/lrivallain/azure_docs_watcher/commit/a31f721b3ec8865a672660d2a46aa70e02281c35"},{"author":"lrivallain","date":"2026-08-17T15:06:14+00:00","message":"Reuse the table rows for the section index\n\nThe section index was a Bootstrap table while the two other lists had become\ncard rows, so the three lists of the application no longer looked related. It\nnow uses the same rows, frame, density and hover halo.\n\nA grid of sections would carry no information, so that page forces the table\nlayout instead of offering the switch. Forcing happens in the same pre-paint\nscript that applies the colour theme, and deliberately does not write to local\nstorage: the layout chosen on the other pages is left untouched.\n\nMeasured on the three pages with the same stored preference: identical row\nheight, hover shadow, border and background.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"eb0ea751168a61c2d8b29e8698c309e08d60b9d8","url":"https://github.com/lrivallain/azure_docs_watcher/commit/eb0ea751168a61c2d8b29e8698c309e08d60b9d8"},{"author":"lrivallain","date":"2026-08-17T14:57:39+00:00","message":"Align the layout switch with the title on both pages\n\nThe switch sat on the commit count line, while the home page put it in the\nheader. Measuring both showed the home one was not where it looked either: its\nrow allowed wrapping, so the long introduction pushed the switch onto a line of\nits own, left aligned under the text.\n\nBoth pages now place it at the top right of the header, on the title line, and\nit no longer shrinks when the viewport gets narrow.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"8e78f479d1561b446570a49cc0b5c1eefa8fbf56","url":"https://github.com/lrivallain/azure_docs_watcher/commit/8e78f479d1561b446570a49cc0b5c1eefa8fbf56"},{"author":"lrivallain","date":"2026-08-17T14:51:39+00:00","message":"Give the hovered row the halo of the grid cards\n\nThe underline was a flat solid line while the grid cards highlight themselves\nwith a coloured edge topped by a translucent band. The row now reuses that\nrecipe on its bottom edge: the accent colour on the divider itself, plus the\nsame 0.2rem band at the same opacity.\n\nThe last row used to drop its divider entirely, which would have made its\nunderline sit one pixel lower than the others. It now keeps a transparent one,\nso every row highlights identically and the height does not change on hover.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"484cb14c2a6b049723159df4cd5a14ffc907395e","url":"https://github.com/lrivallain/azure_docs_watcher/commit/484cb14c2a6b049723159df4cd5a14ffc907395e"},{"author":"lrivallain","date":"2026-08-17T14:49:15+00:00","message":"Stop Bootstrap utilities from swallowing the card hover styles\n\nThe repository cards carried .shadow-sm, which Bootstrap declares !important.\nIt therefore won over every box-shadow of our own: the hovered row of the table\nview showed no underline, and the hover ring of the grid view never appeared\neither. Commit cards, which carry no such utility, showed both, hence the\ninconsistency between the two pages.\n\nThe drop shadow now lives in the stylesheet, like the icon padding that hit the\nsame problem with .p-3, so that the view specific rules can override it.\n\nMeasured on both pages and both layouts: the grid hover ring and the table\nunderline are now identical everywhere.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"fae0312c2cc6f61c79704f7a4f5a605246165cb2","url":"https://github.com/lrivallain/azure_docs_watcher/commit/fae0312c2cc6f61c79704f7a4f5a605246165cb2"},{"author":"lrivallain","date":"2026-08-17T14:45:33+00:00","message":"Add tooltips on every button and underline the hovered table row\n\nTooltips are initialised once for every link and button carrying a title,\nrather than by tagging each element, so new markup gets one for free. Elements\nalready driving another behaviour through data-bs-toggle, the navbar collapse,\nare skipped.\n\nAuditing the rendered pages showed two buttons had no title at all and would\ntherefore have stayed silent: \"Browse sections\" on the home page and \"View\" on\nthe commit list. Both now describe their target.\n\nIn the table view the row under the pointer gets the accent colour as an inset\nunderline and a background tint, which replaces the card ring that did not suit\na table. The underline is drawn as an inset shadow so the row does not shift.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"6c06660b64ae15f79cbcbc720d0d0479430bc3d3","url":"https://github.com/lrivallain/azure_docs_watcher/commit/6c06660b64ae15f79cbcbc720d0d0479430bc3d3"},{"author":"lrivallain","date":"2026-08-17T14:41:03+00:00","message":"Offer a grid or a dense table layout, remembered across visits\n\nBoth the repository list and the commit list can now be shown as a grid of\ncards or as a table. The preference is stored in local storage, shared by the\ntwo pages, and applied before the first paint like the colour theme, so the\nlayout does not flicker on load.\n\nThe table view is a real table rather than spaced out cards: the collection\nbecomes the frame, the cards become flush rows separated by a single divider,\ncard caps lose their background, padding is tightened and the sha and date are\nkept on one line. Rows are 38px instead of 60px, which shows 17 repositories on\na first screen where the grid showed 7.\n\nTwo layout bugs surfaced while measuring this:\n\n* A single 78 line merge message stretched its whole row to 2883px, because the\n  cards use h-100. Commit messages are now clamped, to eight lines in the grid\n  and one in the table, with the full text kept in a title attribute.\n* The repository icon padding came from Bootstrap's p-3 utility, which is\n  !important and silently won over the table rules. It now lives in the\n  stylesheet so the table view can tighten it.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"a300d1740fc82d495608341375d3218d2249a347","url":"https://github.com/lrivallain/azure_docs_watcher/commit/a300d1740fc82d495608341375d3218d2249a347"},{"author":"lrivallain","date":"2026-08-17T14:26:59+00:00","message":"Order the watched repositories by importance\n\nThe home page follows the declaration order, which was historical rather than\nuseful. Repositories are now grouped from the most broadly useful to the most\nspecialised: core platform, AI and data, identity and security, guidance,\ndeveloper tooling, then endpoint, hybrid and edge. The project's own repository\ncomes last. A comment records that the declaration order is what drives the\npage, so it is not lost the next time an entry is added.\n\nAlso drops the \"(preview)\" suffix from Azure Quantum, which is generally\navailable.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"8adcbd038d5b438b7d240c3293558ee0da99e04a","url":"https://github.com/lrivallain/azure_docs_watcher/commit/8adcbd038d5b438b7d240c3293558ee0da99e04a"},{"author":"lrivallain","date":"2026-08-17T14:22:02+00:00","message":"Pre-configure the repositories azure-docs was split into\n\nMicrosoft has been carving MicrosoftDocs/azure-docs into per-domain\nrepositories. Virtual machines, AKS, Cosmos DB, Monitor, AI services, machine\nlearning and Defender for Cloud are no longer in it, so the curated list had\nquietly lost most of the services it advertises. This follows that content to\nits new homes and adds the guidance repositories alongside it.\n\nTheir default branches are not uniform, which the branch autodiscovery already\nhandles: defender-docs publishes from `public`, sql-docs from `live`.\n\nRepositories with no product icon now render a Bootstrap glyph through a shared\nmacro, which also fixes an unguarded <img> on the home page that would have\nrendered a broken image for any entry without one. Section listings drop the dot\nand underscore prefixed tooling folders, which are not documentation.\n\nEvery configured repository was verified end to end: index page, first section\nand its RSS feed.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"f2c087c938251eb7d8c2a7ce6d6eb231209d29da","url":"https://github.com/lrivallain/azure_docs_watcher/commit/f2c087c938251eb7d8c2a7ce6d6eb231209d29da"},{"author":"lrivallain","date":"2026-08-17T14:10:18+00:00","message":"Simplify the configuration and polish the commit list\n\nAZDOCSWATCH_MAX_COMMITS could only lower a count that GitHub already fixes at\nthe feed size, so it was a knob that could never help. The remaining constant is\nno longer configurable and only tells visitors when a listing is capped, hence\nits rename to ATOM_FEED_SIZE.\n\nAlso renames the header \"About\" entry to \"GitHub\", which is what it links to,\nand highlights a commit card with a coloured border when it is pointed at or\nkeyboard focused. The rule lives in a static stylesheet rather than inline, and\nis disabled under prefers-reduced-motion.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"254dccc51830cdec05107371f997e7ff25bf1bf0","url":"https://github.com/lrivallain/azure_docs_watcher/commit/254dccc51830cdec05107371f997e7ff25bf1bf0"},{"author":"lrivallain","date":"2026-08-17T14:06:19+00:00","message":"Always show the 20 most recent commits instead of a look-back window\n\nGitHub caps commit feeds at 20 non paginated entries with no date filter, so a\nlook-back window could only ever hide results that had already been fetched.\n\nIt also made quiet sections useless: a section whose last change is older than\nthe window reported no activity at all, when what a reader wants to know is\nprecisely when it last changed. `articles/aks` for instance now shows its real\nhistory from 2024 rather than \"No commit in the last 5 days\".\n\nRemoves the \"Look back over\" control, the `since` parameter and the\n`AZDOCSWATCH_SINCE` and `AZDOCSWATCH_MAX_SINCE` settings. Existing links and\nfeed subscriptions carrying `?since=` keep working, the parameter is ignored.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"02a7cdcc8e1b9c94b9996cb85e6f5ae19bbf0d5d","url":"https://github.com/lrivallain/azure_docs_watcher/commit/02a7cdcc8e1b9c94b9996cb85e6f5ae19bbf0d5d"},{"author":"lrivallain","date":"2026-08-17T14:02:49+00:00","message":"Do not let low level I/O failures escape as unhandled errors\n\nrequests.exceptions.RequestException derives from OSError, so catching OSError\ncovers both the request level failures and the lower level ones that were\nescaping, such as an unusable TLS CA bundle. Those surfaced as a bare 500\ninstead of the error page, with no indication of the cause.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"1a515a917a72c1a3293b05117484807cbf88ebe7","url":"https://github.com/lrivallain/azure_docs_watcher/commit/1a515a917a72c1a3293b05117484807cbf88ebe7"},{"author":"lrivallain","date":"2026-08-17T14:00:01+00:00","message":"Drop the GitHub credential requirement and modernize the app\n\nThe shared GITHUB_ACCESS_TOKEN had become a recurring chore: organizations can\ncap personal access token lifetimes to a few days, so the deployment depended on\na manual renewal.\n\nCommits are now read from the public Atom feeds published by the GitHub web\nfront-end, which need no credential and consume no REST API rate limit. The\ndefault branch is discovered from the branch-less feed title, which is required\nbecause repositories disagree on it (sql-docs uses `live`). The only remaining\nREST call is the directory listing, performed anonymously and cached.\n\nThe oAuth login was removed with it: it only existed to raise limits that no\nlonger apply, and it was the sole source of the SAML enforcement problem (#10).\nThe `since` control is now available to everyone.\n\nKnown limitation: GitHub serves commit feeds as a single, non paginated page of\n20 entries, so a section can never show more than 20 commits. The previous\nimplementation was capped at 20 too, so this is not a regression.\n\nAlso fixed along the way:\n* RSS entries were published oldest first, and the channel link pointed at the\n  feed instead of the HTML page.\n* The RSS author was an email field holding a display name; it is now dc:creator.\n* Commit messages were HTML escaped before being XML escaped, producing double\n  escaped entities in the feeds.\n* A NameError was raised instead of the intended error page on GitHub failures.\n* The Flask secret key was regenerated on every start, breaking sessions across\n  restarts and workers.\n* The page language was declared as French while the interface is English.\n\nModernization:\n* Bootstrap 5.3 native colour modes replace the abandoned bootstrap-dark-5 fork;\n  jQuery and js-cookie are gone and CDN assets are pinned with SRI.\n* Pages advertise their RSS feed through autodiscovery links.\n* PyGithub, flask_dance, authlib and Flask-Login dropped; dependencies pinned.\n* Added an offline test suite, ruff linting and formatting, and a CI workflow\n  that lints and tests before deploying. The previous workflow relied on the\n  retired v2 artifact actions and could no longer run.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 372234e2-8676-4a29-8c30-4e689a0a406a","sha":"e8828a047fd3c55321aad56b6afff1e5ab2734a7","url":"https://github.com/lrivallain/azure_docs_watcher/commit/e8828a047fd3c55321aad56b6afff1e5ab2734a7"}]
