@hakone these are some great questions!
I’m using the OpenTofu CI/CD component as an example here. Just briefly: it consists of a bunch of templates and an associated Container Image that includes a custom wrapper script shell script around tofu
.
As a rule of thumb I try to put most of the heavy lifting the component does into the shell script which I can “unit test”.
The harder part is testing the templates (which you asked for). What I do here is that in my components .gitlab-ci.yml
I have an integration-test stage with a bunch of jobs each representing a single integration test. An integration test just triggers a child-pipeline with a pipeline configuration that “simulates” the usage of the templates using “test inputs” - the integration test passes if that child-pipeline passes.
(the blue box shows the integration test job and the red box the child-pipeline it triggered)
This approach works pretty well to test certain input combinations. I’m also not directly triggering a child-pipeline but have an “intermediary” pipeline configuration that can augment the template job for testing purposes. Here are some implementation references:
- The include of the integration tests in the top-level
.gitlab-ci.yml
: .gitlab-ci.yml · main · GitLab components / OpenTofu · GitLab - The integration test job definitions included in the top-level
.gitlab-ci.yml
: tests/integration.gitlab-ci.yml · main · GitLab components / OpenTofu · GitLab - the “intermediary” pipeline definition of an integration test: tests/integration-tests/Defaults.gitlab-ci.yml · main · GitLab components / OpenTofu · GitLab
Because of the precedence of variables you can overwrite the most important variables in your “intermediary” pipeline definition - which includes the predefined CI/CD variables. However, be careful with that!