QOps 3.0.12

August 2026

Edit a diff in Studio

Studio has a Diff editing view: the file opens as two panes, the base version on the left and your working file on the right, where you type. Review a change and edit it in the same place. The panes scroll together and unchanged code stays opposite itself, so the only lines that move are the ones you changed.

Open it from the Edit button on a file in the Diff panel, or from the status letter beside a changed file in the Studio file tree. The Editor / Diff editing toggle switches an open tab between the two views and carries your unsaved edits across.

Beside every changed block there are two buttons. Revert block puts that block back to the committed version in your buffer — nothing on disk or in git moves, and Ctrl+Z undoes it. Save and Stage block writes that one block to the file and stages it, leaving your other unsaved edits alone; the tab stays marked unsaved for them, so staging one block does not quietly commit you to the rest.

Compare picks which two versions you are looking at. It opens on Unstaged (worktree vs index), which is the editable one — stage a block and it leaves the comparison, so what remains on screen is what you still have to do. Staged and Working tree (all uncommitted) are for reading and are marked read-only; the ⓘ beside that marker explains why. Switching Compare never touches your unsaved edits.

The Portal opens without a licence

QOps-StartPortal opens the Portal on a machine whose licence has not been activated yet, so the screen where you enter the licence serial is reachable from the first run — no command line needed to get licensed.

The Portal now opens either way. Without a licence it takes you straight to the panel where the serial is entered and the machine-wide settings live, and Dashboard, Settings and Help stay usable — so you can look around, read the documentation, and get licensed, all from inside the product. Setting the serial is the only step: a machine activates itself on the first command that runs.

Everything else waits for the licence. Studio, Operations, Git, Diff, Lineage, Logs, Search and the Editor show a licence screen in place of their contents, giving the actual reason — no serial set, expired, refused by the licence service — and a button that opens the licence settings. Their navigation entries carry a padlock and still take you to that screen, so nothing in the Portal is a dead click. Once the licence is in place they open without a restart.

The operations themselves are unchanged and still licensed exactly as before. Prepare, Build, Reload, Publish, Release and every other cmdlet check the licence themselves, so an unlicensed machine cannot run them from the Portal any more than it could from a prompt. What changed is what you are told when one refuses: instead of a raw error about an internal licence check, you get a sentence naming the licence and a way to fix it.

If the Portal cannot determine the licence state at all — the QOps module is missing from PowerShell's module path, say — nothing is locked. A machine that cannot answer the question is not treated as an unlicensed one.

Starting the Portal without a command line

The Windows installer adds a QOps Portal entry to the Start menu and an icon on the Desktop, so getting in takes a click rather than a PowerShell prompt. Either one starts the Portal and opens it in your browser, and clicking it again while the Portal is already running opens the browser on the running one rather than flashing a console window at you.

Each of those is a question now, not a decision made for you. The wizard has a page for them: a box for the Start menu shortcut, a box for the Desktop shortcut, and a box for opening the Portal as soon as setup finishes. All three start ticked, so clicking through the wizard gives what it always gave; clear any of them and setup leaves that part out. The shortcuts themselves are unchanged — the same Portal, on the same port, started the same way.

An unattended install is deliberately not the same, because nobody is sitting in front of it to have cleared a box or to see a browser open. msiexec /qn on its own creates both shortcuts and does not open the Portal. Each part can be named on the command line, including asking for the browser anyway:

msiexec /i QOps-setup.msi /qn                             # both shortcuts, no browser
msiexec /i QOps-setup.msi /qn INSTALLSTARTMENUSHORTCUT=0  # no Start menu shortcut
msiexec /i QOps-setup.msi /qn INSTALLDESKTOPSHORTCUT=0    # no Desktop shortcut
msiexec /i QOps-setup.msi /qn LAUNCHPORTAL=2              # open the Portal when the install ends

Uninstall takes back whatever was created and has nothing to take back for anything that was declined. All of it applies whether QOps is installed for everyone on the machine or only for you.

The webhook now requires a secret

If your CI calls POST /api/v2/webhooks, it needs a secret from this release on. Run QOps-SetWebhookSecret on the machine running the Portal, under the account it runs as — it prints a token once — and send that token in the X-Webhook-Secret header from your pipeline.

Until you do, the webhook answers 401 and runs nothing. Existing pipelines that call it will stop working at the first call after the upgrade, so set the secret as part of updating rather than after.

Host address restrictions in the Portal

The Portal processes requests only for the hostnames and IP addresses it is configured for, and answers 400 Bad Request to any other address.

Default configuration

These are accepted out of the box, with nothing to set up:

  • localhost
  • 127.0.0.1
  • [::1]
  • the machine's own hostname

So QOps-StartPortal and http://localhost:5555 behave exactly as before.

Adding your own hostname or DNS alias

If you reach the Portal at some other address inside your network — a server name or a DNS alias — add that name to %USERPROFILE%\qopsconfig\portal.settings.json and restart the Portal:

{
  "AllowedHosts": "localhost;127.0.0.1;[::1];qops.example.com"
}

Two rules worth knowing before you edit it

  • Each name is matched exactly. localhost and 127.0.0.1 are separate entries, so a list containing only localhost answers 400 to http://127.0.0.1:5555 — which reads as the Portal being down.

  • Your value replaces the shipped list, it does not add to it. Keep the loopback names and append your own address to them.

Where the value is read from

AllowedHosts is read from portal.settings.json, and that file survives QOps-Update. Settings are applied in order: appsettings.json, then portal.settings.json, then an environment variable, then the command line.

The Portal port can be set once instead of every time

If 5555 is taken on your machine, or you simply want the Portal somewhere else, put the port in %USERPROFILE%\qopsconfig\portal.settings.json and it sticks — no -Port to remember on each start:

{
  "Portal": {
    "Port": 8080
  }
}

QOps-StartPortal with no arguments now starts there and opens http://localhost:8080; so do the Start menu and Desktop shortcuts, which have no command line to put a port on. -Port still wins whenever you pass it, including -Port 5555 — what counts is that you typed it, not the number. A port in that file that cannot be used (not a number, or outside 1–65535) is reported and the Portal starts on 5555 rather than leaving you to work out what happened.

This is the same file that already held the allowed browser origins, and it is deliberately not inside the Portal folder: QOps-Update rebuilds that folder from scratch, so settings kept there disappear at the next update.

Removed: the Urls key in the Portal's own appsettings.json. It had no effect when the Portal was started with QOps-StartPortal, so it is gone rather than left to mislead. Set the port in portal.settings.json instead.