Development Setup

Development Setup

Complete guide for new contributors — from a fresh Windows machine to a working dev environment with CI/CD.

Prerequisites

Requirement Notes
Windows 10/11 Admin access required for GitLab Runner service
Icarus Installed via Steam — needed to use the editor (tests use bundled fixtures)
Python 3.10+ ✅ Check "Add to PATH" during install
Git for Windows Includes Git Bash — most commands below use it

Verify your installs:

python --version      # Python 3.10+ required
git --version         # Any recent version

No pip dependencies needed for the editor itself. The entire project uses only the Python 3 standard library (tkinter, json, struct, zlib).


1. Clone the Repository

git clone https://git.eurekaendeavors.com/root/icarus-pets.git
cd icarus-pets

You should see the full project structure described in the Architecture wiki page.


2. Get Your Mounts.json

The editor needs a Mounts.json save file to load your creatures. (Tests use bundled fixtures — no local save file needed.) Icarus stores these at:

%LOCALAPPDATA%\Icarus\Saved\PlayerData\{SteamID}\Mounts.json

Find yours:

ls "$LOCALAPPDATA/Icarus/Saved/PlayerData/"*/Mounts.json

You should see one or more paths like:

C:\Users\you\AppData\Local\Icarus\Saved\PlayerData\76561198012345678\Mounts.json

Important: You must have at least one tamed mount, pet, or farm animal stored at a station in-game for data to appear in this file. Creatures currently following you or active in the world may not be saved yet.

For local development, copy it into the project directory:

cp "$LOCALAPPDATA/Icarus/Saved/PlayerData/<YourSteamID>/Mounts.json" .

3. Run the Editor

python mount_editor.py

This launches the Tkinter GUI. You should see your mounts listed in the sidebar with the 4-tab interface (Overview, Genetics, Talents, Advanced). See the GUI Guide for usage details.


4. Run Tests Locally

Both test suites should pass before committing any changes.

Species Swap Tests (no test data needed)

python tests/test_species_swap.py

Expected: 13 tests, all , zero failures.

Roundtrip Tests (no setup needed)

python tests/test_roundtrip.py

Expected: Every mount across all locale fixtures in tests/sample_mounts/ parses and re-serializes to identical bytes. Tests 14 mounts across 2 locales (EN-US UTF-8, FR-FR UTF-16 LE) including accented names. No local Mounts.json needed.


5. Request a GitLab Account

Contact the project maintainer to get:

  1. A GitLab account on git.eurekaendeavors.com
  2. Developer (or higher) access to the icarus-pets project
  3. A Personal Access Token — go to Settings → Access Tokens → create one with api + read_repository + write_repository scopes

Save your token in .gitlab_token at the project root (this file is gitignored):

echo "glpat-your-token-here" > .gitlab_token

6. Install the GitLab Runner

The CI/CD pipeline runs on a local GitLab Runner installed on your dev machine. This is a Windows service that picks up jobs from the GitLab server.

6a. Download the Runner

mkdir -p /c/GitLab-Runner
curl -L -o /c/GitLab-Runner/gitlab-runner.exe \
  https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe

6b. Get Your Runner Registration Token

From the GitLab web UI:

  1. Go to Project → Settings → CI/CD → Runners
  2. Expand the Runners section
  3. Copy the registration token (starts with GR1348941...)

Or via the API (requires admin token):

TOKEN=$(cat .gitlab_token)
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
  "https://git.eurekaendeavors.com/api/v4/projects/1" \
  | python -c "import sys,json; print(json.load(sys.stdin)['runners_token'])"

6c. Register the Runner

/c/GitLab-Runner/gitlab-runner.exe register \
  --non-interactive \
  --url "https://git.eurekaendeavors.com/" \
  --registration-token "GR1348941_YOUR_TOKEN_HERE" \
  --executor "shell" \
  --shell "powershell" \
  --description "your-machine-name" \
  --tag-list "windows,python"

Important: Use --shell "powershell", not "cmd". The cmd shell is not properly supported and will fail with shell cmd not found.

The runner config is saved to config.toml in the current directory. Move it to the runner directory:

mv config.toml /c/GitLab-Runner/config.toml

6d. Verify the config

Check that the shell is set to powershell:

cat /c/GitLab-Runner/config.toml

You should see:

[[runners]]
  name = "your-machine-name"
  url = "https://git.eurekaendeavors.com/"
  executor = "shell"
  shell = "powershell"

6e. Install as a Windows Service

Open an Administrator PowerShell (right-click → Run as Administrator):

cd C:\GitLab-Runner
.\gitlab-runner.exe install --working-directory "C:\GitLab-Runner" --config "C:\GitLab-Runner\config.toml"
.\gitlab-runner.exe start

This requires admin access — the install command registers a Windows service that runs automatically on boot.

6f. Enable "Run Untagged Jobs"

By default, the runner only picks up jobs with matching tags. Enable untagged job execution so all pipeline jobs run:

Option A — GitLab UI: Go to Project → Settings → CI/CD → Runners → click the pencil icon on your runner → check "Run untagged jobs" → Save.

Option B — API:

TOKEN=$(cat .gitlab_token)
# First, find your runner ID
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
  "https://git.eurekaendeavors.com/api/v4/projects/1/runners" \
  | python -c "import sys,json; [print(f'#{r[\"id\"]}: {r[\"description\"]}') for r in json.load(sys.stdin)]"

# Then enable run_untagged (replace RUNNER_ID)
curl -s --request PUT \
  --header "PRIVATE-TOKEN: $TOKEN" \
  --data "run_untagged=true" \
  "https://git.eurekaendeavors.com/api/v4/runners/RUNNER_ID"

6g. Verify the Runner is Online

