Building 'Track'
I started working on 'Track', a simple full-stack rust app for managing personal data.
The project is open source at https://github.com/johnshaughnessy/track.
I have progressed through several stages: setting up local and cloud environments, integrating a web client, and setting up CI/CD pipelines. Here's a summary of what I've done so far.
Local Setup
My local development stack is comprised of Docker, Docker Compose, Git, and Bash. I've kept all the source code in a monorepo, synchronized via Git with GitHub, which also doubles as our CI/CD platform. One of the first scripts I created was setup_vm.sh
, which sets up a new VM, assuming Ubuntu but flexible enough for other distributions.
Tackling Standard Input in Scripts
A notable discovery was how processes can consume standard input, affecting the execution of scripts in Docker. After some trial and error, I learned to prevent Docker Compose from consuming the rest of a script as stdin, ensuring the remainder of my script executed as intended. I wrote more details in the dev log, here: DevLog#til-processes-can-consume-standard-input.
Cloud Setup: GCP and GitHub
I've set up 'Track' in Google Cloud Platform (GCP), using Compute Engine VMs for staging and production environments. I utilized Artifact Registry for Docker images and a GCS Bucket for static files. GitHub remains central to my operations, hosting documentation and managing CI/CD workflows.
Client-Side Evolution
Developing the web client, I opted for a Yew
-powered front end to communicate with an actix_web
server. I maintain a separation between the front-end and back-end codebases to accommodate different clients in the future. Deploying the client involves building with Trunk
and managing static files through GitHub workflows and GCS Buckets.
Streamlining with AI
Integrating AI, particularly ChatGPT and Copilot, has significantly boosted my productivity, especially when venturing into unfamiliar territories. These tools have helped me to quickly understand and use new libraries or tools, keeping a history of my steps for easy recall and guidance.
Deploying Migrations
I've crafted a workflow for deploying updates and handling migrations. Migrations pose a risk since they can alter the database, but I've mitigated this by automating their deployment and setting up backups for safety.
Resolving Timezone Conflicts
I encountered a conflict with timezones due to a mismatch between TIMESTAMP datatypes and my use of UNIX timestamps. This required adjusting migrations and considering switching to PostgreSQL's TIMESTAMP for better functionality.
The API and Server Overview
The server, written in Rust with a PostgreSQL backend, exposes a CRUD API. The server is authoritative over fields like ID and timestamps. Deploying changes to the server involves building Docker images and running automated tests.
Continual Improvements and To-Dos
As 'Track' evolves, I maintain a to-do list, marking off completed tasks and noting down future enhancements. Key accomplishments include setting up CI/CD pipelines, creating a clear distinction between staging and production environments, and automating the deployment of app updates and migrations.
- I've automated the storage of images in GCP's Artifact Registry and configured workflows for both staging and production.
- Development of the web client is ongoing. I still need to allow adding (non-random) weights, updating them, and graphing them.
- I'm planning to add typical web app things like accounts, authentication, and tls certs.
The wiki
The project's documentation is in the wiki. There I describe system architecture, deployments, server overview, and a detailed to-do list. My development log serves as a journal written mostly for myself.
Hands-on Local Development
For local development, I've scripted the setup to streamline the creation of Docker environments and manual database migrations. I've made the web client and server APIs accessible locally, and I've documented the initial setup steps meticulously for repeatability.
Leveraging Technologies
I've leveraged a suite of technologies to build and manage 'Track'. Here's a concise table outlining each technology and its use in the project:
Technology | Use |
---|---|
Docker | Containerization of development and production environments |
Docker Compose | Management of multi-container Docker applications |
Git | Source code version control |
Bash | Scripting and automation |
PostgreSQL | Persistent database state |
GitHub | Collaboration, documentation, and CI/CD |
GCP | Cloud infrastructure and services |
Yew | Front-end framework for Rust applications |
Actix Web | Rust framework for building web applications |
Trunk | Build, bundle & ship your Rust WebAssembly application |
Diesel | ORM and Query builder for Rust |
Closing Thoughts
I've wanted to build an app like this for some time now. Rust has been on my mind, but also I've wanted to just get basic CI/CD stuff set up with github workflows, configure postgres and manage migrations, learn the GCP versions of the services I'm familiar with from AWS, and see how I can start using AI in my day-to-day development workflow.
It's been a lot of fun and I plan to continue.