Advanced guide
Documentation · Quick start · API reference · 简体中文
This guide covers the workflows normally needed after the template project is running: template assets, localization, repeatable tests, and automated releases.
1. Template matching with COCO assets
ok-script stores template annotations in COCO format.
Why COCO annotations help
- Position hints: an annotation records the template's relative position in the source screenshot. The matcher can search a smaller region for better speed and accuracy.
- Resolution independence: annotate screenshots at the highest supported resolution, such as 4K. ok-script scales templates down for lower-resolution users.
- Centralized asset management: screenshots, categories, and bounding boxes remain connected instead of becoming an unstructured folder of cropped images.
Workflow
- Capture representative screenshots at the highest supported resolution.
- Annotate each reusable UI feature with a COCO-compatible tool.
label-studio==1.15.0is known to produce compatible exports; newer export formats may differ. - Place
result.jsonand its image directory under the application'sassetsdirectory. - Run
python main_debug.pyand start the application. Debug mode detects the COCO data, crops annotated regions, and optimizes the templates. - Reference category names from methods such as
find_feature,find_one, andwait_feature.
Use distinctive regions with minimal animation. Avoid including large backgrounds or changing text in a button template.
2. Internationalization
Application translations follow the Qt .ts/.qm workflow.
Translation directories
Store gettext application-language files in this structure when the template project uses .po files:
i18n/
├── en_US/LC_MESSAGES/ok.po
└── zh_CN/LC_MESSAGES/ok.po
After editing translations, use Compile i18n in the application's developer tools to generate the binary files loaded at runtime.
For changes to ok-script itself, update every language file under ok/gui/i18n/, ensure no translation remains unfinished, and run:
.\compile_i18n.cmd
3. Automated task tests
TaskTestCase supplies a controlled task runtime. The key technique is self.set_image(), which replaces live capture with a stable screenshot.
from ok.test.TaskTestCase import TaskTestCase
from src.tasks.MyProblematicTask import MyProblematicTask
class TestUserIssue(TaskTestCase):
task_class = MyProblematicTask
def test_scenario_from_user_screenshot(self):
self.set_image("tests/user_screenshots/user_bug_report_01.png")
result = self.task.some_method_that_failed()
self.assertIsNotNone(result)
This makes recognition tests deterministic and allows a user's uploaded screenshot to become a permanent regression test.
Run all tests from the repository root:
python -m pytest tests
When running an individual test from PyCharm, set the working directory to the project root so relative paths such as tests/images/ resolve correctly.
4. Packaging and publishing with GitHub Actions
The boilerplate project's .github/workflows/build.yml can test, package, and publish releases when a version tag such as v1.0.0 is pushed. Packaging is driven by PyAppify and pyappify.yml.
The typical pipeline is:
- A
v*tag triggers the workflow. - Python and project dependencies are installed.
- Small Python dependencies may be copied into the update repository.
- Automated tests run as a release gate.
- update repositories are synchronized and release notes are generated.
- PyAppify creates Windows artifacts.
- GitHub Release publishes the notes and installers.
Inline small source dependencies
inline_ok_requirements includes ok-script and pyappify by default. Additional small, pure-Python packages can be included with repeated arguments:
python -m ok.update.inline_ok_requirements --tag "$env:RELEASE_TAG" `
--add-inlined-requirement custom-package=custom_package `
--add-inlined-requirement another-package=another_package
PACKAGE is the distribution name in requirements.txt; FOLDER is the package directory in site-packages. Large assets and platform-specific binaries should stay in the normal dependency and packaging flow.
Regional update sources
Multiple profiles in pyappify.yml can produce builds with different update repositories:
name: "my-app"
uac: true
profiles:
- name: "China"
git_url: "https://example.cn/owner/update.git"
- name: "Global"
git_url: "https://github.com/owner/update.git"
Each profile embeds its own update URL. A mainland China mirror can therefore coexist with a global GitHub source.
Build artifacts
A release commonly contains:
- a complete installer for each profile;
- an online installer that downloads resources;
- a launcher archive used to accelerate the next build.
The launcher archive is a build cache and is not normally intended for end users.
Reuse a previous launcher
If only task code changed, a workflow can reference a launcher from an earlier release and avoid rebuilding it:
use_release: https://api.github.com/repos/OWNER/REPOSITORY/releases/tags/v1.0.0
Update the URL to a release containing the compatible launcher archive.