TOKEN=$(cat .gitlab_token)
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
  "https://git.eurekaendeavors.com/api/v4/projects/1/runners" \
  | python -c "import sys,json; [print(f'#{r[\"id\"]}: {r[\"description\"]} — {r[\"status\"]}') for r in json.load(sys.stdin)]"

Expected: status: online.


7. Configure the CI Pipeline

The .gitlab-ci.yml in the repo defines three stages with 14 jobs:

Job Stage Trigger Purpose
test:all test Every push Unified runner — all test_*.py files
test:roundtrip test Every push Binary roundtrip (bundled EN-US + FR-FR fixtures)
test:species_swap test Every push 13 species swap test cases
test:ue4_parser test Every push 28 UE4 binary parser tests
test:ue4_serializer test Every push 28 UE4 serializer tests
test:mount_model test Every push 28 MountModel API tests
test:species_swap_edge test Every push 22 edge case tests
test:save_backup test Every push Save/backup/restore tests
test:packaging test Every push Frozen-app path tests
test:refresh test Every push Refresh tool tests
test:talent_data test Every push Talent data integrity (35 tests)
test:changed_files_check test Every push Soft gate — warns on missing test changes
build:exe build Tags / [build] / Manual PyInstaller → IcarusPetEditor.exe
release:package release Tags only ZIP → Package Registry → Release link

No local configuration needed. All tests use bundled fixtures in tests/sample_mounts/. No MOUNTS_JSON path or local save file required.

Trigger the Pipeline

Push a commit to see the pipeline run:

git add -A && git commit -m "Test CI pipeline" && git push origin main

Monitor the pipeline via the GitLab UI (CI/CD → Pipelines) or via API:

TOKEN=$(cat .gitlab_token)
curl -s --header "PRIVATE-TOKEN: $TOKEN" \
  "https://git.eurekaendeavors.com/api/v4/projects/1/pipelines?per_page=1" \
  | python -c "import sys,json; p=json.load(sys.stdin)[0]; print(f'Pipeline #{p[\"id\"]}: {p[\"status\"]}')"

8. Install PyInstaller (for Build Stage)

The build:exe job installs PyInstaller automatically via pip, but you'll want it locally too for testing builds:

pip install pyinstaller

Test a local build using the build script:

python build.py

This cleans previous artifacts, runs PyInstaller with the project's .spec file, and reports the output:

✅ Build successful!
   Version:  v2.0.0
   Output:   dist/IcarusPetEditor.exe
   Size:     10.0 MB
   Time:     10.8s

Clean build artifacts only: python build.py --clean

Verify the exe works: ./dist/IcarusPetEditor.exe --version

Build Triggers in CI

The build:exe job runs when: - A version tag is pushed: git tag v2.0.0 && git push --tags - A commit message contains [build]: git commit -m "feature X [build]" - Manually via the GitLab CI/CD UI (play button on the pipeline)

Built .exe files are stored as pipeline artifacts (downloadable from GitLab, 30-day expiry).


9. Day-to-Day Development Workflow

Making Changes

# 1. Pull latest
git pull origin main

# 2. Make your changes
#    ... edit files ...

# 3. Run tests locally
python tests/test_species_swap.py
python tests/test_roundtrip.py

# 4. Commit and push
git add -A
git commit -m "Brief description of changes"
git push origin main

# 5. CI pipeline runs automatically — check it passes

Files You Should NOT Commit

These are gitignored — don't force-add them:

File Reason
Mounts.json Your personal save data
Mounts_edited.json Editor output file
.gitlab_token Your API credentials
config.toml Runner auth token
pak-files/ Extracted game data (large)
dist/, build/ PyInstaller output

Updating After Game Patches

When Icarus releases a game update that changes talent data, use the one-command refresh tool:

python scripts/refresh_talent_data.py

This auto-detects your Steam/Icarus installation, finds data.pak, and runs the full extraction pipeline: 1. Copies data.pak from your Steam install to pak-files/ 2. Extracts talent definition chunks (pak_extract.py) 3. Parses talent entries (pak_talent_extract.py) 4. Regenerates talent_data.py (generate_talent_data.py)

The tool reports any changes (new/removed talents, type counts) so you know what to review before committing.

Dry run — just check detection without running the pipeline:

python scripts/refresh_talent_data.py --detect

Manual path — if auto-detection fails:

python scripts/refresh_talent_data.py "D:\Steam\steamapps\common\Icarus\Icarus\Content\Data\data.pak"

After refresh, also update bestiary data:

python scripts/extract_bestiary.py
python scripts/add_bestiary_to_talent_data.py

See Architecture → Pak Extraction Pipeline for details.


Troubleshooting

shell cmd not found in CI jobs

Your runner's config.toml has shell = "cmd". Change it to shell = "powershell" and restart the runner service.

UnicodeEncodeError: 'charmap' codec can't encode character

The runner's PowerShell uses Windows cp1252 encoding. The .gitlab-ci.yml sets PYTHONIOENCODING: "utf-8" to fix this. Make sure this variable is present.

test:roundtrip fails with encoding errors

The roundtrip test handles both UTF-8 and UTF-16 LE encoded save files. If you see encoding-related failures, ensure: 1. The PYTHONIOENCODING: "utf-8" variable is set in .gitlab-ci.yml 2. The test fixtures in tests/sample_mounts/ are intact (not corrupted by line-ending conversion)

Runner shows offline in GitLab

# In admin PowerShell:
cd C:\GitLab-Runner
.\gitlab-runner.exe status    # Check if running
.\gitlab-runner.exe restart   # Restart the service

PyInstaller build fails with missing modules

Add --hidden-import MODULE_NAME to the PyInstaller command in .gitlab-ci.yml. Common ones: tkinter, tkinter.ttk.


See also: Architecture · GUI Guide · Binary Format

Back to Docs