mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-09 04:06:42 +00:00
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>
47 lines
1.7 KiB
Ruby
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')
|