Files
computer-playbook/roles/web-app-gitlab/files/ruby/appearance.rb
T
kevinveenbirkenbachandClaude Opus 5.5 c4764235d1 feat(web-app-gitlab): carry the corporate design into GitLab's appearance
GitLab reads its logos, favicon, PWA icon and title from the Appearance
model, so tasks/03_design.yml renders the logo set and runs
files/ruby/appearance.rb through rails runner after the MCP surface.
The script uploads logo, header logo, favicon and PWA icon, sets the
title, PWA name and short name, and removes only the fields the role
set earlier when design is off or a field is missing.
templates/style.css.j2 maps GitLab's colors onto the design tokens,
templates/design.js.j2 mirrors GitLab's own color mode, and
meta/services.yml declares the logo slots.

files/playwright/test-design.js signs in natively as GitLab's root
account with ADMIN_PASSWORD, which holds root's password on this branch
and on feature/store-i18n alike, checks the tokens in both modes, a
color mode picked in the preferences, the sign-in page, the signed-in
interface, top-bar focus, logos and title, and root's admin area, and
captures the gallery. The pass's own administrator provisioning stays out of
this commit: role logic is owned by feature/store-i18n, which keeps
root as its break-glass account.

TODO.md records the open self sign-up, the MCP owner password in argv,
Gravatar and the stale MCP section of the README.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 00:48:18 +02:00

47 lines
1.7 KiB
Ruby

# nocheck: mirrored-unit-test - runs in `rails runner` against the Appearance model of the GitLab image; the model is not loadable anywhere else
# Param: uploads {field: [extension, base64 content]} prepended on stdin; a field the role owns and that is missing here is removed.
# Param: GITLAB_DESIGN_TITLE title, PWA name and short name; empty clears the ones the role set.
require 'base64'
require 'digest'
require 'tmpdir'
mark = 'infinito-design-'
fields = %i[logo header_logo favicon pwa_icon]
texts = %i[title pwa_name pwa_short_name]
title = ENV.fetch('GITLAB_DESIGN_TITLE')
appearance = Appearance.first || Appearance.new
owned = ->(field) { appearance.public_send(field).file&.filename.to_s.start_with?(mark) }
marked = fields.any? { |field| owned.call(field) }
changed = false
Dir.mktmpdir do |dir|
texts.each do |field|
current = appearance.public_send(field).to_s
next if current == title || (current.present? && !marked)
appearance.public_send("#{field}=", title)
changed = true
end
fields.each do |field|
next if uploads.key?(field) || !owned.call(field)
appearance.public_send("remove_#{field}=", true)
changed = true
end
uploads.each do |field, (extension, encoded)|
stored = appearance.public_send(field)
next if stored.file && !owned.call(field)
content = Base64.decode64(encoded)
next if stored.file&.exists? && Digest::SHA256.hexdigest(stored.read) == Digest::SHA256.hexdigest(content)
path = File.join(dir, "#{mark}#{field}.#{extension}")
File.binwrite(path, content)
appearance.public_send("#{field}=", File.open(path))
changed = true
end
appearance.save! if changed
end
puts(changed ? 'CHANGED' : 'OK')