Docs Git Sync — autotests in git

Git Sync — your autotests live in git

Bind an autotest collection to a git repository. Mockarty pulls the tests
out of the repo (they show up ready to run) and pushes what you record or
edit back. Your team’s browser tests live in git next to your app code, review
in pull requests, and roll out to everyone automatically.

Git Sync is free — part of the base product on every plan.

Why

  • One source of truth. The tests live in your repo, versioned and reviewed
    like code — not locked inside one tool.
  • They show up by themselves. Point a repo at Mockarty once; a background
    sync keeps every teammate’s Mockarty fresh with what’s committed.
  • Record in the browser, commit from Mockarty. Record a flow (no Playwright
    inspector), then push it straight to the repo.
  • Runs everywhere. Desktop, on-prem, and cloud all read the same binding, so
    the same tests are available wherever you work.

Quick start (UI)

Open Settings → Git Sync → Add binding:

Field What it is
Repository URL https://github.com/you/tests.git (https only)
Branch default main
Subdirectory where the tests live in the repo, e.g. mockarty (optional)
What to sync UI tests, API collection, both, Wiki pages, boards, or test cases
Git username / Access token a personal access token — needed for private repos and to push. The token is never shown again, and is stored encrypted when the platform’s PII encryption key is configured. A public repo can pull with no token.
Auto-sync keep pulling by itself on a schedule

Then use the row actions: Pull (bring the repository’s changes in),
Push (publish your changes), Delete (unbind — the already-synced tests
stay in Mockarty).

Several devices, one repository

The same repository can be bound from several places at once — your Desktop,
a teammate’s Desktop, a shared Mockarty, and people editing the files directly.
Sync works like a git merge, so nobody’s work is overwritten:

  • Pull brings in what changed in the repository since your last sync. Your
    own edits that you have not pushed yet stay as they are.
  • Push publishes your changes as one commit. If the repository changed in
    the meantime, those changes are kept and brought to you as well.
  • A file deleted on one side is deleted on the other; it does not come back on
    the next sync.
  • A file changed on both sides differently is a conflict. Nothing is
    written anywhere until you decide: a window lists each such file with your
    version against the repository’s, line by line, and you choose Keep mine
    or Take the repository’s for each file, then Apply decisions.
    Cancelling leaves both sides untouched.

From the CLI (CI-friendly)

# bind a repo
mockarty-cli git-sync add \
  --repo https://github.com/you/tests.git \
  --kind ui --subdir mockarty --token "$GIT_PAT"

# list bindings (with last-sync status)
mockarty-cli git-sync list

# pull the latest tests, then run them
mockarty-cli git-sync pull <binding-id>

# push what you recorded back
mockarty-cli git-sync push <binding-id> --message "update login flow"

--output json prints machine-readable output for pipelines.

In a pipeline a conflict stops the command with a non-zero exit and the list of
files. Decide them in the command itself and run it again:

# keep the pipeline's version of one file
mockarty-cli git-sync push <binding-id> --resolve uitests/login-flow.json=local

# take the repository's version of every conflicting file
mockarty-cli git-sync pull <binding-id> --prefer remote

From the SDK

from mockarty import MockartyClient

client = MockartyClient(base_url="http://localhost:5770", api_key="mk_...")

b = client.git_sync.create_binding(
    "https://github.com/you/tests.git",
    kind="ui", subdir="mockarty", auth_token="ghp_…",
)
result = client.git_sync.pull(b["id"])          # {"commit": "...", "uiTestsFound": 12}
client.git_sync.push(b["id"], "update tests")   # commit your edits back

Go and Java expose the same operations (client.GitSync() / client.gitSync()).

For the AI agent

The agent can keep itself in sync with the repo:

  • git_sync_list_bindings — find the bound repo + its id
  • git_sync_pull — materialise the latest tests before running the suite
  • git_sync_push — commit tests it recorded back to the repo

When a file changed on both sides, the call answers with the conflicting files
and both versions; the agent shows them to you or passes its decision
(resolutions: local or remote per file) in the same call again.

In the cabinet, the conflict dialog lets you move between files and compare
both versions before applying your choices. A decision is tied to the exact
repository and local versions shown. If either side changes while the dialog
is open, the server refuses the old decision with 409; review the fresh
conflict instead of silently overwriting an edit you have not seen.

