Solved OpenProject build bug

This commit is contained in:
Kevin Veen-Birkenbach 2025-04-16 00:56:29 +02:00
parent 4b824ecd6c
commit 567622f523
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
12 changed files with 659 additions and 705 deletions

2
ansible.cfg Normal file
View File

@ -0,0 +1,2 @@
[defaults]
lookup_plugins = ./lookup_plugins

View File

@ -0,0 +1,9 @@
from colorscheme_generator import generate_full_palette
class LookupModule(object):
def run(self, terms, variables=None, **kwargs):
base_color = terms[0]
count = kwargs.get('count', 100)
shades = kwargs.get('shades', True)
return [generate_full_palette(base_color, count=count, shades=shades)]

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
colorscheme-generator @ https://github.com/kevinveenbirkenbach/colorscheme-generator/archive/refs/tags/v0.2.0.zip

View File

@ -1,8 +0,0 @@
---
- name: rebuild custom openproject docker image
command:
cmd: docker build --no-cache -t {{custom_openproject_image}} .
chdir: "{{openproject_plugins_service}}"
environment:
COMPOSE_HTTP_TIMEOUT: 600
DOCKER_CLIENT_TIMEOUT: 600

View File

@ -21,16 +21,14 @@
src: Gemfile.plugins src: Gemfile.plugins
dest: "{{openproject_plugins_service}}Gemfile.plugins" dest: "{{openproject_plugins_service}}Gemfile.plugins"
notify: notify:
- docker compose project setup - docker compose project build and setup
- rebuild custom openproject docker image
- name: "Transfering Dockerfile to {{openproject_plugins_service}}Dockerfile" - name: "Transfering Dockerfile to {{openproject_plugins_service}}Dockerfile"
template: template:
src: Dockerfile src: Dockerfile
dest: "{{openproject_plugins_service}}Dockerfile" dest: "{{openproject_plugins_service}}Dockerfile"
notify: notify:
- docker compose project setup - docker compose project build and setup
- rebuild custom openproject docker image
- name: "include role docker-repository-setup for {{application_id}}" - name: "include role docker-repository-setup for {{application_id}}"
include_role: include_role:

View File

@ -6,6 +6,9 @@ x-op-app: &app
volumes: volumes:
- "data:/var/openproject/assets" - "data:/var/openproject/assets"
- "{{dummy_volume}}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes - "{{dummy_volume}}:/var/openproject/pgdata" # This mount is unnecessary and just done to prevent anonymous volumes
build:
context: {{openproject_plugins_service}}
dockerfile: Dockerfile
services: services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}

View File

