-
Notifications
You must be signed in to change notification settings - Fork 0
Custom branding [packit-deploy] #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
429f1c0
to
df68de1
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #12 +/- ##
==========================================
+ Coverage 91.93% 95.12% +3.19%
==========================================
Files 4 4
Lines 248 308 +60
Branches 28 44 +16
==========================================
+ Hits 228 293 +65
+ Misses 12 7 -5
Partials 8 8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
c0b6ff7
to
5ab8c93
Compare
This is due to a change in constellation 1.2.3 - see vimc/orderly-web-deploy#56 for an analogous fix
I realised firstly that: - We need to be able to customise branding config in scenarios where packit-deploy does not provide the proxy, and its provided otherwise, as is the set-up in Montagu. Montagu handles the proxy in that case. - But running packit-deploy in a proxy-less mode doesn't in fact make knowing the app file locations complicated, since the Packit app Dockerfile specifies the location for the built app to be copied to, so we can rely on that to be the case for both proxy-less and non-proxy-less modes of packit-deploy.
e15a53d
to
95fdd41
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! 😎
README.md
Outdated
@@ -117,3 +121,31 @@ docker exec -it packit-packit-db psql -U packituser -d packit | |||
``` | |||
|
|||
If you have anything else running on port 80 or 443, nothing will work as expected; either stop that service or change the proxy port in the configuration that you are using. | |||
|
|||
## Custom branding config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is really useful. Might be worth explicitly stating which yml values each of these features correspond to - or at least pointing to the relevant example config.
README.md
Outdated
|
||
## Custom branding config | ||
|
||
Custom branding is disabled unless both a logo and brand name are configured, since we don't want to display an incorrect combination of brand name and logo/favicon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this - I feel like the brand name could be the minimum as you might want to just show the default logo if you want to give the app a project-centred name but don't have a bespoke logo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I'll make it so all settings are optional.
@@ -42,10 +42,10 @@ outpack: | |||
packit: | |||
api: | |||
name: packit-api | |||
tag: main | |||
tag: mrc-6035-custom-branding # revert to main after mrc-6035-custom-branding is merged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit surprised that you needed to update these tags for configurations which don't make use of custom branding..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I don't remember why, I do remember needing them in one case and thinking what the hell I may as well put it everywhere.
config/complete/packit.yml
Outdated
accent: "hsl(0 100% 50%)" | ||
accent_foreground: "hsl(123 100% 50%)" | ||
dark: | ||
accent: "hsl(30 100% 50%)" | ||
accent_foreground: "hsl(322, 50%, 87%)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For those who don't natively speak hsl, it might be nice to put comments describing each of these colours.
|
||
## Branding configuration | ||
## If only one of 'name' or 'logo_path' is set, both will be ignored. | ||
brand: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess an alternative would have been to put each of these values under the key of the relevant container rather than having the top level "brand" key. I think it makes sense to keep them together, but I wonder if grouping them into "app" and "api" values here might be useful to clearly demarcate which values are applied in which container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no such clear demarcation, since the logo file path is used by the configuration of both the app and the api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a difference in which containers the deploy tool applies the values to - the app container uses the logo path, but it gets it from the api without any explicit tinkering from the deploy tool, which needs to provide the logo to the api.
But the user of the deployment isn't necessarily going to be thinking about it those terms (though they might be!) so fine as is.
docker pull redis:5.0 | ||
docker pull mrcide/outpack.orderly:main | ||
docker pull mrcide/outpack_server:main | ||
docker pull mrcide/packit-db:main | ||
docker pull mrcide/packit-api:main | ||
docker pull mrcide/packit:main | ||
docker pull mrcide/packit-proxy:main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for integration testing? You should be able to start the Packit constellation with the --pull flag. You might be pulling the wrong branches if you rely on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is really a constellation issue that I need to fix at some point
src/packit_deploy/config.py
Outdated
@@ -75,6 +77,39 @@ def __init__(self, path, extra=None, options=None): | |||
else: | |||
self.proxy_enabled = False | |||
|
|||
self.branding_enabled = bool(dat.get("brand", {}).get("name") and dat.get("brand", {}).get("logo_path")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels a little easier to reason about, though I assume the logic shakes down correctly with Python casting.
self.branding_enabled = bool(dat.get("brand", {}).get("name") and dat.get("brand", {}).get("logo_path")) | |
self.branding_enabled = bool(dat.get("brand", {}).get("name")) and bool(dat.get("brand", {}).get("logo_path")) |
Also, it might be tidier to pull out the brand config once, before this line and then query that rather than query from the top level a bunch of times e.g. brand_config = dat.get("brand, {})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the whole concept of 'branding enabled/disabled'.
try: | ||
env.update({"PACKIT_BRAND_LOGO_LINK": cfg.brand_logo_link}) | ||
except AttributeError: | ||
print("[packit-api] A brand logo link was not provided (optional)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just check if the attribute is set and not attempt to set the value if it isn't provided?
env.update({"PACKIT_BRAND_LOGO_NAME": cfg.brand_logo_name}) | ||
env.update({"PACKIT_BRAND_LOGO_ALT_TEXT": cfg.brand_logo_alt_text}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
env
is just an ordinary dictionary so you could just set values like
env["PACKIT_BRAND_LOGO_NAME"] = cfg.brand_logo_name
.
Or conversely you could take advantage of update
and set both values at once:
env.update({"PACKIT_BRAND_LOGO_NAME": cfg.brand_logo_name}) | |
env.update({"PACKIT_BRAND_LOGO_ALT_TEXT": cfg.brand_logo_alt_text}) | |
env.update({ | |
"PACKIT_BRAND_LOGO_NAME": cfg.brand_logo_name, | |
"PACKIT_BRAND_LOGO_ALT_TEXT": cfg.brand_logo_alt_text}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good when run up; comments, questions and suggestions inline
README.md
Outdated
|
||
### Logo (required) | ||
|
||
The logo file is bind-mounted into the front-end container, in a public folder, and the packit api has an env var set for the filename of the logo, so that it can tell the front end where to look for the file. Your logo file should be in the same directory as the config file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What size should this be as a suggestion? Does it matter or is is just resized on the fly? Why is it required? Can we not fall back on the default version if it is not found?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What size should this be as a suggestion? Does it matter or is is just resized on the fly?
I'll put in a comment to say that the logo will be constrained to the height of the header and the width is kept proportional.
Why is it required?
Removed requirement.
Can we not fall back on the default version if it is not found?
Let's discuss over at #12 (comment)
README.md
Outdated
|
||
The logo file is bind-mounted into the front-end container, in a public folder, and the packit api has an env var set for the filename of the logo, so that it can tell the front end where to look for the file. Your logo file should be in the same directory as the config file. | ||
|
||
### Logo alt text (optional) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be alt text or title text? Should it be possible to set both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, those are separately configurable. Title text is referred to as 'brand name'.
|
||
### Logo link (optional) | ||
|
||
This is to allow a configurable link destination for when the user clicks the logo. In VIMC's case this would be a link back to Montagu. This is set as an env var in the packit api, which passes it on to the front end. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the fact that these come through as an envvar matter for the README?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dunno, it might be useful documentation, but the problem with documentation is that it gets out of sync with reality. @EmmaLRussell you are someone who has found this readme useful, what do you reckon?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a bit of docs on the mechanics of how these values work is useful once it's fairly stable, as it's quite bitty and easy to forget which values go where ..
|
||
### Brand colors (optional) | ||
|
||
The brand colors are written as css variables into the public custom.css file, which override default variables in the front-end. If no colors are provided for the dark theme, the light theme colors are reused. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List colours that can be modified here?
# We configure the title tag of the index.html file here, rather than updating it dynamically with JS, | ||
# since using JS results in the page title visibly changing a number of seconds after the initial page load. | ||
substitute_file_content( | ||
container, f"{cfg.app_html_root}/index.html", r"(?<=<title>).*?(?=</title>)", cfg.brand_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
f" --custom-accent-foreground: {cfg.brand_accent_foreground_dark};\n" | ||
"}\n" | ||
) | ||
substitute_file_content(container, f"{cfg.app_html_root}/css/custom.css", r".*", new_css, flags=re.DOTALL) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this just (over)writing a file? Can we do this more obviously?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. I can make the fact it's doing this more obvious by wrapping substitute_file_content
with a method overwrite_file
. It's somewhat convenient (for developers of packit) to have a file custom.css in the packit repo, which explains in comments where the custom css variables will come from in production, and which they can use to play with setting custom variables.
substitute_file_content( | ||
container, f"{cfg.app_html_root}/index.html", r"(?<=<title>).*?(?=</title>)", cfg.brand_name | ||
) | ||
substitute_file_content(container, f"{cfg.app_html_root}/index.html", r"favicon\.ico", cfg.brand_favicon_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused on this, and perhaps generally, why the index.html needs writing at all. Can we not have a path to the content that never changes (say /favicon.ico
) and then have the backend try first (say) custom/favicon.ico
then fall back on baked-in/favicon.ico
for example? With the same strategy for other resources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to have configurable favicon filename so that people can use any type of file, which might require a different extension than .ico
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With regards to other resources - of which there is one, the logo - the same argument could apply. It's also useful to have the logo file be named whatever, so that you can maintain an obvious relationship between it and the file in your organisation's perhaps-chaotic dropbox folder of various different logo variants and versions.
e48c7bc
to
045ca04
Compare
Also document colours
045ca04
to
61eec93
Compare
# Secret used to generate JWT tokens - this can be any string, the secret at this key in the vault is a random | ||
# 32 char string, and is probably fine to re-use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Secret used to generate JWT tokens - this can be any string, the secret at this key in the vault is a random | |
# 32 char string, and is probably fine to re-use | |
# Secret used to generate JWT tokens - this can be any string |
This branch deals with all custom branding config. Twinned with mrc-ide/packit#202
How custom branding works
This should be clear from the 'Custom branding config' section of README.md; let me know if not.
Test this branch locally
Follow the steps in the README, using the provided example config
basicauthcustombrand
to see the app with custom branding applied, and any other (e.g.basicauth
) to see that it still works without branding configuration.When you do
packit start <config>
make sure to add the--pull
option so that you're using the latest version of the packit branch. When using any basicauth-based config, you'll need to use the./scripts/create-super-user
script if you want to see the app in a logged-in state.Other changes
Constellation version is upgraded so we can make use of bind mounts. Bind mounts are useful here because they let us easily mount files, rather than directories (so we don't end up mounting over the whole public folder...), and it's more complicated to write a file into a volume. (Options to do that include getting a special volume driver that allows pre-populating, or using a temporary container with the file bind-mounted and copying it into the volume there.)
As a result of upgrading the constellation version, the test workflow explicitly pulls images. This is due to a change in constellation 1.2.3 - see vimc/orderly-web-deploy#56 for an analogous fix.
Before merging