Navigation
Upgrading from 1.0.0 to 1.1.0
What to check in the database before upgrading, what changes for the owner of a paid licence and for API clients, which setting no longer applies
There is no special upgrade procedure: you update the image, the package or the chart, and the server applies the schema migrations itself at startup. In 1.1.0 there are 187 of them, 98 added after 1.0.0.
But four migrations deliberately stop the upgrade if the database holds data that cannot be merged on the owner’s behalf, and seven things change in behaviour. All of it is named below, item by item.
Before upgrading: four cases where the upgrade stops
The server does not start, does not touch the data and names the reason. Resolve it and repeat the upgrade.
| What was found in the database | What to do |
|---|---|
| NuGet packages in one repository differing only by the case of the name | Merge them into a single name - ready-made queries below |
NuGet versions that do not normalise; duplicates arising after normalisation; two .nupkg files for one version |
Keep one file per version, rename ambiguous versions |
| A username that matches a group path | Rename one of the two: after the upgrade the names live in one namespace |
| Licence activations referring to different installation ids | A sign that the database has already been split (two installations on one copy). Contact support before upgrading |
What changes for the owner of a paid licence
Enterprise capabilities moved from Pro to Max. SAML SSO sign-in and its settings, account management over SCIM, LDAP, the audit log, quota assignment, instance-level address rules, custom branding and knowledge draft limits are now unlocked by the Max edition. In 1.0.0 any valid Pro licence unlocked them.
An installation on a Pro licence that was using anything from that list will get 403 license_required on those calls. Migration: the vendor issues a Max activation file with the same licence id, and the expiry date need not move; seats are not doubled and no second row appears in the list of licences. It is entered in the same place as a renewal — renewal and change of edition.
What was paid for is not lost: a Pro licence issued before 15 September 2026 is honoured as Max until the end of the paid term.
Pro seats now work. A licence limited by seat count opens paid sections only to participants holding the seat flag — seats. Installations on a licence with an unlimited number of seats are not affected.
Entitlement is confirmed for a limited time. A signed activation response is now valid for 14–90 days depending on the subscription term, rather than until the end of the licence term. As long as signatures keep arriving — by the check-in to the licence server or by a file entered by hand — nothing changes. When they stop, paid capabilities close before the end of the paid term, but what was paid for does not burn — confirmation period.
What changes for API clients
The move to 1.1.0 is the only place where something later declared unchangeable does change: the /api/v1 compatibility promise takes effect with 1.1.0. Four things change.
The response shape became a page in three places. Instead of a top-level array you get {"items": [...], "next_cursor": ...}: issue comments, pull request comments and reviews; repository packages and the versions of a single package; the aggregate quota lists GET /admin/quotas/users and /groups.
An unknown field in a request body is rejected - 400 with code validation, and the text names the unrecognised fields by their full path. Previously such a field was dropped silently: a request carrying a visibility field named the way other platforms name it returned 201 and created a private repository. The rule applies only to GitRiver’s own API /api/v1; the compatibility layers, SCIM, OIDC, Git LFS, the package registry protocols and the runner protocol accept unknown fields as before.
A body that cannot be parsed comes back in the common envelope. It used to be 400 on broken JSON and 422 on JSON of the wrong shape, both with an English-language message from the library. It is now 400 with code validation. A body without Content-Type: application/json is answered with 415 in the same envelope. Parsing failures on path and query parameters changed the same way.
Three deliberate tightenings - where the previous behaviour answered success to something not done: PATCH /api/v1/users/{username} with is_admin or is_pro_seat and no right to set them answers 403 instead of 200; PUT .../environments/{env} requires the environment name in the body to match the one in the address; an empty sp_entity_id on a SAML provider is rejected.
The setting that no longer applies
GITRIVER_RATE_LIMIT_DISABLED no longer works. Its replacement is a list of exempt addresses: rate_limit_exempt_cidrs in the configuration or GITRIVER_RATE_LIMIT_EXEMPT_CIDRS in the environment.
An installation where that variable was set will find itself rate-limited after the upgrade. The server says so in the startup log.
Order of work
- Take a backup - before the upgrade, not after.
- Check the four cases from the first table.
- If you are on Pro and need the enterprise capabilities, request the Max activation file in advance.
- Update the image, package or chart and restart. Migrations apply themselves.
- Check the startup log: it will also say if
GITRIVER_RATE_LIMIT_DISABLEDis still in the environment.
If the upgrade stopped on NuGet packages
NuGet identifiers are case-insensitive: Newtonsoft.Json and newtonsoft.json are the same package, and the client requests it by its lowercase address. Early versions of GitRiver stored the name as given, so one repository could end up with two records. The migration that introduces uniqueness does not merge such records by itself - identical versions may differ in files and metadata - and stops the upgrade.
Find the conflicting records:
SELECT r.name AS repo, LOWER(p.name) AS package_id,
ARRAY_AGG(p.name ORDER BY p.created_at) AS variants
FROM packages p
JOIN repositories r ON r.id = p.repo_id
WHERE p.type = 'nuget'
GROUP BY r.name, p.repo_id, LOWER(p.name)
HAVING COUNT(*) > 1;
For each group choose the spelling that stays (usually the one published first) and move the versions over from the rest:
BEGIN;
UPDATE package_versions SET package_id = '<id of the package that stays>'
WHERE package_id = '<id of the extra package>';
DELETE FROM packages WHERE id = '<id of the extra package>';
COMMIT;
If the same version is published in both records, the UPDATE fails with package_versions_package_id_version_key: these are two different publications of the same version number. Decide which one is right, delete the other (DELETE FROM package_versions WHERE id = ...) and repeat the move.
After merging, restart the server - the migration will apply.