5
\$\begingroup\$

The source for my Godot 4 game is public and open. With exports targeting Web, Linux, or Windows this was just fine. However, now I'm trying to target macOS with an export as well. This includes signing and notarizing the app (as I suspect Android and iOS targets would need too) with specific secrets.

These secrets should not go into the public source but, well... be kept secret. I cannot find any good documentation on how to do this. I've checked:

As well as other bits of the documentation and online search results. None of them have any definitive advice on how to handle this situation. But perhaps I've not been reading of searching precisely enough?

The closest I've come is what the .gitignore from godot-demo-projects seems to do: just ignore exports_presets.cfg and presumably have secrets inside that file. That has two major downsides for me:

  1. A ton of other non-secret export settings are now no longer under source control;
  2. You're one git mistake away from making your secrets public.

I must be missing something, because anyone who wants to make a notarized macOS export for a Godot game will encounter this situation. Even if your source code is private, you'd not want to have secrets in there in plaintext, right?

How do you keep export secrets safely outside of the game code repository, without giving up on all source control of non-secret export settings?

I'm happy to utilize any Godot 4 feature as I'm on the latest major release, but I reckon others might be interested in a Godot 3.x solution as well.

\$\endgroup\$
5
  • \$\begingroup\$ A few extra hours of chewing on this and searching the web, I think that this comment from 3 weeks ago on a relevant proposal suggests that there is no way to do what I want, currently? Not sure though. \$\endgroup\$
    – Jeroen
    Apr 16 at 16:35
  • \$\begingroup\$ I doubt this is specific to Godot. Perhaps strip these details and tags? \$\endgroup\$
    – Kromster
    Apr 16 at 18:15
  • \$\begingroup\$ Hmmm, there might be generic workarounds or solutions that I can use (and would welcome). But coming from web development myself, I'd expect the best solutions for this kind of problem to be ecosystem (in this case Godot) specific? For example in web development .NET has .config transforms and user secrets, Node-based systems (e.g. Vite) rely on .env files in a hierarchy, etc. (The link from my earlier comment also suggests the Godot community is looking for Godot-specific solutions?) \$\endgroup\$
    – Jeroen
    Apr 16 at 20:20
  • \$\begingroup\$ @Jeroen Yes, there is interest in a Godot specific solution, however at the time of writing we don't have it. \$\endgroup\$
    – Theraot
    Apr 16 at 21:16
  • \$\begingroup\$ I am not familiar with Godot, so I don't want to make an answer but... have you consider "templating"? That is, put "magic values" (like "aaaaaaaaa") instead of the secrets in the committed file, then have a build script replace those magic values by environment variables when building in a file that is never committed (and ideally, never put in the repo itself /tmp/ is a fine place for it). \$\endgroup\$ Apr 17 at 10:19

1 Answer 1

3
\$\begingroup\$

The way I currently handle this is as follows:

  • The developer responsible for release keeps a local branch with the changes that add the secret details to exports_presets.cfg.
  • When we want to release, that developer merges the main branch into that local branch, so he can export the release build of the game.

The shared exports_presets.cfg can have enough information to make some debug builds, which are useful for testing by other members of the team. However it does not contain enough information to make the release builds which require additional credentials.


On safeguards

First of all, if you automate your build process (which you can with Godot command line arguments) then you can have your build script merge in the correct way.


Now, if you want to prevent people from merging the wrong way, you could use Git Hooks. You want a pre-merge-commit. Which you create with a shell script called pre-merge-commit (no extension) in your .git/hooks folder. Git will honor the shebang (#!) at the start of the file.

To prevent the merge, the script must end with a non-zero exit code. Also, if Git fails to execute the script (e.g. it could not resolve the shebang) it will not merge.

Notes for the shebang in Windows:

  • The path using / as folder separator character will work.
  • You need to escape spaces and dots with \.
  • You don't need to include the executable extension .exe.
  • A path that starts with / will be relative to the installation folder of Git.

As a result #!/bin/bash and #!/bin/sh will resolve to \bin\bash.exe and \bin\sh.exe respectively, in the Git installation folder (e.g. C:\Program Files\Git\). In fact, \bin\bash.exe and \bin\sh.exe are provided with the installation of Git for Windows. So you can use either #!/bin/bash or #!/bin/sh cross platform.

Here is an example of what you want: pre-merge-commit.


Be aware that the Git Hooks are in the .git/hooks folder, and thus not in source control.

You might not need to deploy the Git Hooks, since only the developer that builds the game would be in the situation to make the mistakes necessary to leak the information.

However, one option to deploy them would be to use a template directory which would have to be part of the development environment on the target machines. And you could protect that with OS level security, and you want the option to boot from another device protected with a password so they don't bypass OS level security, and and you want physical security to prevent other means.

But assuming you can trust your developers, then adding a script in your repository that deploys the Git Hooks should be sufficient.

In fact, we can assume that you trust in particular the developer that has the exports_presets.cfg with extra credentials, since they have extra credentials. So probably you can trust they will run the script to build the game, and you don't need Git Hooks.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ That seems to be in the domain of "You're one git mistake away from making your secrets public" - do you know of any safeguards you can add against accidentally merging in the wrong direction and putting the secrets into main? \$\endgroup\$
    – DMGregory
    Apr 16 at 18:01
  • 1
    \$\begingroup\$ @DMGregory I would argue that it is two mistakes away (merge and push). Yet, I have expanded the answer to a higher number of "mistakes". \$\endgroup\$
    – Theraot
    Apr 16 at 21:18
  • \$\begingroup\$ Excellent addition! Thanks for taking the time to add that - I expect more than one dev is going to have a nicer time by following this advice. \$\endgroup\$
    – DMGregory
    Apr 16 at 21:26
  • 1
    \$\begingroup\$ I wonder if it couldnt be solved by ignoring the real file and having 2 files (one with the secrets and gitignored, one "template" config) that are combined to the final config by a prebuild script. \$\endgroup\$
    – masterX244
    Apr 17 at 7:25
  • \$\begingroup\$ @masterX244 sounds viable. Addendum: You could have the build script make a copy of the project to a temporary folder, then replace the exports_presets.cfg, then do the build, extract the artifact, and then clean the temporary folder. That should work. \$\endgroup\$
    – Theraot
    Apr 17 at 7:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .