Skip to content

Create composite action to create constructor-based installers #63

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

Open
wants to merge 27 commits into
base: main
Choose a base branch
from

Conversation

marcoesters
Copy link

This PR creates a composite action to build constructor-based installers. The goal of this action is to unify the build workflows for both Anaconda and Miniforge installers and pool maintenance resources.

The action takes or creates an environment.yaml to create a build environment. Inside that build environment, it runs constructor on a provided recipe directory to create the installer. The output directory contains all constructor-created build artifacts.

The workflow is intended to be flexible and can:

  • Run the creation directly on a runner or inside a Docker container.
  • Use GitHub expressions to dynamically set the content of the build environment.
  • Can use existing conda installations on the runner/image or use conda-standalone/micromamba to create the build environment.
  • Supports constructor's interface for signing installers.

The README file contains several use cases and I added tests for each of them.

Closes #3

@marcoesters marcoesters marked this pull request as ready for review April 17, 2025 15:29
@marcoesters marcoesters requested a review from a team as a code owner April 17, 2025 15:29
action.yaml Outdated
description: |
Path to the environment.yaml file used to create the build environment.
Takes precedence over envrionemnt-yaml-string.
The file must not have the `name` property.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if it does? Ignored or error?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I mixed something up here - name can be used in the file, so I removed the comment.

CONSTRUCTOR_WORKSPACE=$(cygpath "${CONSTRUCTOR_WORKSPACE}")
fi
mkdir -p "${CONSTRUCTOR_WORKSPACE}"
chmod 777 "${CONSTRUCTOR_WORKSPACE}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need 777?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, yes. For builds inside a container, the UID and GIDs are not the same for the runner and the container image, and you need x permissions to access that directory. If we want to mitigate the risks here somewhat, we can set those permissions only for those builds that use a container image.

@jaimergp
Copy link
Member

jaimergp commented May 5, 2025

Would be interesting to run https://github.com/woodruffw/zizmor on this repository to catch some potential security risks.

@marcoesters
Copy link
Author

Would be interesting to run https://github.com/woodruffw/zizmor on this repository to catch some potential security risks.

Thank you for your review! I think I addressed your specific comments. Also thanks for recommending zizmor - I ran the checks and made several recommended changes. The chief concern was template injection vulnerabilities, so I replaced most with environment variables.

The reason why I employed template substitutions is that adding environment variables into the env context of the build step is not enough - they also need to be added to building the Docker command. If we ever support other containerization software like podman, they need to be handled in that way, too. This can be quite brittle to maintain because this is easy to miss.

To mitigate template injection vulnerabilities, I added an input validation step and added tests that try and inject a cat command output (see this run as an example for how it would succeed if we just did template substitution). The workflow will error out if those inputs do not point to a directory/file, so an attacked will have to find a file with the exact same path as the malicious code that is being executed.

To be specific, these are the templates in the build step zizmor still annotates (with severity):

  • steps.workspace.outputs.constructor-workspace (informational): This is based on environment variables and code inside the action that is not controlled by the caller.
  • steps.workspace.outputs.outputs-file (informational): Same as constructor-workspace.
  • inputs.environment-yaml-file (high): mitigated by input validation
  • steps.environment-str.outputs.environment-yaml-file (informational): same as constructor-workspace
  • inputs.conda-root (high): mitigated by input validation
  • inputs.input-directory (high): mitigated by input validation
  • inputs.standalone-location (high): mitigated by input validation

If you see risks despite the input validation, we will have to accept the more cumbersome maintenance model though. The input validation is a good addition either way.

@marcoesters marcoesters requested a review from jaimergp May 7, 2025 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create action skeleton
2 participants