diff --git a/.gitignore b/.gitignore index b8aa4aaabc..33698c9c5a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ ui/dist/app/* !ui/dist/app/gitkeep site/ *.iml +.tilt-bin/ # delve debug binaries cmd/**/debug debug.test diff --git a/Dockerfile.tilt b/Dockerfile.tilt new file mode 100644 index 0000000000..6e1b2d4624 --- /dev/null +++ b/Dockerfile.tilt @@ -0,0 +1,62 @@ +FROM docker.io/library/golang:1.24.1@sha256:c5adecdb7b3f8c5ca3c88648a861882849cc8b02fed68ece31e25de88ad13418 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN echo 'deb http://archive.debian.org/debian buster-backports main' >> /etc/apt/sources.list + +RUN apt-get update && apt-get install --no-install-recommends -y \ + curl \ + openssh-server \ + nginx \ + unzip \ + fcgiwrap \ + git \ + git-lfs \ + make \ + wget \ + gcc \ + sudo \ + zip \ + tini \ + gpg \ + tzdata \ + connect-proxy + +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +COPY hack/install.sh hack/tool-versions.sh ./ +COPY hack/installers installers + +RUN ./install.sh helm && \ + INSTALL_PATH=/usr/local/bin ./install.sh kustomize + +COPY hack/gpg-wrapper.sh \ + hack/git-verify-wrapper.sh \ + entrypoint.sh \ + /usr/local/bin/ + +# support for mounting configuration from a configmap +WORKDIR /app/config/ssh +RUN touch ssh_known_hosts && \ + ln -s /app/config/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts + +WORKDIR /app/config +RUN mkdir -p tls && \ + mkdir -p gpg/source && \ + mkdir -p gpg/keys + +COPY .tilt-bin/argocd_linux /usr/local/bin/argocd + +RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-repo-server && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-application-controller && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-dex && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-notifications && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \ + ln -s /usr/local/bin/argocd /usr/local/bin/argocd-commit-server + +# directory for Tilt restart file +RUN mkdir -p /tilt + +# overridden by Tiltfile +ENTRYPOINT ["/usr/bin/tini", "-s", "--", "dlv", "exec", "--continue", "--accept-multiclient", "--headless", "--listen=:2345", "--api-version=2"] \ No newline at end of file diff --git a/Dockerfile.ui.tilt b/Dockerfile.ui.tilt new file mode 100644 index 0000000000..bef84b99b8 --- /dev/null +++ b/Dockerfile.ui.tilt @@ -0,0 +1,9 @@ +FROM node:20 + +WORKDIR /app/ui + +COPY ui /app/ui + +RUN yarn install + +ENTRYPOINT ["yarn", "start"] \ No newline at end of file diff --git a/Tiltfile b/Tiltfile new file mode 100644 index 0000000000..31b57323a3 --- /dev/null +++ b/Tiltfile @@ -0,0 +1,282 @@ +load('ext://restart_process', 'docker_build_with_restart') +load('ext://uibutton', 'cmd_button', 'location') + +# add ui button in web ui to run make codegen-local (top nav) +cmd_button( + 'make codegen-local', + argv=['sh', '-c', 'make codegen-local'], + location=location.NAV, + icon_name='terminal', + text='make codegen-local', +) + +# add ui button in web ui to run make codegen-local (top nav) +cmd_button( + 'make cli-local', + argv=['sh', '-c', 'make cli-local'], + location=location.NAV, + icon_name='terminal', + text='make cli-local', +) + +# detect cluster architecture for build +cluster_version = decode_yaml(local('kubectl version -o yaml')) +platform = cluster_version['serverVersion']['platform'] +arch = platform.split('/')[1] + +# build the argocd binary on code changes +code_deps = [ + 'applicationset', + 'cmd', + 'cmpserver', + 'commitserver', + 'common', + 'controller', + 'notification-controller', + 'pkg', + 'reposerver', + 'server', + 'util', + 'go.mod', + 'go.sum', +] +local_resource( + 'build', + 'CGO_ENABLED=0 GOOS=linux GOARCH=' + arch + ' go build -gcflags="all=-N -l" -mod=readonly -o .tilt-bin/argocd_linux cmd/main.go', + deps = code_deps, + allow_parallel=True, +) + +# deploy the argocd manifests +k8s_yaml(kustomize('manifests/dev-tilt')) + +# build dev image +docker_build_with_restart( + 'argocd', + context='.', + dockerfile='Dockerfile.tilt', + entrypoint=[ + "/usr/bin/tini", + "-s", + "--", + "dlv", + "exec", + "--continue", + "--accept-multiclient", + "--headless", + "--listen=:2345", + "--api-version=2" + ], + platform=platform, + live_update=[ + sync('.tilt-bin/argocd_linux_amd64', '/usr/local/bin/argocd'), + ], + only=[ + '.tilt-bin', + 'hack', + 'entrypoint.sh', + ], + restart_file='/tilt/.restart-proc' +) + +# build image for argocd-cli jobs +docker_build( + 'argocd-job', + context='.', + dockerfile='Dockerfile.tilt', + platform=platform, + only=[ + '.tilt-bin', + 'hack', + 'entrypoint.sh', + ] +) + +# track argocd-server resources and port forward +k8s_resource( + workload='argocd-server', + objects=[ + 'argocd-server:serviceaccount', + 'argocd-server:role', + 'argocd-server:rolebinding', + 'argocd-cm:configmap', + 'argocd-cmd-params-cm:configmap', + 'argocd-gpg-keys-cm:configmap', + 'argocd-rbac-cm:configmap', + 'argocd-ssh-known-hosts-cm:configmap', + 'argocd-tls-certs-cm:configmap', + 'argocd-secret:secret', + 'argocd-server-network-policy:networkpolicy', + 'argocd-server:clusterrolebinding', + 'argocd-server:clusterrole', + ], + port_forwards=[ + '8080:8080', + '9345:2345', + '8083:8083' + ], +) + +# track crds +k8s_resource( + new_name='cluster-resources', + objects=[ + 'applications.argoproj.io:customresourcedefinition', + 'applicationsets.argoproj.io:customresourcedefinition', + 'appprojects.argoproj.io:customresourcedefinition', + 'argocd:namespace' + ] +) + +# track argocd-repo-server resources and port forward +k8s_resource( + workload='argocd-repo-server', + objects=[ + 'argocd-repo-server:serviceaccount', + 'argocd-repo-server-network-policy:networkpolicy', + ], + port_forwards=[ + '8081:8081', + '9346:2345', + '8084:8084' + ], +) + +# track argocd-redis resources and port forward +k8s_resource( + workload='argocd-redis', + objects=[ + 'argocd-redis:serviceaccount', + 'argocd-redis:role', + 'argocd-redis:rolebinding', + 'argocd-redis-network-policy:networkpolicy', + ], + port_forwards=[ + '6379:6379', + ], +) + +# track argocd-applicationset-controller resources +k8s_resource( + workload='argocd-applicationset-controller', + objects=[ + 'argocd-applicationset-controller:serviceaccount', + 'argocd-applicationset-controller-network-policy:networkpolicy', + 'argocd-applicationset-controller:role', + 'argocd-applicationset-controller:rolebinding', + 'argocd-applicationset-controller:clusterrolebinding', + 'argocd-applicationset-controller:clusterrole', + ], + port_forwards=[ + '9347:2345', + '8085:8080', + '7000:7000' + ], +) + +# track argocd-application-controller resources +k8s_resource( + workload='argocd-application-controller', + objects=[ + 'argocd-application-controller:serviceaccount', + 'argocd-application-controller-network-policy:networkpolicy', + 'argocd-application-controller:role', + 'argocd-application-controller:rolebinding', + 'argocd-application-controller:clusterrolebinding', + 'argocd-application-controller:clusterrole', + ], + port_forwards=[ + '9348:2345', + '8086:8082', + ], +) + +# track argocd-notifications-controller resources +k8s_resource( + workload='argocd-notifications-controller', + objects=[ + 'argocd-notifications-controller:serviceaccount', + 'argocd-notifications-controller-network-policy:networkpolicy', + 'argocd-notifications-controller:role', + 'argocd-notifications-controller:rolebinding', + 'argocd-notifications-cm:configmap', + 'argocd-notifications-secret:secret', + ], + port_forwards=[ + '9349:2345', + '8087:9001', + ], +) + +# track argocd-dex-server resources +k8s_resource( + workload='argocd-dex-server', + objects=[ + 'argocd-dex-server:serviceaccount', + 'argocd-dex-server-network-policy:networkpolicy', + 'argocd-dex-server:role', + 'argocd-dex-server:rolebinding', + ], +) + +# track argocd-commit-server resources +k8s_resource( + workload='argocd-commit-server', + objects=[ + 'argocd-commit-server:serviceaccount', + 'argocd-commit-server-network-policy:networkpolicy', + ], + port_forwards=[ + '9350:2345', + '8088:8087', + '8089:8086', + ], +) + +# docker for ui +docker_build( + 'argocd-ui', + context='.', + dockerfile='Dockerfile.ui.tilt', + entrypoint=['sh', '-c', 'cd /app/ui && yarn start'], + only=['ui'], + live_update=[ + sync('ui', '/app/ui'), + run('sh -c "cd /app/ui && yarn install"', trigger=['/app/ui/package.json', '/app/ui/yarn.lock']), + ], +) + +# track argocd-ui resources and port forward +k8s_resource( + workload='argocd-ui', + port_forwards=[ + '4000:4000', + ], +) + +# linting +local_resource( + 'lint', + 'make lint-local', + deps = code_deps, + allow_parallel=True, +) + +local_resource( + 'lint-ui', + 'make lint-ui-local', + deps = [ + 'ui', + ], + allow_parallel=True, +) + +local_resource( + 'vendor', + 'go mod vendor', + deps = [ + 'go.mod', + 'go.sum', + ], +) + diff --git a/docs/developer-guide/tilt.md b/docs/developer-guide/tilt.md new file mode 100644 index 0000000000..96751fe5a4 --- /dev/null +++ b/docs/developer-guide/tilt.md @@ -0,0 +1,148 @@ +# Tilt Development + +[Tilt](https://tilt.dev/) provides a real-time web UI that offers better visibility into logs, health status, and dependencies, making debugging easier compared to relying solely on terminal outputs. With a single `tilt up` command, developers can spin up all required services without managing multiple processes manually, simplifying the local development workflow. Tilt also integrates seamlessly with Docker and Kubernetes, allowing for efficient container-based development. Unlike goreman, which lacks dynamic config reloading, Tilt can detect and apply changes to Kubernetes YAML and Helm charts without full restarts, making it more efficient for iterative development. + +### Prerequisites +* kubernetes environment (kind, minikube, k3d, etc.) +* tilt (`brew install tilt`) +* kustomize +* kubectl + +### Running +1. Spin up environment by running `tilt up` in the root directory of the repo + * Resources will be deployed into the `argocd` namespace in the cluster that your `kubeconfig` is currently pointed to. + +2. Use `ctrl+c` to close tilt which stops watching files for changes and closes port-forwards. Everything deployed to the local cluster will be left in tact and continue to run. Run `tilt up` again to start up another session and pick up where you left off. + +### Cleanup +To remove all deployed resources in your local cluster including CRDs, run `tilt down` from the root of the repo. + +### Port Forwarding +Port forwarding is automatically setup from the cluster to localhost host for the folling ports: + +| Deployment | API | Metrics | Webhook | Debug | +|------------|-----|---------|---------|-------| +| argocd-server | 8080 | 8083 | | 9345 | +| argocd-repo-server | 8081 | 8084 | | 9346 | +| argocd-redis | 6379 | | | | +| argocd-applicationset-controller | | 8085 | 7000 | 9347 | +| argocd-application-controller | | 8086 | | 9348 | +| argocd-notifications-controller | | 8087 | | 9349 | +| argocd-commit-server | 8089 | 8088 | | 9350 | + +### Debugging ArgoCD +Each deployed pod running ArgoCD components uses delve to expose a debug port. Tilt is configured to forward each of those ports locally to `localhost`. IDEs can attach to the corresponding application to set break points and debug code running inside the cluster. + +| Deployment | Debug Host Port | +|-----------|------------| +| argocd-server | localhost:9345 | +| argocd-repo-server | localhost:9346 | +| argocd-applicationset-controller | localhost:9347 | +| argocd-application-controller | localhost:9348 | +| argocd-notifications-controller | localhost:9349 | +| argocd-commit-server | localhost:9350 | + + +#### VS Code +Add a `.vscode/launch.json` file with these configurations to support attaching to running pods corresponding to the service. + + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Connect to server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9345, + "host": "127.0.0.1" + }, + { + "name": "Connect to repo-server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9346, + "host": "127.0.0.1" + }, + { + "name": "Connect to applicationset-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9347, + "host": "127.0.0.1" + }, + { + "name": "Connect to application-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9348, + "host": "127.0.0.1" + }, + { + "name": "Connect to notifications-controller", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9349, + "host": "127.0.0.1" + }, + { + "name": "Connect to commit-server", + "type": "go", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 9350, + "host": "127.0.0.1" + } + ] +} +``` + +#### Goland +Add a `.run/remote-debugging.run.xml` file with these configurations to support attaching to running pods corresponding to the service. + +```xml + + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/manifests/dev-tilt/kustomization.yaml b/manifests/dev-tilt/kustomization.yaml new file mode 100644 index 0000000000..d5eb1926ca --- /dev/null +++ b/manifests/dev-tilt/kustomization.yaml @@ -0,0 +1,141 @@ +# This manifest is used by Tilt to deploy the argocd resources to the cluster. +namespace: argocd + +resources: + - namespace.yaml + - ui-deployment.yaml + - ../cluster-install-with-hydrator + +patches: + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-repo-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: remove + path: /spec/template/spec/initContainers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-commit-server + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: StatefulSet + name: argocd-application-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-dex-server + patch: |- + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/initContainers/0/securityContext + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-notifications-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: remove + path: /spec/template/spec/securityContext + - op: add + path: /spec/template/spec/containers/0/ports + value: + - name: debug + containerPort: 2345 + - name: metrics + containerPort: 9001 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-applicationset-controller + patch: |- + - op: replace + path: /spec/template/spec/containers/0/image + value: argocd + - op: remove + path: /spec/template/spec/containers/0/securityContext + - op: add + path: /spec/template/spec/containers/0/ports/0 + value: + name: debug + containerPort: 2345 + + - target: + group: apps + version: v1 + kind: Deployment + name: argocd-redis + patch: |- + - op: replace + path: /spec/template/spec/initContainers/0/image + value: argocd-job + - op: remove + path: /spec/template/spec/initContainers/0/securityContext diff --git a/manifests/dev-tilt/namespace.yaml b/manifests/dev-tilt/namespace.yaml new file mode 100644 index 0000000000..a040f2ba58 --- /dev/null +++ b/manifests/dev-tilt/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: argocd diff --git a/manifests/dev-tilt/ui-deployment.yaml b/manifests/dev-tilt/ui-deployment.yaml new file mode 100644 index 0000000000..d98b7adad2 --- /dev/null +++ b/manifests/dev-tilt/ui-deployment.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argocd-ui +spec: + selector: + matchLabels: + app: argocd-ui + template: + metadata: + labels: + app: argocd-ui + spec: + containers: + - name: argocd-ui + image: argocd-ui + env: + - name: ARGOCD_API_URL + value: https://argocd-server + - name: ARGOCD_E2E_YARN_HOST + value: "0.0.0.0" + ports: + - containerPort: 4000 + name: http diff --git a/manifests/dev-tilt/ui-service.yaml b/manifests/dev-tilt/ui-service.yaml new file mode 100644 index 0000000000..76c9c08ce5 --- /dev/null +++ b/manifests/dev-tilt/ui-service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: argocd-ui +spec: + selector: + app: argocd-ui + ports: + - port: 4000 + targetPort: http diff --git a/mkdocs.yml b/mkdocs.yml index 76d82e85cf..99a4585e10 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -222,6 +222,7 @@ nav: - developer-guide/extensions/ui-extensions.md - developer-guide/extensions/proxy-extensions.md - developer-guide/faq.md + - developer-guide/tilt.md - faq.md - security_considerations.md - Support: SUPPORT.md