Skip to content

feat(mister): add per-profile RetroAchievements config#1128

Merged
wizzomafizzo merged 2 commits into
mainfrom
feat/mister-ra-profile-config
Jul 21, 2026
Merged

feat(mister): add per-profile RetroAchievements config#1128
wizzomafizzo merged 2 commits into
mainfrom
feat/mister-ra-profile-config

Conversation

@wizzomafizzo

@wizzomafizzo wizzomafizzo commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • swap odelot RetroAchievements credentials and preferences with active MiSTer profile
  • seed profile configs from currently visible config while preserving transactional mount rollback
  • keep plaintext retroachievements.cfg files excluded from local and cloud backups
  • document custom-fork behavior and add profile/backup regression coverage

Closes #1102

Summary by CodeRabbit

  • New Features

    • Added RetroAchievements account configuration as MiSTer profile-managed data, including automatic copying into the selected profile and mounting over the live location.
    • Profile switching now preserves the correct RetroAchievements configuration per profile and updates ownership accordingly.
    • If the live RetroAchievements config is missing, the profile apply becomes a no-op.
  • Bug Fixes

    • Backup snapshots exclude authentication credentials (including local and cloud ZIPs).
    • Restore is blocked while media is active.
  • Documentation

    • Refreshed MiSTer guidance for backup methods and profile data swapping/deletion behavior, including deferred swaps during active media.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e5e654ec-74ab-4717-a0db-10b59abc3fbd

📥 Commits

Reviewing files that changed from the base of the PR and between 3dae247 and c05ffa7.

📒 Files selected for processing (4)
  • docs/api/methods.md
  • pkg/platforms/mister/profiledata.go
  • pkg/platforms/mister/profiledata_backup.go
  • pkg/platforms/mister/profiledata_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/platforms/mister/profiledata_test.go
  • pkg/platforms/mister/profiledata.go

📝 Walkthrough

Walkthrough

MiSTer profile data now includes retroachievements.cfg as a file-backed profile item. The implementation copies, mounts, switches, restores, and rolls back this file, while backup definitions exclude RetroAchievements-related files and documentation describes the behavior.

Changes

MiSTer profile data

Layer / File(s) Summary
Profile item modeling and file application
pkg/platforms/mister/profiledata.go, pkg/platforms/mister/profiledata_test.go
Typed profile specifications add RetroAchievements configuration as a file item with copying, mounting, idempotency, rollback, ledger support, and coverage for profile switching and storage-root behavior.
Profile backup restore resolution
pkg/platforms/mister/profiledata_backup.go
Restore preparation resolves profile item IDs to typed specifications and uses them for paths and errors.
Backup exclusions and behavior validation
pkg/platforms/mister/backup_test.go, pkg/service/backup/mister_integration_test.go, docs/api/methods.md
Tests exclude RetroAchievements-related files from backups, and documentation describes credential exclusion, profile-owned data, swapping, and restore constraints.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant profileDataManager
  participant prepareFileItem
  participant copyProfileFile
  participant MountLedger
  profileDataManager->>prepareFileItem: prepare retroachievements.cfg
  prepareFileItem->>copyProfileFile: copy live config into profile pool
  copyProfileFile-->>profileDataManager: profile config path
  profileDataManager->>MountLedger: record profile item ownership
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: per-profile RetroAchievements config support.
Linked Issues check ✅ Passed The changes implement the requested inclusion of retroachievements.cfg in MiSTer profile setup for individual users.
Out of Scope Changes check ✅ Passed The documentation and backup test updates are directly tied to the RetroAchievements profile feature and do not appear unrelated.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mister-ra-profile-config

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 69.07216% with 30 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/platforms/mister/profiledata.go 70.93% 15 Missing and 10 partials ⚠️
pkg/platforms/mister/profiledata_backup.go 54.54% 4 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
pkg/platforms/mister/profiledata.go (1)

106-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

File-kind path handling is RetroAchievements-specific, not actually generic.

profileItemTarget and prepareFileItem both hardcode retroAchievementsConfigFile rather than deriving the filename from item (e.g. item.id). The new kind field models a generic "file vs directory" dispatch, but the file branch only works correctly for exactly one item. If a second profileDataItemKindFile entry is ever added to profileDataItems, profileItemTarget and the pool path in prepareFileItem would both silently resolve to the RetroAchievements path instead of the new item's own file.

Consider adding a filename (or similar) field to profileDataItemSpec and using it in both places instead of the literal constant.

♻️ Sketch of a more generic dispatch
 type profileDataItemSpec struct {
 	id    string
 	label string
 	kind  profileDataItemKind
+	// filename is the config filename for kind == profileDataItemKindFile.
+	filename string
 }
 func profileItemTarget(root string, item profileDataItemSpec) string {
 	if item.kind == profileDataItemKindFile {
-		return filepath.Join(misterconfig.SDRootDir, retroAchievementsConfigFile)
+		return filepath.Join(misterconfig.SDRootDir, item.filename)
 	}
 	return filepath.Join(root, item.id)
 }
