Usage¶
Pubgrade connects repositories, whose CI publishes new images, with
subscribers, e.g. Pubgrade-Sidecar next to a deployment,
which Pubgrade notifies of them. The examples use <base URL> for the
address of Pubgrade, e.g. https://pubgrade.example.org.
Register a repository¶
curl --request POST '<base URL>/repositories' \
--header 'Content-Type: application/json' \
--data '{"url": "<repository URL>"}'
The response holds the repository's id and its access_token: the
repository's CI needs both to publish images. Keep the token secret.
A repository may declare build types, e.g., to tell releases from test
builds, with "build_types": ["production", "testing"] next to url. Each
build type is a name of letters, digits, ., _ and - (up to 64
characters, starting with a letter or digit); a repository declares at most
50. Its builds may then name one of them (see
Publish an image), and subscriptions may ask for some
of them only (see Subscribe to a repository).
Without build types, builds have no type, as before.
Register a user¶
Subscriptions belong to users, who must be verified by an admin. Admin users are set up in the configuration.
curl --request POST '<base URL>/users/register' \
--header 'Content-Type: application/json' \
--data '{"name": "<name>"}'
An admin verifies the user:
curl --request PUT '<base URL>/users/<user ID>/verify' \
--header 'X-Super-User-Id: <admin user ID>' \
--header 'X-Super-User-Access-Token: <admin access token>'
Subscribe to a repository¶
A verified user subscribes a callback URL, e.g. of a Pubgrade-Sidecar, to a tag or branch of a repository:
curl --request POST '<base URL>/subscriptions' \
--header 'X-User-Id: <user ID>' \
--header 'X-User-Access-Token: <user access token>' \
--header 'Content-Type: application/json' \
--data '{
"repository_id": "<repository ID>",
"callback_url": "<callback URL>",
"access_token": "<subscriber access token>",
"type": "<tag or branch>",
"value": "<tag or branch name>"
}'
Pubgrade sends access_token to callback_url with each notification, so use
https for anything outside the cluster. A subscription's value must equal
the tag or branch of a published image; the value * matches any of them,
e.g. every new tag. A repository takes at most 100 subscriptions by default
(the deployment can change this with
endpoints.subscriptions.max_per_repository); further ones get a 403.
A subscription may also list build_types, e.g., "build_types":
["production"], to get only builds of these types. Each must be declared by
the repository; otherwise the request gets a 400. Without build_types, or
with an empty list, the subscription gets all builds that match type and
value, as before. With a non-empty build_types (at most 50), builds
without a type don't match. The subscription's details (GET /subscriptions/<subscription
ID>) show its build_types, the repository's (GET /repositories/<repository
ID>) its declared build_types, and each build its build_type, if any.
Publish an image¶
The repository's CI builds and pushes the image, then publishes it:
curl --request POST '<base URL>/repositories/<repository ID>/builds' \
--header 'X-Project-Access-Token: <repository access token>' \
--header 'Content-Type: application/json' \
--data '{
"images": [{"name": "<image name>:<image tag>"}],
"head_commit": {"tag": "<tag name>"}
}'
If the repository declares build types, the build may name one of them with
"build_type": "<build type>"; a type that the repository doesn't declare
gets a 400. A build without a type reaches only subscriptions without
build_types, or with an empty list.
Notifications¶
Pubgrade notifies all subscriptions of the repository at the same time, with a
timeout per call (endpoints.subscriptions.notification_timeout in the
configuration, by default 10 seconds, for connecting and for the response).
Results per subscription, once all calls are done, are in the field
notifications of the build
(GET /repositories/<repository ID>/builds/<build ID>):
delivered: the subscriber answered with a 2xx status, so it accepted the notification. Pubgrade-Sidecar then rolls out in the background and reports the state atGET /deployment/<deployment name>(see its API).failed: another response, or none in time.skipped: the subscription doesn't match the build (itstype,valueorbuild_types).
Receiving notifications without the sidecar¶
Each notification is a PUT to the subscription's callback_url, with the
subscription's access_token in the header X-Access-Token and the image
in the body, split into name and tag at its last colon:
curl --request PUT '<callback URL>' \
--header 'X-Access-Token: <subscriber access token>' \
--header 'Content-Type: application/json' \
--data '{"image_name": "elixircloud/tesk-api", "tag": "v1.2.0"}'
A listener of your own, instead of Pubgrade-Sidecar,
checks the token, answers with a 2xx status if it accepts the notification,
updates what uses the image repository image_name (see
Services with several images),
and does the actual work (e.g., triggering a CD pipeline) in the background:
it must answer in time (see above; to be safe, within notification_timeout
from the request). Pubgrade only reads the status
of the response, not its body, and doesn't follow redirects (a redirect
counts as failed). It doesn't repeat failed notifications. The API
describes the call as the callback notification of POST /subscriptions,
with the body NotificationRequest (see API); Pubgrade-Sidecar's
PUT /deployment/<deployment name> is an example of such a listener (see
its API).
Services with several images¶
Each published build has one image (a prebuilt image is the only entry of
images; with builds on, only the first entry counts), and each notification
names one image: Pubgrade doesn't group images by service. A service with
several images (e.g., an API and a worker, or a main container and a helper)
publishes each image as a build of its own, from one Pubgrade repository or
from several, and the subscribers of a repository get one notification per
build that matches their subscription. Subscribers match notifications by
image repository: a listener updates every container whose image repository
equals image_name (e.g., elixircloud/tesk-api, also when the container
spells it docker.io/elixircloud/tesk-api) to the new tag, and leaves the
others as they are.
Pubgrade-Sidecar does this with PUT /deployment: in every Deployment it
manages (its targetDeployments, optionally only those with the label
deploymentLabel), it updates every container of the notified image
repository. Subscribe its callback URL <sidecar URL>/deployment once to
each Pubgrade repository that publishes images of the service, not once per
image: subscriptions belong to Pubgrade repositories, so a second
subscription of the same callback to a repository gets every notification
twice (see the sidecar's API and
Deployment). PUT /deployment/<deployment name>
updates the containers of the repository in that one Deployment only.
A release of a service with several images therefore leads to several notifications, one at a time per build, and each Deployment rolls out each new image on its own. Containers that must change together (e.g., because their versions depend on each other) are best published from one repository with one image, or rolled out by a listener of your own that waits for all of them.
Cancel a build¶
The repository's access token also allows withdrawing a build, e.g., one published by mistake:
curl --request DELETE '<base URL>/repositories/<repository ID>/builds/<build ID>' \
--header 'X-Project-Access-Token: <repository access token>'
The build is kept and stays listed, with the status CANCELED; finished_at
is set if it hadn't finished. With builds switched on, a build that is still
running is stopped (see Builds): it doesn't succeed,
and no one is notified of it. Finished builds are only marked. Deployments
that have been notified keep what they pulled: Pubgrade doesn't notify them
again, undeploy anything or delete images from a registry. To roll
deployments back or forward, publish the image they should run as a new
build. A build that is canceled already gets a 409; an unknown one, or one of
another repository, gets a 404.
Builds can't be changed: to publish a corrected image, publish it as a new
build. PUT /repositories/<repository ID>/builds/<build ID> is Pubgrade's
internal callback for finished build pods, not a way to change a build.
Change or delete a repository¶
The repository's access token also allows changing its URL, and its build
types if the request gives build_types (otherwise they stay as they are);
the repository keeps its identifier, access token, builds and subscriptions.
Subscriptions keep their build_types, also types that the repository no
longer declares; builds of those types can't be published any more:
curl --request PUT '<base URL>/repositories/<repository ID>' \
--header 'X-Project-Access-Token: <repository access token>' \
--header 'Content-Type: application/json' \
--data '{"url": "<new repository URL>"}'
Deleting a repository deletes its builds and subscriptions too, permanently:
curl --request DELETE '<base URL>/repositories/<repository ID>' \
--header 'X-Project-Access-Token: <repository access token>'
The subscriptions disappear from their users' lists, and their deployments are no longer notified; they keep the images they already have. Pubgrade doesn't manage deployments: to remove one, its operators undeploy it (e.g., with Helm or kubectl). Images and subscriptions sent to the repository while it is deleted get a 404. With builds switched on, its builds are stopped (see Builds).
Queries¶
# Repositories
curl '<base URL>/repositories'
# Builds of a repository
curl '<base URL>/repositories/<repository ID>/builds'
# Subscriptions of a user
curl '<base URL>/subscriptions' \
--header 'X-User-Id: <user ID>' \
--header 'X-User-Access-Token: <user access token>'
See API for all endpoints.