Skip to content

Spa webapp - #479

Merged
gabriel-samfira merged 6 commits into
cloudbase:mainfrom
gabriel-samfira:spa-webapp
Aug 16, 2025
Merged

Spa webapp#479
gabriel-samfira merged 6 commits into
cloudbase:mainfrom
gabriel-samfira:spa-webapp

Conversation

@gabriel-samfira

@gabriel-samfira gabriel-samfira commented Aug 12, 2025

Copy link
Copy Markdown
Member

This PR includes multiple changes. There are a number of fixes and one big feature: Web UI for GARM in the form of a single page application.

It is written in svelte and uses a generated REST client, built from the swagger definitions, the websocket interface for live updates of entities and eager loading of everything except runners, as users may have many runners and we don't want to load hundreds of runners in memory.

Proper pagination should be implemented in the API, in future commits, to avoid loading lots of elements for no reason.

To enable the web UI, add the following to your config:

[apiserver.webui]
  enable = true

You will then be able to access your UI at https://garm.example.com/ui/.

@gabriel-samfira
gabriel-samfira force-pushed the spa-webapp branch 4 times, most recently from ca673a6 to c48b3ae Compare August 12, 2025 12:48
There are some inconsistencies in the way the API returns some
values for pools and scale sets. This is due to not preloading
the appropriate relations.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Add swagger annotations to models to allow generating a full swagger
definition. This will help generate clients in other languages if needed.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Filter out gitea tools to only consider archived downloads. This
should help in situations where bandwidth is more important than
CPU time used to unarchive the tools.

Also a drive by fix for scale sets cleanup.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This change considers cookies as a source for the JWT token.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
@gabriel-samfira
gabriel-samfira force-pushed the spa-webapp branch 3 times, most recently from 1dda7f6 to 53f141c Compare August 12, 2025 14:12
@gabriel-samfira

Copy link
Copy Markdown
Member Author

CC @ChristopherHX

Hopefully this should help from a UX perspective. I also updated the building_from_source.md document to contain a bit more info. It can still be improved, but at least it is a bit more useful now.

@gabriel-samfira
gabriel-samfira force-pushed the spa-webapp branch 3 times, most recently from 2515ca9 to 119700f Compare August 14, 2025 21:58

@ChristopherHX ChristopherHX left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will probably not come to the point to try this out in the next two weeks, but I am looking forward to this.

Comment thread Makefile
cp -r webapp/build/* webapp/assets/

.PHONY: generate
generate: ## Run go generate after checking required tools are in PATH

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document the new required tools? Some of them are only mentioned in the webapp guide

even if another docs document mentions make generate

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Trying to find a good place to have those docs so people don't have to grep to get to them.

Comment thread database/common/store.go
}

//go:generate mockery --name=Store
//go:generate go run github.com/vektra/mockery/v2@latest

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So mockery binary no longer needed in PATH. Great :)

Comment thread webapp/README.md Outdated

- **Make changes**: Edit source files in `webapp/src/`
- **Rebuild**: Run step 2 above to rebuild and deploy changes
- **No dev server**: The webapp is always served by the GARM binary at `/ui/` endpoint

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document nginx reverser proxy via docker/podman? I was too lazy to actually solve my similar problem, possible I only updated my web code ca. 3 times in 5 years.

e.g. tell nginx to serve the dev server files and route garm endpoints at the same time

Should save much time in edit + rebuild loop

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I though about having this as a separate project. Perhaps as a submodule or to just serve it up via nginx. While people can still do that, even with the stuff embedded, it's usually easier to run if it comes from the same service the UI calls into. In your load balancer/reverse proxy, you'd only have to worry about proxy passing everything to the garm service.

In development, you can still run make build-webui and just have nginx serve the resulting static content when you access /ui via a simple location parameter. Heck, you can even use the development server offered by npm with hot reload during development, and have the /ui location proxy pass to the npm server.

But when deployin, I think embedding it would be easiest for most users. There is also the "promise" that whatever ships with a version should work with that version.

I will definitely document the various development options and potentially ways for people to use nginx to serve the UI instead of the embedded version.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes embedding is the right approach for deploying/releasing such an application.

Just about development of an spa app on a foreign server component. I am not someone who would optimize serving assets via cdn.

go-gitea has a buildtag for including the ui or serving it from the folder next to the binary.

They require me to do TAGS="bindata" make build, but I almost never build without that tag myself. Good to embed by default

@gabriel-samfira gabriel-samfira Aug 16, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the ability to just run the dev server. Instructions on how to set it up will be in the webapp/DEV_SETUP.md. Also added some instructions on how to override the embedded UI when behind a reverse proxy like nginx. The dev server has hot reload on changes. Should save time in development.

The generated web UI included in the repo, should work without rebuilding, if nothing changed in the API. So a rebuild of GARM with no changes to the web UI or API, should just be:

make build

@gabriel-samfira
gabriel-samfira force-pushed the spa-webapp branch 6 times, most recently from 0e8186f to ab6fe9e Compare August 16, 2025 09:08
This change adds a single page application front-end to GARM. It uses
a generated REST client, built from the swagger definitions, the websocket
interface for live updates of entities and eager loading of everything
except runners, as users may have many runners and we don't want to load
hundreds of runners in memory.

Proper pagination should be implemented in the API, in future commits,
to avoid loading lots of elements for no reason.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
@gabriel-samfira
gabriel-samfira merged commit 8cc96db into cloudbase:main Aug 16, 2025
4 checks passed
@gabriel-samfira
gabriel-samfira deleted the spa-webapp branch August 16, 2025 10:23
@gabriel-samfira

Copy link
Copy Markdown
Member Author

we can have followup PRs to fix anything that still needs to be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants