Skip to content

chore(sync): merge voc/main 2026-11-02 - #93

Open
andibraeu wants to merge 60 commits into
mainfrom
sync/voc-main-20261102
Open

andibraeu wants to merge 60 commits into
mainfrom
sync/voc-main-20261102

Conversation

@andibraeu

Copy link
Copy Markdown
Member

Summary

Weekly sync of voc/voctoweb main into freifunk/voctoweb.

Merge conflicts detected — resolve branding overlay files, then merge. Only conflicted tracked paths were staged.

Checklist

  • CI green ( workflow)
  • Branding overlay still correct (locales, footer, about, oembed, brand color)
  • Disabled VOC workflows still disabled (, , )
  • Smoke: home, search, about (after deploy)

dependabot Bot and others added 30 commits August 18, 2026 06:23
Bumps the gems group with 2 updates: [rbs](https://github.com/ruby/rbs) and [haml](https://github.com/haml/haml).


Updates `rbs` from 4.1.2 to 4.1.3
- [Release notes](https://github.com/ruby/rbs/releases)
- [Changelog](https://github.com/ruby/rbs/blob/master/CHANGELOG.md)
- [Commits](ruby/rbs@v4.1.2...v4.1.3)

Updates `haml` from 7.3.0 to 7.3.1
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](haml/haml@v7.3.0...v7.3.1)

---
updated-dependencies:
- dependency-name: rbs
  dependency-version: 4.1.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: gems
- dependency-name: haml
  dependency-version: 7.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump the gems group with 2 updates
Bumps the gems group with 1 update: [haml](https://github.com/haml/haml).


Updates `haml` from 7.3.1 to 7.4.1
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](haml/haml@v7.3.1...v7.4.1)

---
updated-dependencies:
- dependency-name: haml
  dependency-version: 7.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump haml from 7.3.1 to 7.4.1 in the gems group
Bumps the gems group with 2 updates: [rbs](https://github.com/ruby/rbs) and [haml](https://github.com/haml/haml).


Updates `rbs` from 4.1.3 to 4.2.0
- [Release notes](https://github.com/ruby/rbs/releases)
- [Changelog](https://github.com/ruby/rbs/blob/master/CHANGELOG.md)
- [Commits](ruby/rbs@v4.1.3...v4.2.0)

Updates `haml` from 7.4.1 to 7.5.0
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](haml/haml@v7.4.1...v7.5.0)

---
updated-dependencies:
- dependency-name: rbs
  dependency-version: 4.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: gems
- dependency-name: haml
  dependency-version: 7.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump the gems group with 2 updates
Add SlugType scalar (validates no forward slashes) and use it for
slug fields on Channel, Conference, and Movie types instead of plain String.
…urce types

Rename video_primary to video for cleaner API naming. Add field descriptions to video_preferred, video, videos, audios, slides, and mime_type fields.
Add `prefer` (VideoPreferenceEnum list) and `quality` (VideoQualityEnum) arguments
to the `video` field on LectureType, allowing clients to request a specific
container/codec (MP4, AV1, DASH, WebM) before falling back to the master recording.

Add VideoPreferenceEnum and VideoQualityEnum types. Cover all three format
variants with integration tests.
Exposes available translation languages for a lecture as ISO 639-2 encoded strings.
Add `promoted` connection field to QueryType returning promoted lectures for the start page. Supports `first`/`offset` pagination with a default limit of 10 and max page size of 30.

Add integration tests covering basic listing, limiting, and connection-style pagination.
Introduce Types::BaseConnection that suppresses the `edges` field,
exposing only `nodes` and `pageInfo` on all connection types. Keeps the
public API minimal and consistent with a nodes-first convention.

Remove the `edges` assertion from the promoted-lectures integration test
to match the new connection shape.
Add experimental `metadata_raw` and `streaming_raw` JSON fields to ConferenceType,
exposing the underlying database metadata and streaming v2 API data respectively.
Both fields are marked deprecated to signal their experimental status.
Expose structured image data on Conference via two new GraphQL fields:
- `logo(prefer: ImageMimeTypeEnum)` — returns logo as ImageType with optional MIME preference
- `images` — returns all conference images (logo, banners, variants) as [ImageType]

Deprecate scalar `logo_url` and `images_url` in favour of the new structured fields.

`Conference#images` aggregates logo and metadata-sourced images into a uniform list.
Both REST JSON views (public and API) now include the `images` array.
Add `item(by: {guid|slug})` query and `items` connection as generic
aliases for the lecture-named equivalents. Deprecate `lecture`,
`lecture_by_slug`, `lectures`, and `Conference.lectures` in favour of
the new names. Add `ItemLookupInput` for the oneOf-style lookup arg.
Update descriptions and README to use "item" terminology throughout.
Use `(metadata || {})` to avoid NoMethodError when metadata is nil.
Add test to cover nil metadata case.
…nd #remote_id

Same NoMethodError class as the Conference#images 500 fixed in 8e963d9:
`metadata['related']`/`metadata['remote_id']` crash when the jsonb
column is NULL (schema default doesn't apply retroactively, and the
column allows NULL). `lectures_related_to` in query_type.rb calls
related_events directly, so this was reachable from the public GraphQL
API.

Assisted-by: LLM
Resolves ambiguous gem spec warning during bundle install caused by
multiple psych versions satisfying rdoc's `>= 4.0.0` constraint.
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v5...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Add APP_REVISION constant via initializer (reads Capistrano's REVISION
file, falls back to `git rev-parse --short HEAD`, then 'dev'). Link it
in the footer pointing at the corresponding git commit.
dependabot Bot and others added 30 commits September 8, 2026 06:22
Bumps [actions/github-script](https://github.com/actions/github-script) from 8 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@v8...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…/github-script-9

chore(deps): bump actions/github-script from 8 to 9
Bump rails constraint to ~> 8.0 in Gemfile and relock dependencies, updating actionpack/activerecord/activesupport etc. to 8.1.3.1 and pulling in action_text-trix.
…ass via pnpm

Replaces sass-rails/coffee-rails/jquery-rails/turbolinks/bootstrap-sass/uglifier
with propshaft + jsbundling-rails (esbuild) + cssbundling-rails (sass), managed
via pnpm. Rails 8 dropped default Sprockets support in favor of this stack.

- JS: app/javascript/{application,oembed-player,active_admin}.js are the three
  esbuild entry points, mirroring the old Sprockets manifests file-for-file and
  in the same require order. Genuinely custom/vendored code (mediaelement +
  plugins, the in-house VOCPlayer/Clappr fork and its 2 plugins, timelens, the
  bxslider fork, purl, an old handlebars alpha) is kept byte-identical as local
  imports rather than swapped for fresh npm packages, to avoid version-drift
  risk on a live video site. jquery/jquery-ujs/turbolinks are pinned to the
  exact versions the old jquery-rails/turbolinks gems served. bootstrap-sass
  and @activeadmin/activeadmin are pinned to the exact gem versions they
  replace (3.4.1 and 3.5.2, matching exactly).
- clappr-thumbnails-plugin/clappr-playback-rate-plugin do `require("clappr")`
  in their UMD wrapper for a real Clappr peer that doesn't exist here (our
  Clappr global is the vendored VOCPlayer fork) - marked external so esbuild
  leaves the unreachable require() call alone instead of failing to resolve it.
- mejs-player.js: dropped the .erb extension and its 3 asset_path() calls
  (esbuild can't process ERB) in favor of reading SVG icon sprite paths off
  data-* attributes rendered onto <body> by the two frontend layouts.
- CSS: application.scss/embed.scss/active_admin.scss replace the Sprockets
  `*= require` manifests with plain @import chains. font-url()/image-url()/
  asset-url() (sass-rails-only Sass functions, unavailable in plain dart-sass)
  become plain url(...) - Propshaft rewrites those to fingerprinted paths
  itself as a post-processing step, so this is a lossless conversion.
- vendor/assets/mediaelement-plugins/ renamed to vendor/assets/player-plugins/:
  Propshaft::LoadPath#dedup does a naive string prefix check, and would
  otherwise silently drop this path as a false "duplicate" of the sibling
  vendor/assets/mediaelement path (mediaelement-plugins.start_with?(mediaelement)).
- Extra asset roots moved from config/initializers/assets.rb into
  config/application.rb: Propshaft snapshots config.assets.paths into its
  asset assembly before user initializers run, so paths added from an
  initializer were silently ignored.
- config/initializers/sass_skip.rb deleted: worked around a Sprockets+GraphiQL
  CSS-compression bug; Propshaft doesn't compress anything, so it's moot.
- production.rb's `config.assets.configure do |env| ... end` block called a
  Sprockets-only method that no longer exists on config.assets - would have
  crashed production boot outright. Removed along with config.assets.compile.

Verified: bin/rails test (0 failures, same pre-existing ES-connection errors
as before), assets:precompile, and manual requests against the homepage,
admin login, an event page, and its oembed page all render the correct
fingerprinted bundles with no server errors. Not verified in an actual
browser (no browser tool available this session) - JS runtime behavior of
the players themselves still needs a manual check.

Assisted-by: LLM
Two distinct bug classes surfaced after the asset-pipeline migration, both
because esbuild gives each file its own module scope instead of Sprockets'
old single-concatenated-script model:

1. Bare top-level `var`/`function` declarations used to leak onto `window`
   for free under Sprockets concatenation. Under esbuild they stay private
   to their module, breaking anything that referenced them as a global:
   - mirrorbrain-fix.js: `var MirrorbrainFix = {...}` -> `window.MirrorbrainFix`
   - vendor/timelens.js: bare `function timelens()` was never exposed
     alongside the `Timelens` class - broke every timelens widget
   - theme.js: `toggleTheme` is called from onclick="" in _navbar.haml,
     which runs in true global scope, not the bundle's module closure
   - mastodon-share.js: `mastodonShare` is called from a separate inline
     <script> block in _embedshare.haml, same issue

2. `window.jQuery = jquery` in application.js/oembed-player.js was a plain
   statement, not part of an import. Per ES module spec, ALL of a module's
   own imports evaluate fully (in declaration order) before ANY of its own
   top-level statements run - regardless of source order. So that assignment
   actually ran dead last, after bxslider/slider.js/bootstrap/jquery-ujs had
   already evaluated expecting a global jQuery to exist already. Fixed by
   extracting it into vendor/jquery-global.js and importing it first, so it
   runs as an earlier graph dependency instead of a same-file trailing
   statement.

Also: the 2 clappr plugins' `require("clappr")` (present so a real npm
`clappr` peer could be used, which we never have) made esbuild detect them
as CommonJS and synthesize real module/exports objects, forcing their UMD
wrapper into a branch that calls an unresolvable `require()` at runtime -
throwing and halting every synchronous bundle statement after it (relive-seek,
timelens, activate-timelens). Rewrote both wrappers to go straight to the
window.Clappr branch, and dropped the now-unneeded --external:clappr flag.

Assisted-by: LLM
Rails 8.1 dumps schema.rb with alphabetized columns and schema-qualified extension names, so annotate_models diff is pure reordering plus enable_extension "plpgsql" -> "pg_catalog.plpgsql". No structural table/column changes.
Rails 8 upgrade switched asset pipeline to Propshaft + esbuild/sass via pnpm, so CI needs Node 22 and pnpm (via corepack) before setup.
with_filesizes wrote directly to @filesizes_path without ensuring its parent directory existed, causing Errno::ENOENT on fresh checkouts/CI. Create the directory first via FileUtils.mkdir_p.
The Propshaft migration moved the mediaelement plugins out of
vendor/assets/mediaelement-plugins and into a subdirectory of
vendor/assets/mediaelement. Only the latter is an asset root, so the
plugins' logical paths gained a "plugins/" prefix while their
stylesheets still ask for "playlist/playlist-controls.svg". Propshaft
cannot resolve that, leaves the URL relative, and the browser requests
an undigested path that does not exist. The source chooser gear and the
playlist controls were missing from the player.

Renaming the directory to vendor/assets/player-plugins lines the
logical paths back up with the stylesheets.

The six plugin JS files under vendor were byte-identical copies of the
ones in app/javascript/mediaelement-plugins that esbuild bundles.
Propshaft published them as dead weight.

All five config.assets.paths entries were inert. Propshaft already
globs every subdirectory of app/assets and vendor/assets, one of the
five directories did not exist, and Propshaft::LoadPath#dedup discarded
app/assets/images/frontend for sharing a prefix with app/assets/images.
_bootstrap-sprockets.scss is bootstrap-sass's Sprockets shim. It sets
$bootstrap-sass-asset-helper to true and aliases twbs-font-path() to
Sprockets' font-path() helper. dart-sass has no such function and
copied the call into application.css verbatim:

    src: url(font-path("../fonts/fontawesome-webfont.eot"));

which no browser can parse. Without the shim, bootstrap emits a plain
relative url() that Propshaft rewrites to a digested path.

This exposes an older problem. $icon-font-name points bootstrap's
glyphicon font at FontAwesome, and no FontAwesome files exist in the
repo, so assets:precompile now warns about five unresolvable fonts.
The deployed CSS carries the same broken references today, and no view
uses .glyphicon.
Dart Sass 3.0 removes the global colour and math functions. Our own
stylesheets now use the module equivalents:

    lighten($c, $x)  ->  color.adjust($c, $lightness: $x)
    darken($c, $x)   ->  color.adjust($c, $lightness: -$x)
    ceil(), floor()  ->  math.ceil(), math.floor()
    $a / $b          ->  math.div($a, $b)

These are the documented one-for-one equivalents, so all three entry
points compile to byte-identical CSS. Sass also suggests color.scale(),
which would have shifted the colours.

That covers every deprecation warning we own. The rest come from
node_modules and are handled separately.

Commented-out lines quoting bootstrap's own defaults are left alone,
since they describe upstream values.
The Sprockets pipeline compressed production assets with the uglifier
and sass compressors. Both were dropped in the Propshaft migration with
nothing in their place, so we started shipping unminified JavaScript
and expanded CSS.

    application.js   1,862,938 -> 1,137,960 bytes
    application.css    257,321 ->   209,475 bytes

application.js now comes out smaller than the 1,261,135 bytes uglifier
produced. The two player bundles shrank by roughly the same factor.

build:css also gains --quiet-deps and --silence-deprecation=import.
Every deprecation warning left comes either from vendored sass we do
not control, bootstrap-sass 3.4.1 and @activeadmin, or from our own
@import rules, which cannot move to @use while bootstrap-sass is still
in the tree. That takes `rake test` from roughly 480 warnings to none.
Silencing them buys time: when Dart Sass 3.0 drops @import the build
stops working, so bootstrap-sass has to go before then.
The Docker setup was never updated for the Propshaft migration. The
image installs nodejs but no package manager, since Alpine's nodejs
package ships neither npm nor corepack, and nothing ever ran pnpm
install or pnpm build. app/assets/builds is gitignored, so a fresh
checkout has no bundles and Propshaft raises MissingAssetError on every
page render.

The bundles have to be built when the container runs rather than when
the image is built: the image holds no application code, the working
copy is bind mounted, and app/assets/builds sits under that mount.

The containers also get their own node_modules in a named volume.
esbuild and @parcel/watcher ship platform-specific binaries, so a
node_modules built on a macOS host must never reach the Linux
container through the bind mount. The volume has to be named, because
the `compose run` that installs and the `compose up` that serves need
to share it.

This stays a single-stage dev image. Production deploys with Capistrano.

The image has not been built or run. Docker is not installed on the
machine this was written on.
deploy:compile_assets runs assets:precompile, which jsbundling-rails
and cssbundling-rails extend to shell out to pnpm install and the two
build scripts. The app server therefore needs node and pnpm on PATH,
which is a new requirement from this branch.

Linking node_modules into shared/ keeps each deploy to an incremental
install.
This Syriac-script font has been the site's primary sans-serif
font since the very first asset import in 2015, ahead of Helvetica
and Arial. Nothing in the codebase or history suggests it was a
deliberate choice; it has the shape of an unedited leftover from
whatever Bootstrap theme the frontend was originally scaffolded
from. Its self-hosted .eot file also isn't a valid format for any
browser but old IE, so every other browser's font sanitizer rejects
it, producing console/error-tracking noise on every page load.
Bumps the npm_and_yarn group with 1 update in the / directory: [jquery](https://github.com/jquery/jquery).


Updates `jquery` from 1.12.4 to 3.5.0
- [Release notes](https://github.com/jquery/jquery/releases)
- [Changelog](https://github.com/jquery/jquery/blob/main/changelog.md)
- [Commits](jquery/jquery@1.12.4...3.5.0)

---
updated-dependencies:
- dependency-name: jquery
  dependency-version: 3.5.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
…arn-1b29616cd2

chore(deps): bump jquery from 1.12.4 to 3.5.0 in the npm_and_yarn group across 1 directory
Bumps the gems group with 2 updates in the / directory: [solargraph](https://github.com/castwide/solargraph) and [haml](https://github.com/haml/haml).

Updates `solargraph` from 0.60.3 to 0.60.4
- [Changelog](https://github.com/castwide/solargraph/blob/master/CHANGELOG.md)
- [Commits](castwide/solargraph@v0.60.3...v0.60.4)

Updates `haml` from 7.5.0 to 7.5.1
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](haml/haml@v7.5.0...v7.5.1)

---
updated-dependencies:
- dependency-name: haml
  dependency-version: 7.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gems
- dependency-name: solargraph
  dependency-version: 0.60.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump the gems group across 1 directory with 2 updates
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…/setup-node-7

chore(deps): bump actions/setup-node from 6 to 7
Bumps the gems group with 3 updates: [listen](https://github.com/guard/listen), [pg](https://github.com/ged/ruby-pg) and [apollo-federation](https://github.com/Gusto/apollo-federation-ruby).


Updates `listen` from 3.10.0 to 3.10.1
- [Release notes](https://github.com/guard/listen/releases)
- [Commits](guard/listen@v3.10.0...v3.10.1)

Updates `pg` from 1.6.3 to 1.7.0
- [Changelog](https://github.com/ged/ruby-pg/blob/master/CHANGELOG.md)
- [Commits](ged/ruby-pg@v1.6.3...v1.7.0)

Updates `apollo-federation` from 3.10.3 to 3.10.5
- [Release notes](https://github.com/Gusto/apollo-federation-ruby/releases)
- [Changelog](https://github.com/Gusto/apollo-federation-ruby/blob/main/CHANGELOG.md)
- [Commits](Gusto/apollo-federation-ruby@v3.10.3...v3.10.5)

---
updated-dependencies:
- dependency-name: listen
  dependency-version: 3.10.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gems
- dependency-name: pg
  dependency-version: 1.7.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: gems
- dependency-name: apollo-federation
  dependency-version: 3.10.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump the gems group with 3 updates
Bumps the gems group with 1 update: [solargraph](https://github.com/castwide/solargraph).


Updates `solargraph` from 0.60.4 to 0.61.0
- [Changelog](https://github.com/castwide/solargraph/blob/master/CHANGELOG.md)
- [Commits](castwide/solargraph@v0.60.4...v0.61.0)

---
updated-dependencies:
- dependency-name: solargraph
  dependency-version: 0.61.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps-dev): bump solargraph from 0.60.4 to 0.61.0 in the gems group
Bumps the gems group with 1 update: [kaminari](https://github.com/kaminari/kaminari).


Updates `kaminari` from 1.2.2 to 1.3.0
- [Release notes](https://github.com/kaminari/kaminari/releases)
- [Changelog](https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md)
- [Commits](kaminari/kaminari@v1.2.2...v1.3.0)

---
updated-dependencies:
- dependency-name: kaminari
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gems
...

Signed-off-by: dependabot[bot] <support@github.com>
chore(deps): bump kaminari from 1.2.2 to 1.3.0 in the gems group
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants