Testing¶
This document describes how to run tests for Otterdog. You should set up your development environment as described in the Development Setup guide before running tests.
Prerequisites¶
- Skaffold
- tailscale or ngrok (either can expose the dev environment for GitHub Webhooks, see below)
- minikube
- k9s
Development Resources¶
[Optional] Creating an Organization for development¶
On your profile, create an organization
- Organization name:
otterdog-<github username>(Ex: otterdog-foobar) - Contact email: your@email
- This organization belongs to: My personal account
Accept the Terms of Service (if you agree)
Fork otterdog¶
Fork otterdog in your own organization. This will act as a base for modifications and contributions to the project, and will serve as the URL for the otterdog config base_template.
Create a user token¶
Create a Personal Access Token with sufficient permissions to access the organization API.
The GitHub API token needs to have the following scopes enabled: repo, workflow, admin:org, admin:org_hook, delete_repo.
For more about credentials, see Credentials.
Credentials provider configuration¶
For the purpose of this testing section, we use GitHub environment variables, but third-party providers are also supported, such as pass or bitwarden.
Add these environment variables at the GitHub org level: https://github.com/organizations/otterdog-OTTER_USERNAME
* OTTER_PASSWORD
* OTTER_TOTP_SEED
* OTTER_API_TOKEN (token previously created)
NOTE: 2FA must be activated on your account.
For other credential providers, see Credentials.
Configure your otterdog (source code) to work with your development organization¶
Create a new repository named otterdog-config and set up the otterdog configuration: Otterdog configuration
Go to your organization https://github.com/otterdog-<github username> > Repositories > New repository
- Repository name:
otterdog-config
Click on Create repository.
Then create the file otterdog.json in this repository with all the required settings.
{
"defaults": {
"jsonnet": {
"base_template": "https://github.com/<Github Username>/otterdog#otterdog/resources/defaults/otterdog-defaults.libsonnet@main",
"config_dir": "orgs"
}
},
"organizations": [
{
"name": "otterdog-<Github Username>",
"github_id": "otterdog-<Github Username>",
"credentials": {
"provider": "env",
"api_token": "OTTER_API_TOKEN",
"username": "OTTER_USERNAME",
"password": "OTTER_PASSWORD",
"twofa_seed": "OTTER_TOTP_SEED"
}
}
]
}
[Optional] Set up Otterdog GitHub org configuration repository¶
Go to your organization https://github.com/otterdog-<github username> > Repositories > New repository
- Repository name:
.otterdog
Click on Create repository.
If the name differs from .otterdog, edit your configuration and include:
[Optional] Otterdog WebApp development environment¶
To run the otterdog webapp (without integration with GitHub)
Make sure you have the eclipse-csi Helm chart repository added:
Note
The make dev-webapp* targets deploy to the current kubectl context. They stop with an error if this context is
not minikube, e.g. after working with another cluster, to prevent deploying the development environment to it.
Switch back with kubectl config use-context minikube, or check the context with make check-kube-context.
If you want use the integration with GitHub, you can use tailscale or ngrok to expose your development environment. Pick one:
- Setup a tailscale tunnel
- Setup an ngrok tunnel (alternative to tailscale)
Setup a tailscale to enable GitHub Webhooks to your development environment¶
-
Sign up/Login to tail tailscale
-
Go to tailscale admin console
We use tailscale on Kubernetes (minikube), configuring it:
-
Go to tailscale admin console -> ACL
Include or update the
tagOwnersAdd
tag:k8sto thenodeAttrs: -
Create an OAuth in Settings > OAuth clients (https://login.tailscale.com/admin/settings/oauth)
Create an OAuth client in the OAuth clients page of the admin console. Create the client with Devices Core and Auth Keys write scopes, and the tag
tag:k8s-operator.This is well described in the official doc
Your new OAuth client's Client ID and Client Secret will be displayed—copy these values now as you'll need them in the next step.
-
Save your tailscale DNS
It might look like
tail<some hash>.ts.net -
Export them in your terminal
export TS_CLIENT_ID=<client id> export TS_CLIENT_SECRET=<client secret> export TS_DNS=tail<some hash>.ts.netNOTE: If you close the terminal, you will need to re-export these values.
-
Test secrets
export TS_ACCESS_TOKEN="$(
curl -sS \
-d "client_id=${TS_CLIENT_ID}" \
-d "client_secret=${TS_CLIENT_SECRET}" \
"https://api.tailscale.com/api/v2/oauth/token" \
| jq -r '.access_token'
)"
echo "$TS_ACCESS_TOKEN"
curl -sS \
-H "Authorization: Bearer ${TS_ACCESS_TOKEN}" \
"https://api.tailscale.com/api/v2/tailnet/-/devices" \
| jq .
- Enabling HTTPS
Official documentation: https://tailscale.com/docs/how-to/set-up-https-certificates
Go to the dns configuration page: https://login.tailscale.com/admin/dns
HTTPS Certificates -> Click Enable HTTPS...
Create a tailscale GitHub App¶
NOTES:
- Replace
<OTTERDOG-WEBAPP>by yourtail<some hash>.ts.net(tailscale) orotterdog.<your reserved domain>(ngrok) - You can always double check the URL at https://login.tailscale.com/admin/machines as multiple instances
of your development environment can generate
otterdog-1,otterdog-2...
It is required if you are the integration with GitHub (Create a GitHub app)
- Go to your organization
https://github.com/organizations/<ORG> - Click Settings.
- In the left sidebar, select <> Developer settings
- Click GitHub Apps
- New GitHub App
Basic Information
- Add GitHub App name:
<choose a name> - Homepage URL:
<OTTERDOG-WEBAPP>
Webhook
- [X] Active
- Webhook url:
<OTTERDOG-WEBAPP>/github-webhook/receive - Secret: Choose the secret
Add the following permissions and events:
Repository Permissions
| Permission | Access Level |
|---|---|
| Actions | Read & Write |
| Administration | Read & Write |
| Codespaces secrets | Read & Write |
| Commit statuses | Read & Write |
| Contents | Read & Write |
| Custom properties | Read & Write |
| Dependabot secrets | Read & Write |
| Environments | Read & Write |
| Issues | Read only |
| Metadata | Read only |
| Pages | Read & Write |
| Pull requests | Read & Write |
| Secrets | Read & Write |
| Variables | Read & Write |
| Webhooks | Read & Write |
| Workflows | Read & Write |
Organization Permissions
| Permission | Access Level |
|---|---|
| Administration | Read & Write |
| Custom Organization Roles | Read & Write |
| Custom properties | Admin |
| Members | Read only |
| Organization codespaces secrets | Read & Write |
| Organization dependabot secrets | Read & Write |
| Plan | Read only |
| Secrets | Read & Write |
| Variables | Read & Write |
| Webhooks | Read & Write |
The permissions for Codespaces and Dependabot secrets are only used when the default configuration defines the functions that create these secrets, see Dependabot and Codespaces secrets.
Events
| Event |
|---|
| Issue comment |
| Pull request |
| Pull request review |
| Push |
| Workflow job |
| Workflow run |
Note
When permissions are added to an existing GitHub App, each installation keeps its previous
permissions until an organization owner accepts the new ones in the organization settings
(Settings > GitHub Apps > Configure > Review request).
The otterdog app should appear in the organization settings > Third-party Access > GitHub Apps:
https://github.com/organizations/otterdog-
Install the GitHub App in the organization¶
Once the app is created, you need to install it in your organization:
https://github.com/organizations/otterdog-
Click Install next to your organization and grant the required permissions.
Configure the values.yaml to setup your otterdog webapp¶
This file must be set at the root level of your otterdog fork project.
config:
configOwner: "otterdog-<github username>" # GitHub organization hosting the otterdog.json
configToken: "" # GitHub token — no specific permissions required, used only for rate-limiting
dependencyTrackToken: "" # Dependency Track API token
github:
webhookSecret: "" # webhook secret as configured for the GitHub App
appId: "" # The App ID created in GitHub
appPrivateKey: "" # TApp private key
NOTE: In the dev configuration, the Otterdog webapp uses the following repositories by default:
You can override these defaults in values.yaml
It is recommended to create the repository otterdog-configs and add the otterdog.json file.
Example of otterdog.json
{
"defaults": {
"jsonnet": {
"base_template": "https://github.com/<GitHub Username>/otterdog#otterdog/resources/defaults/otterdog-defaults.libsonnet@main",
"config_dir": "orgs"
}
},
"github": {
"config_repo": ".otterdog"
},
"organizations": [
{
"name": "otterdog-<GitHub Username>",
"github_id": "otterdog-<GitHub Username>"
}
]
}
Run otterdog with tailscale¶
Make sure you have the eclipse-csi, tailscale, and dependency-track Helm chart repositories added:
helm repo add dependency-track https://dependencytrack.github.io/helm-charts
helm repo add eclipse-csi https://eclipse-csi.github.io/helm-charts
helm repo add tailscale https://pkgs.tailscale.com/helmcharts
Start the otterdog webapp with the tailscale tunnel:
You can verify the machine is registered at https://login.tailscale.com/admin/machines.
The Otterdog WebApp is reachable at https://otterdog.tail<some hash>.ts.net
Trigger the Otterdog initialization:
Dependency Track is reachable at https://sbom.tail<some hash>.ts.net (it still needs to be configured — see below)
Setup ngrok to enable GitHub Webhooks to your development environment¶
Alternative to the tailscale tunnel above.
-
Sign up/Login to ngrok
-
Go to the ngrok dashboard
We use the ngrok Kubernetes Operator (minikube), configuring it:
-
Get your API Key from https://dashboard.ngrok.com/api and your Authtoken from https://dashboard.ngrok.com/get-started/your-authtoken
-
Reserve a domain in https://dashboard.ngrok.com/domains
NOTE: Free ngrok domains (e.g.
<something>.ngrok-free.dev/.ngrok-free.app) do not support subdomains — only a custom domain you own, with wildcard DNS delegated to ngrok on a paid plan, does (see ngrok custom domains).NGROK_DOMAINbelow is therefore used as-is (nootterdog.prefix) for the Otterdog webapp. Dependency Track is not exposed via ngrok in this dev setup — access it withkubectl port-forwardinstead (see [Optional] Configure dependency track below). -
Export them in your terminal
export NGROK_API_KEY=<api key> export NGROK_AUTHTOKEN=<authtoken> export NGROK_DOMAIN=<your reserved domain>NOTE: If you close the terminal, you will need to re-export these values.
Run otterdog with ngrok¶
Alternative to #### Run otterdog with tailscale above.
Make sure you have the eclipse-csi, ngrok, and dependency-track Helm chart repositories added:
helm repo add dependency-track https://dependencytrack.github.io/helm-charts
helm repo add eclipse-csi https://eclipse-csi.github.io/helm-charts
helm repo add ngrok https://charts.ngrok.com
Start the otterdog webapp with the ngrok tunnel:
The Otterdog WebApp is reachable at https://<your reserved domain>
Trigger the Otterdog initialization:
Dependency Track is not exposed via ngrok; reach it with:
then open http://localhost:8080 (it still needs to be configured — see below)
Verify webhook delivery¶
Once the service is running and the GitHub App is installed in your organization, verify that webhooks are correctly reaching the backend by sending a ping event from the app's advanced settings:
https://github.com/organizations/otterdog-
Click Redeliver on the most recent ping delivery to trigger a test event. Check the otterdog backend logs to confirm the ping was received:
[Optional] Test the Playground with the documentation¶
The Playground of the webapp is available at /playground, it lists the examples of the Configuration Guides next
to the editor. It evaluates them with the default configuration of the instance, or with the example template of
otterdog (otterdog/resources/defaults, /playground?template=example) which the examples are validated with. Complete
examples of the documentation link to it with the example preloaded and the example template selected. To make these
links target your development environment, serve the documentation with the target that matches the way you started
the webapp, in a second terminal:
| Webapp started with | Documentation served with | Playground links target |
|---|---|---|
make dev-webapp |
make docs-serve-dev |
$OTTERDOG_DEV_URL, http://localhost:5000 by default |
make dev-webapp-tunnel, make dev-webapp-tunnel-local |
make docs-serve-tunnel |
https://otterdog.$TS_DNS |
make dev-webapp-ngrok, make dev-webapp-ngrok-local |
make docs-serve-ngrok |
https://$NGROK_DOMAIN |
The webapp started with make dev-webapp is not exposed, forward its port first:
Then open the documentation at http://127.0.0.1:8000, e.g. the
Configuration Guides, and follow the "Open in the Playground" link below an example.
The webapp started with any make dev-webapp* target links the examples of its Playground to the documentation served
with make docs-serve*, at http://127.0.0.1:8000/ by default. Both take this address from the variable
DOCS_DEV_ADDR of the Makefile, set it for both to serve the documentation on another port, e.g.:
make dev-webapp-ngrok DOCS_DEV_ADDR=127.0.0.1:8001
make docs-serve-ngrok DOCS_DEV_ADDR=127.0.0.1:8001
The webapp gets this address as value config.documentationUrl of the Helm chart (environment variable
DOCUMENTATION_URL), supported from version 1.6.0 of the chart: with an earlier chart, use the -local targets, which
deploy the chart of a helm-charts checkout. Outside of development, the Playground links to
https://csi.eclipse.dev/otterdog/ unless config.documentationUrl is set.
The Playground of a project starts with the current configuration of its organization, once the webapp fetched it
again, e.g. after calling /internal/init. Its button "Propose on GitHub" validates the modified configuration with
otterdog, asking to confirm if it has errors, then copies it and opens it in the editor of GitHub, where the user
creates the pull request from their own account. It opens the editor on the default branch of the configuration
repository, which is also known once the configuration has been fetched again.
[Optional] Configure dependency track¶
-
Access
https://sbom.tail<some hash>.ts.net(tailscale) orhttp://localhost:8080viakubectl port-forward(ngrok, see above) — default DependencyTrack credentials (First time will ask to change password and re-login) -
To generate the
dependencyTrackToken, go toAdministration>Access Management>Teams -
Create a Team or choose one (i.e.
Automation) create and API Key. -
Use this API Key as
dependencyTrackTokeninvalues.yaml
It will reload automatically.
Test otterdog client¶
This section walks through basic end-to-end testing of the otterdog CLI against your development organization.
1. Test GitHub web access¶
Export your credentials and set the path to your local otterdog configuration project, then verify that web-based login works:
export OTTER_API_TOKEN=...
export OTTER_USERNAME=...
export OTTER_PASSWORD=...
export OTTER_TOTP_SEED=...
export OTTERDOG_CONFIG_ROOT="/path/to/your/otterdog-config"
otterdog web-login otterdog-<GitHub Username>
NOTE: These environment variables must be re-exported in every new terminal session.
2. Import and push the organization configuration¶
Import the current state of your GitHub organization and push the generated configuration to the .otterdog repository:
This creates the initial jsonnet configuration file under orgs/otterdog-<GitHub Username>/ in your config project.
3. Fetch the remote configuration¶
Fetch the configuration stored in the remote .otterdog repository to ensure it is in sync with your local state:
4. Create a test repository¶
Edit the organization jsonnet configuration file:
Add a new repository entry:
If the file contains org-level settings that conflict with the defaults (e.g. settings already defined in otterdog-defaults.libsonnet), remove the duplicates. For example, the following block can be trimmed down to only the settings you want to override:
orgs.newOrg('otterdog-<GitHub Username>', 'otterdog-<GitHub Username>') {
settings+: {
members_can_change_repo_visibility: true,
members_can_create_private_pages: true,
members_can_create_private_repositories: true,
members_can_create_public_repositories: true,
members_can_create_teams: true,
members_can_delete_repositories: true,
},
Apply the changes to GitHub:
Test otterdog PR¶
Clone the .otterdog repository:
Change description of test-repo:
Edit the organization jsonnet configuration file:
Change repo-test description:
Create a specific branch and commit the modification:
git checkout -b "feat/repo_desc"
git add .
git commit -s -m "feat: change repo-test description"
git push origin "feat/repo_desc"
Then open a PR from this branch: https://github.com/otterdog-<GitHub Username>/.otterdog/pull/new/feat/repo_desc