If you build a REST client for collaborative repositories, send
expectedBaseCommit and expectedRemoteCommit from the 409 response with
resolutions. For each chosen path, copy the response’s inBase, inLocal,
inRemote, baseDigest, localDigest, and remoteDigest into
expectedConflicts[path]. A path-only decision is accepted for older clients
but cannot protect a user from a concurrent edit; do not use it for a shared
repository.

An owner or administrator can bind a repository in the UI or through the
git_sync_create_binding agent tool. Use a narrowly scoped token for a private
repository; the token is write-only after binding.

What the repo looks like

Tests are stored as small, diff-clean files — one per test — so a change is a
readable one-file diff and a code review is easy:

<subdirectory>/
  uitests/
    _manifest.json
    checkout.json
    login-flow.json

Each file holds the test’s name, platform, and its recorded steps. Ephemeral
details (ids, timestamps, screenshots) are left out so the files stay stable
across syncs.

Give UI tests distinct names that also produce distinct file names within the
Space. For example, Login flow and login-flow would use the same file name.
Git Sync stops with a validation error instead of guessing which file to
update. Rename one of the tests and retry; neither test is deleted by the
failed sync. If names written only in non-Latin characters collide, add a distinct Latin word
or number to each name.

Wiki pages (kind = wiki)

A Wiki binding stores pages as wiki/<page-path>.md. If a page cannot be read,
its parent hierarchy is invalid, or two pages map to the same file path, sync
reports an error instead of publishing an incomplete Wiki. Correct the pages
and retry.

Boards (kind = boards)

A board binding stores each board as boards/<name>.excalidraw.json. Give boards
distinct names that produce distinct file names. If two boards map to the same
file name, or an imported board file is invalid or cannot be saved, sync reports
an error. Correct the board or file and retry; do not treat that revision as
imported successfully.

Test cases as code (kind = tcm)

A binding with What to sync = Test cases (as code) stores your TCM test
cases as markdown files with a YAML header — one file per case, folders
becoming directories:

<subdirectory>/
  tcm/
    auth/
      login-works.md
    checkout.md
---
id: 5f6a…                # stable case id (keeps re-pulls idempotent)
name: Login works
priority: high
tags: [smoke, auth]
customFields:
  Component: Auth
steps:
  - action: Open /login
    expected: Email and password fields visible
    data: user=admin
---
Free-form case description (markdown).
  • Push writes the namespace’s case catalogue out — review case changes in
    pull requests like any other code.
  • Pull applies edited files back: a file whose id matches an existing
    case updates it (metadata, custom fields; steps get a new version only when
    they actually changed), a brand-new file creates a case in the folder that
    matches its directory. Hand-written files without an id match by name, so
    a colleague can author a case entirely in the editor.
  • Automated steps stay automated. The file format describes a step the way a
    person reads it — name, action, expected result, test data. A step that runs
    itself also carries its run settings (what it calls, what it checks, what it
    passes on to later steps), and those are not written into the file. Editing
    the text of such a case in the repository and pulling it back keeps the run
    settings in Mockarty: the file decides the wording, Mockarty keeps the rest.
    One thing to know: a step is recognised by its name and action, so if you
    rewrite the action itself, the step counts as a new one and comes back as a
    manual step — set its run settings again in the interface.

Private repos & tokens

  • Use a personal access token with repo read (for pull) and write (for push)
    scope. GitHub ghp_…, GitLab glpat-…, and Bitbucket app passwords all work.
  • The token is never returned by the API or shown in the UI — only a “token
    stored” indicator — and is stored encrypted when the platform’s PII
    encryption key is configured.
  • Only https repository URLs are accepted, and a URL that points at a private
    or internal address is refused.

Good to know

A Git-connected API Tester collection syncs the same way: its unpushed edits
survive a pull, and a request changed on both sides is shown for you to decide.
The collection is saved as one operation — if saving any request fails, the
previous content remains. Read-only access does not permit pulling, pushing, changing the Git
connection or disconnecting it; editing access is required. If the connection
changes while a pull is running, repeat the pull using the current connection.

  • Pull is idempotent — pulling the same repo again updates the existing tests
    and pages instead of duplicating them.
  • Deleting a binding stops syncing but keeps the tests already in Mockarty.
  • Auto-sync pulls on a schedule so committed tests appear without a manual
    pull. Turn it off per binding if you prefer manual pulls.