-	plan.pool = filepath.Join(profileDir, retroAchievementsConfigFile)
+	plan.pool = filepath.Join(profileDir, item.filename)

Also applies to: 263-299

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/platforms/mister/profiledata.go` around lines 106 - 111, Make file-item
path resolution generic by adding a filename field to profileDataItemSpec and
populating it for each profileDataItemKindFile entry. Update profileItemTarget
and prepareFileItem to use that item-specific filename instead of
retroAchievementsConfigFile, while preserving directory-item handling.
pkg/platforms/mister/profiledata_backup.go (1)

177-183: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the backup-eligible item list from profileDataItems instead of a hardcoded slice.

This is now one more hardcoded []string{profileDataItemSaves, profileDataItemSavestates} literal (alongside three already in backupPlan). The new typed profileDataItemSpec/kind model exists precisely to avoid this kind of duplication — filtering profileDataItems by kind == profileDataItemKindDir here would keep this list in sync automatically if a future directory-kind item is added.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/platforms/mister/profiledata_backup.go` around lines 177 - 183, The
backup loop in the profile-data backup method should derive eligible items from
profileDataItems rather than the hardcoded saves/savestates slice. Filter
profileDataItems for entries whose kind is profileDataItemKindDir, then process
those items while preserving the existing lookup, locking, and error behavior.
pkg/platforms/mister/profiledata_test.go (1)

468-487: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent path construction: some literals in this block bypass filepath.Join.

Lines 474, 476, and 478 hardcode POSIX-style path strings ("/media/usb0/saves", "/zaparoo/profiles/"+kidA().ID+"/saves", "/media/fat/saves"), while the rest of this same updated block (468, 482, 484-486, 487) correctly uses filepath.Join.

As per coding guidelines, "Use filepath.Join for path construction everywhere, including test files — never hardcode POSIX-style paths like "/roms/snes/game.sfc" as string literals."

♻️ Suggested fix
-	saves := mountsAt(m.mounts, "/media/usb0/saves")
+	saves := mountsAt(m.mounts, filepath.Join(mediaRootPath, "usb0", "saves"))
 	require.Len(t, saves, 1)
-	assert.Equal(t, "/zaparoo/profiles/"+kidA().ID+"/saves", saves[0].Root)
+	assert.Equal(t, "/"+filepath.Join("zaparoo", "profiles", kidA().ID, "saves"), saves[0].Root)
 	assert.Equal(t, "/dev/sda1", saves[0].Source)
-	assert.Empty(t, mountsAt(m.mounts, "/media/fat/saves"))
+	assert.Empty(t, mountsAt(m.mounts, filepath.Join(misterconfig.SDRootDir, "saves")))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/platforms/mister/profiledata_test.go` around lines 468 - 487, Update the
path assertions in the profile application test around mountsAt to construct all
paths with filepath.Join: use the existing mediaRootPath and relevant
storage/profile constants for the USB saves, profile saves, and FAT saves paths.
Preserve the current expected mount roots and sources while removing the
hardcoded POSIX-style path literals.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/platforms/mister/profiledata_backup.go`:
- Around line 177-183: The backup loop in the profile-data backup method should
derive eligible items from profileDataItems rather than the hardcoded
saves/savestates slice. Filter profileDataItems for entries whose kind is
profileDataItemKindDir, then process those items while preserving the existing
lookup, locking, and error behavior.

In `@pkg/platforms/mister/profiledata_test.go`:
- Around line 468-487: Update the path assertions in the profile application
test around mountsAt to construct all paths with filepath.Join: use the existing
mediaRootPath and relevant storage/profile constants for the USB saves, profile
saves, and FAT saves paths. Preserve the current expected mount roots and
sources while removing the hardcoded POSIX-style path literals.

In `@pkg/platforms/mister/profiledata.go`:
- Around line 106-111: Make file-item path resolution generic by adding a
filename field to profileDataItemSpec and populating it for each
profileDataItemKindFile entry. Update profileItemTarget and prepareFileItem to
use that item-specific filename instead of retroAchievementsConfigFile, while
preserving directory-item handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 61c4f3db-a97c-4bf4-9a78-0e3b75432591

📥 Commits

Reviewing files that changed from the base of the PR and between 694dd93 and 3dae247.

📒 Files selected for processing (6)
  • docs/api/methods.md
  • pkg/platforms/mister/backup_test.go
  • pkg/platforms/mister/profiledata.go
  • pkg/platforms/mister/profiledata_backup.go
  • pkg/platforms/mister/profiledata_test.go
  • pkg/service/backup/mister_integration_test.go

@wizzomafizzo
wizzomafizzo merged commit aad3b4a into main Jul 21, 2026
15 checks passed
@wizzomafizzo
wizzomafizzo deleted the feat/mister-ra-profile-config branch July 21, 2026 00:14
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.

Include retroachievements.cfg in the MiSTer setup for individual RetroAchievements.

1 participant