@ -1,26 +1,34 @@
# 🌍 Nginx Global Theming Role # 🌍 Global CSS Injection for Nginx
This **Ansible role** provides a **global theming solution** for Nginx-based web applications. It ensures a **consistent look and feel** across multiple applications by injecting a **unified global.css** with customizable theming options. ## Description
---
## 🚀 Features This Ansible role ensures **consistent global theming** across all Nginx-served applications by injecting a unified `global.css` file.
**Automatic CSS Deployment** Injects `global.css` into all Nginx-served applications. The role leverages [`colorscheme-generator`](https://github.com/kevinveenbirkenbach/colorscheme-generator/) to generate a dynamic, customizable color palette for light and dark mode, compatible with popular web tools like **Bootstrap**, **Keycloak**, **Nextcloud**, **Taiga**, **Mastodon**, and many more.
**Dynamic Theming** Uses `design.css.colors` from Ansible variables for **full customization**.
**Bootstrap Override Support** Ensures Bootstrap-based apps use the **unified global styles**.
**Versioning System** Prevents caching issues with automatic **timestamp-based versioning**.
**Dark Mode Support** Automatically adapts to user preferences.
**Runs Once Per Deployment** Avoids redundant executions with `run_once_nginx_global_css`.
--- ## Overview
## 🎨 Theming Details This role deploys a centralized global stylesheet (`global.css`) that overrides the default theming of web applications served via Nginx. It's optimized to run only once per deployment and generates a **cache-busting version number** based on file modification timestamps.
It includes support for **dark mode**, **custom fonts**, and **extensive Bootstrap and UI component overrides**.
The **CSS template (`global.css.j2`)** dynamically applies the defined theme colors and ensures **Bootstrap, buttons, alerts, forms, and other UI elements** follow the **unified design**. ## Purpose
## 🛠️ Contribution The goal of this role is to provide a **single source of truth for theming** across your infrastructure.
Feel free to **fork, modify, and improve** this role! Contributions are always welcome. 🛠️🔥 It makes all applications feel like part of the same ecosystem — visually and functionally.
--- ## Features
🚀 **Happy Theming!** 🎨✨ - 🎨 **Dynamic Theming** via [`colorscheme-generator`](https://github.com/kevinveenbirkenbach/colorscheme-generator/)
*Created by [Kevin Veen-Birkenbach](https://www.veen.world) with the assistance of [ChatGPT](https://chatgpt.com/share/67a5fea3-4d5c-800f-8bc4-605712c02c9b). - 📁 **Unified global.css** deployment for all Nginx applications
- 🌒 **Dark mode support** out of the box
- 🚫 **No duplication** tasks run once per deployment
- ⏱️ **Versioning logic** to bust browser cache
- 🎯 **Bootstrap override compatibility**
- 🧩 **Theme support for Keycloak, Nextcloud, Gitea, LAM, Peertube, and more**
## Credits 📝
Developed and maintained by **Kevin Veen-Birkenbach**.
Learn more at [www.veen.world](https://www.veen.world)
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
License: [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl)

View File

@ -1,94 +0,0 @@
import colorsys
def adjust_color(hex_color, target_lightness=None, lightness_change=0, hue_shift=0, saturation_change=0):
"""
Adjust a HEX color in HSL space.
- target_lightness: If provided (0 to 1), the lightness is set absolutely to this value.
Otherwise, lightness_change is applied additively (in percentage points, where 100 => 1 in HSL).
- lightness_change: Percentage points to add or subtract from lightness (if target_lightness is None).
- hue_shift: Degrees to shift hue (e.g., +180 for complementary).
- saturation_change: Percentage points to add or subtract from saturation.
Uses a 'cyclical' approach for lightness and saturation if no target_lightness is provided:
If the new value goes above 1, it wraps around (subtract 1).
If it goes below 0, it wraps around (add 1).
"""
# Strip leading '#' if present
hex_color = hex_color.lstrip('#')
# Parse the original RGB values
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
# Convert from [0..255] range to [0..1] for colorsys
r /= 255.0
g /= 255.0
b /= 255.0
# Convert RGB -> HLS (colorsys uses HLS, also hier: Hue, Lightness, Saturation)
h, l, s = colorsys.rgb_to_hls(r, g, b)
# Shift hue by (hue_shift / 360)
h = (h + (hue_shift / 360.0)) % 1.0
# Adjust saturation (cyclically)
s_new = s + (saturation_change / 100.0)
if s_new > 1:
s_new -= 1
elif s_new < 0:
s_new += 1
# Adjust lightness: either set to a target or change it additively (cyclically)
if target_lightness is not None:
l_new = target_lightness
else:
l_new = l + (lightness_change / 100.0)
if l_new > 1:
l_new -= 1
elif l_new < 0:
l_new += 1
# Convert back to RGB
new_r, new_g, new_b = colorsys.hls_to_rgb(h, l_new, s_new)
# Scale back to [0..255] and format as HEX
new_r = int(new_r * 255)
new_g = int(new_g * 255)
new_b = int(new_b * 255)
return '#{:02x}{:02x}{:02x}'.format(new_r, new_g, new_b)
def adjust_color_rgb(hex_color, target_lightness=None, lightness_change=0, hue_shift=0, saturation_change=0):
"""
Wrapper function for adjust_color.
Calls adjust_color to get the adjusted HEX color and then converts it to a string
of comma-separated RGB values.
"""
adjusted_hex = adjust_color(
hex_color,
target_lightness=target_lightness,
lightness_change=lightness_change,
hue_shift=hue_shift,
saturation_change=saturation_change
)
# Remove '#' and parse the RGB components
hex_val = adjusted_hex.lstrip('#')
r = int(hex_val[0:2], 16)
g = int(hex_val[2:4], 16)
b = int(hex_val[4:6], 16)
return f"{r},{g},{b}"
# Integration in the FilterModule for Ansible
class FilterModule(object):
'''Custom filters for Ansible'''
def filters(self):
return {
'adjust_color': adjust_color,
'adjust_color_rgb': adjust_color_rgb,
}

View File

@ -1,2 +1,29 @@
dependencies: ---
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Global CSS injection for Nginx-based apps using dynamic colorschemes."
license: "CyMaIS NonCommercial License (CNCL)"
license_url: "https://s.veen.world/cncl"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
min_ansible_version: "2.9"
platforms:
- name: Archlinux
versions:
- rolling
galaxy_tags:
- nginx - nginx
- css
- colors
- bootstrap
- theming
- dynamic
- frontend
- global
repository: https://s.veen.world/cymais
issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais
dependencies:
- role: nginx

View File

@ -1,26 +1,33 @@
# Load this role via nginx-modifier-all for consistency # Load this role via nginx-modifier-all for consistency
- name: Deploy global.css from template # roles/nginx-modifier-css/tasks/main.yml
- name: Generate color palette with colorscheme-generator
set_fact:
color_palette: "{{ lookup('colorscheme', global_css_base_color, count=global_css_count, shades=global_css_shades) }}"
when: run_once_nginx_global_css is not defined
- name: Deploy global.css
template: template:
src: global.css.j2 src: global.css.j2
dest: "{{global_css_destination}}" dest: "{{ global_css_destination }}"
owner: "{{nginx.user}}" owner: "{{ nginx.user }}"
group: "{{nginx.user}}" group: "{{ nginx.user }}"
mode: '0644' mode: '0644'
when: run_once_nginx_global_css is not defined when: run_once_nginx_global_css is not defined
- name: Get stat for global.css destination file - name: Get stat for global.css
stat: stat:
path: "{{ global_css_destination }}" path: "{{ global_css_destination }}"
register: global_css_stat register: global_css_stat
when: run_once_nginx_global_css is not defined when: run_once_nginx_global_css is not defined
- name: Set global_css_version to file modification time - name: Set global_css_version
set_fact: set_fact:
global_css_version: "{{ global_css_stat.stat.mtime }}" global_css_version: "{{ global_css_stat.stat.mtime }}"
when: run_once_nginx_global_css is not defined when: run_once_nginx_global_css is not defined
- name: Mark global css tasks as run once - name: Mark css as done
set_fact: set_fact:
run_once_nginx_global_css: true run_once_nginx_global_css: true
when: run_once_nginx_global_css is not defined when: run_once_nginx_global_css is not defined

File diff suppressed because it is too large Load Diff

View File

@ -1 +1,4 @@
global_css_destination: "{{nginx.directories.data.global}}global.css" global_css_destination: "{{nginx.directories.data.global}}global.css"
global_css_base_color: "{{ design.css.colors.base }}"
global_css_count: 100
global_css_shades: true