Fix download URL mismatch
This commit is contained in:
@@ -1,88 +0,0 @@
|
|||||||
# RhemaWave
|
|
||||||
|
|
||||||
A Go-based fullscreen SDL2/OpenGL application for Linux kiosk systems. Displays proclamations with audio playback and animated visual patterns.
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
Development uses Nix for a reproducible build environment.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix develop # enter dev shell
|
|
||||||
go build -o bin/rhemawave rhemawave.go # build
|
|
||||||
./bin/rhemawave # run
|
|
||||||
./dev_scripts/reset.sh # reset database (if needed)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
- Nix with flakes enabled
|
|
||||||
- A display server (X11/Wayland) and audio device for running the application
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
- **Page-based UI** — SDL2/OpenGL 3.3 fullscreen rendering with a page stack for navigation
|
|
||||||
- **Proclamation player** — scrolling text display with synchronized audio playback
|
|
||||||
- **Startup validation** — WiFi, TOS acceptance, email, license key checks
|
|
||||||
- **Singleton managers** — ShaderManager, FontManager, Logger (initialized once via `sync.Once`)
|
|
||||||
|
|
||||||
### Key Directories
|
|
||||||
|
|
||||||
```
|
|
||||||
bin/ # build output (gitignored)
|
|
||||||
share/rhemawave/ # assets (fonts, shaders, proclamations, TOS)
|
|
||||||
internal/ # Go source packages
|
|
||||||
packaging/ # deployment configs (kiosk, updater, polkit)
|
|
||||||
dev_scripts/ # developer utilities
|
|
||||||
```
|
|
||||||
|
|
||||||
### Runtime Data
|
|
||||||
|
|
||||||
Stored in `~/.local/share/rhemawave/`:
|
|
||||||
|
|
||||||
- `data.db` — SQLite database (config, proclamations, logs)
|
|
||||||
- `log.txt` — application log
|
|
||||||
- `license_key` — license key file
|
|
||||||
|
|
||||||
### Development Rules
|
|
||||||
|
|
||||||
These rules must be followed during the development of RhemaWave to retain a
|
|
||||||
maintainable application.
|
|
||||||
|
|
||||||
1. The Application package is soley responsible for managing the database handler, and the
|
|
||||||
configuration cache. Internal packages may update the configuration within the database, and
|
|
||||||
then signal the application to refresh the cache via a callback function `refreshCache()`.
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
|
|
||||||
Deployed to kiosk hardware via NixOS.
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
### Deployment Pipeline
|
|
||||||
|
|
||||||
A manual walkthough of deploying Radiant Wave updates.
|
|
||||||
For reference later when writing automated actions.
|
|
||||||
|
|
||||||
1. Create a new branch for issue being worked on
|
|
||||||
2. Perform work
|
|
||||||
3. Merge to dev when done
|
|
||||||
4. Build dev with `nix build` to verify no errors
|
|
||||||
5. Checkout KioskConfig dev
|
|
||||||
6. Update rhemawave-dev with `nix flake update rhemawave-dev`
|
|
||||||
7. Build rhemawavekiosk-dev virtual machine
|
|
||||||
8. Test virtual machine for problems
|
|
||||||
9. Build dev-iso
|
|
||||||
10. Install dev-iso to a machine and check for problems
|
|
||||||
11. Checkout `main`
|
|
||||||
12. Merge `dev`
|
|
||||||
13. `nix flake update rhemawave`
|
|
||||||
14. Build virtual machine
|
|
||||||
15. Build iso image
|
|
||||||
16. Build commercial virtual machine
|
|
||||||
17. Build commercial iso image
|
|
||||||
18. Build Raspberry Pi img
|
|
||||||
19. Approve all virtual machines and iso images
|
|
||||||
20. Approve all machines update on their own
|
|
||||||
21. Rename all iso image to "radiantwavekiosk-iso-{system}-{MM-DD-YYYY}-{radiantwave-git-hash}.iso"
|
|
||||||
22. Upload iso images to file server
|
|
||||||
23. Move old iso images to `archives/` on the fileserver
|
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
#+TITLE: Radiantwave & KioskConfig Development & Release Pipeline
|
||||||
|
#+AUTHOR: Neil C.
|
||||||
|
#+DATE: 2026-06-23
|
||||||
|
#+OPTIONS: toc:nil num:nil
|
||||||
|
#+TAGS: development nixos radiantwave kiosk automation
|
||||||
|
|
||||||
|
* Radiant Wave
|
||||||
|
|
||||||
|
* Full Pipeline Workflow (Detailed)
|
||||||
|
|
||||||
|
** Development Phase
|
||||||
|
1. Create a new branch for the issue
|
||||||
|
2. Implement the changes for the issue
|
||||||
|
|
||||||
|
** Integration to =dev=
|
||||||
|
3. Open a pull request to =dev=
|
||||||
|
4. CI: Run =nix build= to verify no errors
|
||||||
|
5. CI: Run linting and unit tests
|
||||||
|
6. CI: Auto-update =rhemawave-dev= flake input
|
||||||
|
7. CI: Build all =dev= VMs in parallel (Kiosk, Commercial, RPi)
|
||||||
|
8. Merge the pull request to =dev= after CI passes
|
||||||
|
|
||||||
|
** Testing Phase
|
||||||
|
9. Run all VMs (Kiosk, Commercial, RPi) and test all functionality of the application on each VM
|
||||||
|
10. Install =dev-iso= to a test machine and verify installation and application functionality
|
||||||
|
|
||||||
|
** Release to =main=
|
||||||
|
11. Open a pull request from =dev= to =main=
|
||||||
|
12. CI: Build all =main= VMs in parallel (Kiosk, Commercial, RPi)
|
||||||
|
13. CI: Build all ISO images in parallel
|
||||||
|
14. CI: Auto-rename ISO images to format =radiantwave-{system}-{YYYY-MM-DD}-{git-hash}.iso=
|
||||||
|
15. CI: Upload ISO images to file server
|
||||||
|
16. CI: Move old ISO images to =archives/= on file server
|
||||||
|
17. Merge the pull request to =main= after CI passes
|
||||||
|
18. Tag the release (optional, for traceability)
|
||||||
|
|
||||||
|
* Automation Opportunities
|
||||||
|
|
||||||
|
This section describes which parts of the workflow can be automated via CI/CD, and how.
|
||||||
|
|
||||||
|
** Group 1: Development Validation (Steps 3-8)
|
||||||
|
- =What to automate=: PR triggering, =nix build=, linting, unit tests, flake updates, dev VM builds
|
||||||
|
- =How=: GitHub Actions workflow triggered on PR to =dev=
|
||||||
|
- =Why=: Catch integration errors before manual testing; ensure =dev= is always buildable
|
||||||
|
|
||||||
|
** Group 2: Testing (Steps 9-10)
|
||||||
|
- =What to automate=: VM functionality testing, ISO installation verification
|
||||||
|
- =How=: Scripted test suites, automated ISO installation in VMs
|
||||||
|
- =Why=: Reduce manual toil; increase test coverage and consistency
|
||||||
|
|
||||||
|
** Group 3: Release Pipeline (Steps 11-16)
|
||||||
|
- =What to automate=: Main VM/ISO builds, ISO renaming, file server uploads, archiving
|
||||||
|
- =How=: GitHub Actions workflow triggered on PR to =main=
|
||||||
|
- =Why=: Ensure consistent releases; eliminate human error in naming/uploading
|
||||||
|
|
||||||
|
* Preflight Checklist
|
||||||
|
|
||||||
|
- [ ] Create a new branch for the issue
|
||||||
|
- [ ] Implement the changes for the issue
|
||||||
|
- [ ] Open a pull request to =dev=
|
||||||
|
- [ ] Merge the pull request to =dev= after CI passes
|
||||||
|
- [ ] Run all VMs (Kiosk, Commercial, RPi) and test all functionality of the application on each VM
|
||||||
|
- [ ] Install =dev-iso= to a test machine and verify installation and application functionality
|
||||||
|
- [ ] Open a pull request from =dev= to =main=
|
||||||
|
- [ ] Merge the pull request to =main= after CI passes
|
||||||
|
- [ ] Tag the release (optional, for traceability)
|
||||||
|
|
||||||
|
* Automation Task List
|
||||||
|
|
||||||
|
** Group 1: Development Validation
|
||||||
|
- [ ] Set up GitHub Actions workflow for PRs to =dev=
|
||||||
|
- [ ] Configure =nix build= step
|
||||||
|
- [ ] Add linting and unit test steps
|
||||||
|
- [ ] Add flake auto-update step
|
||||||
|
- [ ] Configure parallel VM builds (Kiosk, Commercial, RPi)
|
||||||
|
- [ ] Verify workflow blocks PR merge on failure
|
||||||
|
|
||||||
|
** Group 2: Testing
|
||||||
|
- [ ] Create automated test scripts for VM functionality
|
||||||
|
- [ ] Set up automated ISO installation testing
|
||||||
|
- [ ] Integrate with CI for optional automated testing
|
||||||
|
|
||||||
|
** Group 3: Release Pipeline
|
||||||
|
- [ ] Set up GitHub Actions workflow for PRs to =main=
|
||||||
|
- [ ] Configure parallel VM builds
|
||||||
|
- [ ] Configure parallel ISO builds
|
||||||
|
- [ ] Add ISO auto-renaming step (using =git rev-parse HEAD= and =date +%Y-%m-%d=)
|
||||||
|
- [ ] Add file server upload step (=rsync= or similar)
|
||||||
|
- [ ] Add archive old ISOs step
|
||||||
|
- [ ] Verify workflow blocks PR merge on failure
|
||||||
@@ -20,12 +20,44 @@ type DownloadStatus struct {
|
|||||||
Err error // Error, if any
|
Err error // Error, if any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureDir checks if a dire
|
||||||
|
func ensureDir(path string) error {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err == nil {
|
||||||
|
if !info.IsDir() {
|
||||||
|
return fmt.Errorf("path exists but is not a directory: %s", path)
|
||||||
|
}
|
||||||
|
fmt.Printf("Directory already exists: %s\n", path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("error checking path: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0760 = rwxrw---- (owner: rwx, group: rw-, others: ---)
|
||||||
|
if err := os.MkdirAll(path, 0760); err != nil {
|
||||||
|
return fmt.Errorf("failed to create directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Directory created: %s\n", path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DownloadAudioFiles downloads multiple audio files and sends progress updates
|
// DownloadAudioFiles downloads multiple audio files and sends progress updates
|
||||||
// to the provided channel. The channel is closed when all downloads are complete.
|
// to the provided channel. The channel is closed when all downloads are complete.
|
||||||
func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string, destDir string) {
|
func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string, destDir string) {
|
||||||
defer close(progressChan)
|
defer close(progressChan)
|
||||||
|
|
||||||
urlBase := "https://files.rhemawavetech.com/audio/"
|
if err := ensureDir(destDir); err != nil {
|
||||||
|
logger.Error("failed to ensureDir %s %v", destDir, err)
|
||||||
|
progressChan <- DownloadStatus{
|
||||||
|
Msg: fmt.Sprintf("Failed to ensure directory exists: %v", err),
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
urlBase := "https://files.radiantwavetech.com/audio/"
|
||||||
|
|
||||||
// First, calculate the total size of files that need to be downloaded
|
// First, calculate the total size of files that need to be downloaded
|
||||||
totalSize := int64(0)
|
totalSize := int64(0)
|
||||||
@@ -87,6 +119,8 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string,
|
|||||||
url := urlBase + filename
|
url := urlBase + filename
|
||||||
destPath := filepath.Join(destDir, filename)
|
destPath := filepath.Join(destDir, filename)
|
||||||
|
|
||||||
|
// Ensure the destination directory exists
|
||||||
|
|
||||||
// Create the destination file
|
// Create the destination file
|
||||||
out, err := os.Create(destPath)
|
out, err := os.Create(destPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,13 +192,6 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.Close()
|
out.Close()
|
||||||
|
|
||||||
// Send completion for this file
|
|
||||||
progressChan <- DownloadStatus{
|
|
||||||
Max: totalSize,
|
|
||||||
Cur: totalDownloaded,
|
|
||||||
Msg: "Finished Downloading",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send final status
|
// Send final status
|
||||||
|
|||||||
Reference in New Issue
Block a user