DIP17: describe native build extensions#57
Conversation
|
todo, integrate the following:
future extensions:
|
|
For the script, I think something as easy as Aa for image versioning, if we publish via actions to GitHub Container Repository, we can tag them with very very little extra effort with a GitHub action on git tag creation. |
|
Apologies for the delay on this. New deadline for changes is 2022-11-27T00:00:00Z. |
KazWolfe
left a comment
There was a problem hiding this comment.
Approving these changes, but I do have some inline notes that some may find useful.
All that being said, I still feel as though this system is a bit overcomplicated/overengineered for our use case. While I don't think it's worth tearing down what we currently have (as it is, well, already built for the one plugin that would reasonably use it), I suspect this would be a good candidate to revisit in the future. For example, may it suffice to simply build a developer-provided Dockerfile and then mandate that the final output be placed in a specific directory?
Lastly, I think we should make absolutely clear that the extensions provided here are not designed for developers to mutate or significantly change the build process to suit their wishes (e.g. disabling debug symbols), and instead only exists to assist staging of non-C# code. We can get into an entire debate of whether it's better or not (given that we're not on Windows images, probably not) to just make the developer deal with MSBuild as well, but this solution seems fine for now.
|
|
||
| Developers are also encouraged to ensure that the `csproj` is only responsible for building the plugin, and does not build anything unrelated (normal dependencies are fine). This may require developers to partition their project, or use a conditional build step. Additionally, if the plugin has a build-time dependency on a non-.NET build (e.g. JavaScript assets), it is best if that dependency is built ahead of time and the result committed to the repository, as the CI will not be able to build it. | ||
|
|
||
| As new plugins have been introduced that include native components (i.e. C++ or other such languages), the build agent will also execute a `./plogonbuild.sh` script located at `project_path` to produce any native artifacts. As these native components are likely to require the MSVC toolchain, it is recommended that you use the `extended` build image, as described above. An example of a build script can be seen in the [xivr repository](https://github.com/ProjectMimer/xivr/blob/main/dip17build.sh). |
There was a problem hiding this comment.
Ideally, we would allow users to specify build scripts as part of the manifest to allow for more flexibility in the process, potentially allowing caching of steps, and similar. This would also give developers more flexibility in deciding where to place files (e.g. those that wish to have .plogon/build.sh) as well as generally limiting the amount of hardcoded things for us to deal with.
This, however, is a very low priority need and would be more of a wishlist item than anything. The defined build script may already call other scripts as necessary, rendering a viable workaround.
There was a problem hiding this comment.
I'm not going to say "no", but I do think that's potentially overcomplicating things. To some extent, if you need multiple script files, there might be other issues that need to be resolved?
Re caching of steps: that's a decent point. For now, leaning towards "call make in your build script" and revisiting this at a later stage once we have a better idea of how it's being used.
There was a problem hiding this comment.
The main reason for "overcomplication" and allowing multiple scripts is to give developers flexibility and freedom in structuring their repositories in a way that best suits their purposes, as well as allow certain components to be more isolated (useful for testing). Granted, this can be done by having the script we call also call subscripts, but then we get back into the entire "hardcoded paths thing." This doesn't have to be solved now, however.
| - This RFC does not address automated building and deployment for plugins with hidden source or secrets, which will continue to submit to DalamudPlugins. This should be addressed at some point to allow plugins under these categories to submit. The current solution in mind for secrets is for the secret to be provided to goatcorp, who will then supply it to the GitHub runner, but this requires more thought. For hidden source plugins, we may ask developers to provide access to their repository for the buildbot, but we will need to ensure that this is done securely. | ||
| - The existence of a build script, as well as the ability to download network dependencies, suggests a potential future extension of secrets encrypted with a goatcorp public key and decrypted by a private key provided by the build agent. |
There was a problem hiding this comment.
Ultimately, closed-source plugins need to go away. At present, the two (known) closed-source plugins have security concerns related to API keys, which is reasonable but also problematic.
I like the idea of our images having a known GPG key loaded into its keychain (stored as a secret in our runner configs), and then allowing users to specify whatever decryption process as part of their pre-build steps. This will, of course, not solve the issue of the final build artifact leaking whatever was created, but that's the nature of (trusted) client-side code. Plugins that require secure connections to backend servers are, as always, advised to do account or session management themselves.
There was a problem hiding this comment.
Agree on all of this. Feel free to propose a follow-up extension in another PR - I don't know enough about how to securely handle secrets in a scenario like this
| ] | ||
| ``` | ||
|
|
||
| The `build.image` property refers to the Docker image used for building. By default, this is a minimalistic image that can build C# code; the `extended` image includes MSVC build tools and Wine, allowing it to build native C++ code. Future images may be made available to build other code. The extended image is defined [here](https://github.com/goatcorp/plogon-builder). There are currently two supported images, hardcoded in [Plogon](https://github.com/goatcorp/Plogon); a formal mechanism for this may be added at some point. This image is unversioned, but this will be revisited when required. |
There was a problem hiding this comment.
So long as the image is unversioned, we need to be careful to not introduce any breaking changes. Until such time as we have a system to version build images, may it make sense to guarantee that updates to the base image coincide with Dalamud API bumps?
There was a problem hiding this comment.
@goaaats Do you have any problems with that? My concern is that we might need to update the image at a time that doesn't coincide with an API bump, and we're left in the unfortunate situation of either holding back a plugin or forcing an API bump on everyone else.
My feeling is that if we run into issues with breaking changes, we'll just revert the relevant change and either a) make a new image or b) add some kind of versioning scheme (which could be as simple as creating extended-v2 or something while we get the rest of our ducks in line)
| @@ -142,9 +161,13 @@ Developers should add a DalamudPackager step to their `csproj`. It will generate | |||
|
|
|||
| Developers are also encouraged to ensure that the `csproj` is only responsible for building the plugin, and does not build anything unrelated (normal dependencies are fine). This may require developers to partition their project, or use a conditional build step. Additionally, if the plugin has a build-time dependency on a non-.NET build (e.g. JavaScript assets), it is best if that dependency is built ahead of time and the result committed to the repository, as the CI will not be able to build it. | |||
There was a problem hiding this comment.
Please clarify this to better suit the below additions - would we rather assets be built in plogonbuild.sh or still pre-baked?
There was a problem hiding this comment.
For now, pre-baked, depending on the type of asset. Rule of thumb, I guess: if it can be built with the tools available in the image, it's probably fine, but if it can't, then it should be prebaked. If uncertain, ask goat or another build system tech.
The concern with that is the Dockerfile could do arbitrary things (like wasting bandwidth / storage space / building Chromium and holding up the box for everyone else). Suppose we could catch that in review. Not sure if a custom Dockerfile is simpler than a script running in a known Docker environment? Guess it's up to your personal preferences. Will think about it some more.
Sure. I'll update that in the next draft. Given the feedback, I'll update the draft in a day or two and we can ratify by the end of the month. Depends on how busy I am. |
|
A custom Dockerfile will always be easier than a prebaked sandbox with a custom build script, because you can use an arbitrary base image, which defeats the purpose of the DIP. If we allowed arbitrary Dockerfiles and then restricted the base image to a few allowed images, then we'd be right back where we are now (though that would benefit from built-in caching so there might be merit to that). |
|
Also, versioning our base images should be seriously considered at some point for reproducibility. DIP17 gives us confidence that builds are managed by a trustworthy authority, but it doesn't necessarily make our builds reproducible, since the build artifacts may change if the build image changes. Having some record of a build being done on a particular image version would fix that. |
A script is simpler given:
A Dockerfile would allow a developer to more easily test their build processes locally, build an environment that's suited for their purposes, and otherwise handle things in a more graceful manner. I do think the point about local testing is particularly salient though - right now if I wanted to make and test an extended build I'd need to pull down the extended container, browse around, figure out where files are dumped, and run the container and build steps locally until they worked - or, worse, reconfigure my local bare-metal environment to behave like the extended image. |
|
|
||
| The `build.image` property refers to the Docker image used for building. By default, this is a minimalistic image that can build C# code; the `extended` image includes MSVC build tools and Wine, allowing it to build native C++ code. Future images may be made available to build other code. The extended image is defined [here](https://github.com/goatcorp/plogon-builder). There are currently two supported images, hardcoded in [Plogon](https://github.com/goatcorp/Plogon); a formal mechanism for this may be added at some point. This image is unversioned, but this will be revisited when required. | ||
|
|
||
| The `build.needs` array property describes files that should be downloaded by the build agent and made available to the build environment, ala NixOS or similar build environments. An arbitrary number of files can be downloaded, but this will be checked by members of the review team. This is intended for direct dependencies required for your build script. These files are downloaded before the rest of the build occurs. |
There was a problem hiding this comment.
The review team specifically should also encourage the use of clearly-defined URLs that point to a specific version (e.g. don't use https://get.myapp.io/download/sdk).
Files or URLs that seem to have a high tendency to break should be rejected by the review team. This does pose a bit of a problem though, as certain providers don't necessarily like "playing nice" and providing versioned files - we'd likely need to recommend users upload these SDK versions to their own file store (or something else?).
|
Word of Goat says we shan't be supporting custom Docker images, so we'll stick with predefined images for now |
As required for XIVR and other plugins that have additional build components.
Unless any objections arise, this will be ratified by 2022-11-18T00:00:00Z.
https://discord.com/channels/581875019861328007/1040413030959284244