Skip to main content

Source Control Integration

Source control is essential for all software projects. For Anemos projects, it serves an additional crucial role. Anemos stores its output files within the project directory. This practice means that these output files become part of the source control history.

Tracking output files is valuable not only for monitoring changes but also because these files can act as implicit tests for your project. When refactoring your Anemos code, you can examine the diff of the output files in your source control system to verify that the generated configurations remain correct.

Using Git

We will use Git for source control management. This tutorial assumes Git is already installed on your system. If not, you can download it from the official Git website.

First, initialize a new Git repository within your project directory by running:

git init

The anemos new command (run in the previous step of the tutorial) had already created a .gitignore file for you. This file tells Git to ignore transient files like the node_modules and .anemos/types directories.

.gitignore
.anemos
node_modules
dist/*
!dist/**/output

Now, stage all the project files and create the initial commit:

git add .
git commit -m "Initial commit"

Observing Changes with Diff

While you can push your project to a remote repository at this stage, let's first demonstrate how source control helps track changes.

Modify the main script file to change the name of the application:

index.ts
import * as anemos from "@ohayocorp/anemos";

const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

const name = "example-app2";
const namespace = "default";
const image = "nginx";
const replicas = 1;

builder.addDocument(
`deployment.yaml`,
`
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${name}
namespace: ${namespace}
spec:
replicas: ${replicas}
selector:
matchLabels:
app: ${name}
template:
metadata:
labels:
app: ${name}
spec:
containers:
- name: app
image: ${image}
ports:
- containerPort: 80
`);

builder.addDocument(
`service.yaml`,
{
apiVersion: "v1",
kind: "Service",
metadata: {
name: name,
namespace: namespace,
},
spec: {
selector: {
app: name
},
ports: [
{
protocol: "TCP",
port: 80,
targetPort: 80
}
]
}
});

builder.build();

Run the Anemos build command again to regenerate the output files based on this change:

anemos build --tsc . dist/index.js

Now, use git diff to see the changes in both your source file index.ts and the generated output files:

git diff

Git will display the differences. Notice how the change in the name variable affects the generated Kubernetes manifests:

index.ts
@@ -3,7 +3,7 @@ import * as anemos from "@ohayocorp/anemos";
const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

-const name = "example-app";
+const name = "example-app2";
const namespace = "default";
const image = "nginx";
const replicas = 1;
apiVersion: apps/v1
kind: Deployment
metadata:
- name: example-app
+ name: example-app2
namespace: default
spec:
replicas: 1
selector:
matchLabels:
- app: example-app
+ app: example-app2
template:
metadata:
labels:
- app: example-app
+ app: example-app2
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80

This demonstrates how Git tracks changes not only in your Anemos code but also in the generated output, providing a way to verify the impact of your modifications.

To discard the experimental changes made in this section and revert the files back to the state of the last commit (the "Initial commit"), run the following command:

git checkout -- .