Build Text Forge from source
This page is a complete guide to get Text Forge running from source, to build a release from it, and to run its test suite.
Get the Engine
Text Forge is built on Godot 4.5.stable (v4.5.stable.official [876b29033]). Get that exact
version from the Godot download archive.
A newer Godot can open the project, but Text Forge is only tested against 4.5.x, and the export
templates have to match the editor version.
Get the Source
git clone https://github.com/text-forge/text-forge.git
Or open the official repo, click Code > Open with
GitHub Desktop and configure it there.
Important
If your clone is for contribution, always create a new branch for new PRs.
Run it from the Editor
Open the project.godot of the cloned repository with Godot 4.5. The first import takes a moment,
it builds the resources of the editor and of the bundled test addon.
F5runs the editor.F6runs the current scene.
The editor keeps its data in the user:// folder, which is
%APPDATA%\Godot\app_userdata\Text Forge on Windows. Deleting that folder resets the editor to a
fresh state, which is the way to recover from a broken setting.
Build a Release
1. Install the export templates
Download the export templates for 4.5-stable (Godot_v4.5-stable_export_templates.tpz) and
install them in the Godot editor: Editor > Manage Export Templates > Install from file. The
templates have to match the editor version, otherwise the export fails.
2. Export
Text Forge ships two presets in export_presets.cfg:
| Preset | Platform | Output |
|---|---|---|
Windows Desktop |
Windows | TextForge.exe |
Linux |
Linux | TextForge.x86_64 |
In the editor: Project > Export, pick the preset, and press Export Project. Pick an empty
folder, the export writes the executable there. Copy the data folder of the repository next to
it, it holds the menu configuration, the themes and the default modes. It is not a Godot resource,
so it is not part of the exported .pck and the editor cannot find it without it.
Note
Enable Export With Debug, the same way the release workflow exports. The official builds are debug exports, and a release export leaves out files the editor needs.
From the command line (Linux)
Unpack the export templates into the folder Godot looks in, the version has to match the editor:
unzip Godot_v4.5-stable_export_templates.tpz
mkdir -p ~/.local/share/godot/export_templates/4.5.stable/
cp templates/* ~/.local/share/godot/export_templates/4.5.stable/
Import the project once, so Godot builds its resources, then export:
godot --headless --import
godot --headless --export-debug "Linux" $(pwd)/TextForge.x86_64 --quit
The binary is the one that was written, run it from the folder that holds data:
./TextForge.x86_64
3. Package
A release archive holds the exported files plus the files that are not resources:
TextForge/ # the exported editor
data/ # menu configuration, themes, default modes
icon.png
README.md
CHANGELOG.md
SECURITY.md
LICENSE
4. Or let CI do it
The release workflow (.github/workflows/release.yml) does all of that for you. It is triggered by
pushing a tag:
git tag v0.5.0-stable
git push origin v0.5.0-stable
The workflow exports both presets, builds the two archives and attaches them to a draft GitHub
release. The draft is not published, review the notes and publish it when it looks right. Keep the
tag when you publish it: a draft published without its tag gets an untagged-<sha> tag, that tag
fires the workflow again and it puts the release back in draft.
Tags follow v<major>.<minor>.<patch>-<suffix>, for example v0.3.0-stable or v0.2.0-rc1. The
version in project.godot, the one in core/classes/static.gd (S.EDITOR_VERSION) and the
CHANGELOG.md entry belong to the same release.
Every change to a release needs the tag, not only the publish. A PATCH that sets the name or the
body without tag_name puts the tag of the draft back to untagged-<sha>:
gh api -X PATCH repos/text-forge/text-forge/releases/<id> -F tag_name=v0.5.0-stable -F name="0.5 - Stable" -F body=@notes.md
gh api -X PATCH repos/text-forge/text-forge/releases/<id> -F draft=false -F tag_name=v0.5.0-stable
The body of a file goes in with body=@file, a field with another name is ignored. The id of the
release comes from gh api "repos/text-forge/text-forge/releases?per_page=10" --jq '.[] | "\(.id)
draft=\(.draft) tag=\(.tag_name)"', gh release edit <tag> does not find a draft.
Run the Tests
The unit tests use gdUnit4, which is enabled as an addon
in project.godot. From the command line:
export GODOT_BIN=/path/to/godot
./addons/gdUnit4/runtest.sh -a res://tests/ # all suites
./addons/gdUnit4/runtest.sh -a res://tests/core/autoload/utils_test.gd # one suite
Headless runs need --ignoreHeadlessMode, and suites that drive the interface only pass inside
the editor, so run those from the gdUnit4 panel. There is no flag for a single test case, select
it in the panel.
The reports are written to reports/, the numbers of the last run are in
the test overview.