Repository navigation
Releases: supercorp-ai/superci
Release list
0.20.1
- A container's processes may signal each other again on AWS's Ubuntu 26.04 machines. RunsOn's image of 2 November 2026 boots a kernel (7.0.0-1016-aws) under which Docker's default AppArmor profile denied every signal inside a container (moby/moby#54099): Postgres never started, and builds that stop their workers failed with EACCES. Each Linux machine now sets
kernel.apparmor_restrict_unprivileged_unconfined=0before Docker and the runner start, kept in/etc/sysctl.dso a package installed by a job does not undo it. A machine runs one job and is thrown away, so this hardening of a shared host buys nothing there. Update your control plane for it. - Jobs boot the build of RunsOn's image that this version of SuperCI was tested with, not each new one as it comes out: a new build reached every job at once before, as the one above did. Each kind of image (Ubuntu 24.04 and 26.04 on x64 and arm64, with GPUs, Windows Server 2025) is pinned to a build, and a release moves the pins. RunsOn keeps only its last three builds of each: once it has deleted the pinned one, jobs boot the oldest newer one left, and
superci statusand the dashboard say so and ask for an update. Your own copies of the image, in regions RunsOn does not publish in, are made of the pinned build too. Update your control plane for it.
0.20.0
- Several AWS accounts run one CI's jobs too:
superci login aws --add, thensuperci runners create aws --account=ID --region=R [--name=WORD]. Each has its own role, machines, regions, spot notes and limits; a CI keeps one cache, in its first account, which machines elsewhere reach by links. Limits for any account:superci accounts update WORD. Each account's bill is kept in the control plane, so every computer of a CI shows it. - A Modal launcher that has not been used for a while is woken before a job's machine is asked of it. Starting from nothing took longer than a control plane waits, and the job then showed no machine with a note left over from waiting.
- Several Modal workspaces run one CI's jobs, each its own runner with its own limits and spend:
superci login modal --addsigns in to one more, andsuperci runners create modal --account=WORKSPACE [--name=WORD]adds it. A runner's word stays for good. Deleting one keeps what it spent counting toward its account's limit, and its word comes back only for the same workspace. Updating, moving and deleting a control plane handle each launcher with its own workspace's sign-in and say which they could not reach. Sign-ins by Taras Kornichuk (github.com/artile). - Repository rules and the one default provider are gone: a workflow's label picks a provider (
runs-on: superci/provider=modal) and the order does the rest. Neither could be set for a long time. Updating a control plane that still has one says which, with the label that does the same. - Changes made at the same moment on several computers are all kept. The order, limits and launchers are kept by the control plane and written through it, each change to the one field it changes: a dialog's change no longer writes back the fields it showed but did not change, over a teammate's change to them. A field changed on another computer since the page showed it is refused, saying what it is now, with Set it anyway for that field alone; a command is taken as said. They were written into the cloud's own settings whole, the last write winning. An older SuperCI's change is still taken, as before. Update your control plane for it.
- A Modal control plane makes every write from one container. Its sweep ran in a container of its own beside the one that answers requests, and an update ran the old one beside the new for a while: as Modal's store cannot write over only what was read, two could take the same job, or lose a change. Now the minute's schedule has the sweep run where the requests are answered, and an update stops the old container as the new one starts (requests meanwhile wait a few seconds). Jobs run in an app of their own (
superci-jobs-<id>), so an update never stops them. Update your control plane for it. - A Modal control plane answers GitHub's and GitLab's events first and starts the job's sandbox after, as an AWS one does: each of its reads and writes is a call to Modal's API, and the event's answer took most of the ten seconds GitHub waits before it counts a delivery as failed. Each write with its end is one call now, its Dict's calls made side by side. Update your control plane for it.
- A control plane's status reads the newest jobs from one record, where a Modal or Cloudflare one listed every job of the last 90 days at each look; and what jobs are still going and the days' totals once, not three times and twice. Update your control plane for it.
- A Modal deploy works in any Modal workspace, however new: SuperCI tells Modal's client which image builder version to build with (2026.10, with Modal's client 1.6.3), where it took the workspace's own, and a client refuses one newer than it knows. A workspace made now is on 2026.10, which SuperCI's client before refused. By Taras Kornichuk (github.com/artile), who moved the client to 1.6.3. Update your control plane for it.
- A Modal control plane or launcher deploys in a Modal workspace that has nothing of SuperCI's yet. Modal had begun to refuse to create an app for a client whose version it could not read ("Could not determine the SDK version for client type CLIENT_TYPE_LIBMODAL_GO"), and SuperCI said its own: it now says Modal's Go SDK's, as that SDK does. By Taras Kornichuk (github.com/artile).
- A Modal sign-in ends once it is approved in Modal's tab, whatever the dashboard's tab does meanwhile. Modal hands the token only to a call waiting at that moment: one now waits all the time. By Taras Kornichuk (github.com/artile).
- What Modal says of a client release it will stop taking is said: by
superciwhen it asks Modal, above the dashboard's pages, and insuperci statusfrom the control plane, which keeps what its launchers and its own client heard. Update your control plane for it. - Updating the control plane updates its Modal launcher too (as it did a Cloudflare one), with a Modal sign-in to the workspace it is in: it kept the Modal client it was deployed with.
- Modal Functions are a row of their own in the order, taken out until put in:
superci runners order modal-functions modal(a further runner's isWORD-functions). They are deployed when the row goes on. A Function costs a third of a sandbox ($0.0000131 a core-second and $0.00000222 a GiB-second, against $0.00003942 and $0.00000667), and jobs are priced so. Modal may preempt a Function and start it again: it then starts no runner (GitHub's registration is used up) and says so, and the job is run again by itself further down the order once its run has finished, once at most.superci statusand the dashboard count this month's preemptions and the jobs run again. Its Functions, one per image, are deployed in that workspace when the row goes on, when an image is added or changed, and withsuperci runners create modal. Taking the row out goes back to sandboxes. Update your control plane, and a Modal launcher, for it. - A job on Modal can start from an image of your own, with a repository's tools in it already:
superci runner_images create rust-ci --reference=ghcr.io/acme/ci:2026-10, thenruns-on: superci/image=rust-ci. A label is split at each/, so it names the image and the control plane keeps its address. Make the image FROMghcr.io/actions/actions-runner; a job whose image has no GitHub runner, or one Modal cannot pull, fails at once, saying so. A private registry needs a Modal Secret (--modal-secret=NAME). A new build goes in under the same name in one change, so no job finds the name missing meanwhile:superci runner_images update rust-ci --reference=ghcr.io/acme/ci:2026-11. AWS and Cloudflare refuse such a job, saying why. Update your control plane, and a Modal launcher, for it. - A run from a computer whose workflow names
actions/checkoutby its commit (actions/checkout@3d3c42e…, as security guides advise) checks out the working tree as with a version (@v4). GitHub's runner took its own copy of GitHub's checkout, kept on the machine by that commit, which failed asking for a token. Update your control plane for it. - A run from a computer whose checkout names a full path inside the workspace (
path: ${{ github.workspace }}/src/github.com/acme/app, as Go projects do) checks out there, as GitHub's checkout does; one outside the workspace is refused, saying so. The full path was put under the workspace again, so the steps after found no checkout. Update your control plane for it.
0.19.21
- A spot machine is asked for first among the pools near the cheapest in any of its regions, then in each region whole. When the first region had no room for the cheapest type, its dearer types were asked before the next region's cheap one: a job whose label names
family=c8a+m8a+r8agot r8a in N. Virginia at three times the price, and Ohio's c8a was never asked. The first region still counts 15% cheaper. Update your control plane for it.
0.19.20
- The spinner beside a step that takes more than one line ("Uploading the new functions (the control plane and its Docker image converter)", in an update) stays round, beside the step's first line. The step's text squeezed it into an oval.
- A job whose runner said it had ended, in a request the control plane could not finish (its store or a call failing midway), is ended when the runner says so again, and its machine stopped. It stayed running, its machine paid for until its time was up, because the runner's second word said nothing new. The same for a runner saying it took its job. Update your control plane for it.
- A GitHub job's end that the control plane could not keep is kept when GitHub sends the event again. Its runner was forgotten before the end was kept, so the event sent again found no job. Update your control plane for it.
- A job of a run from a computer whose start failed midway is started again by the control plane's upkeep. It stayed "started" with nothing started, and the run never ended. Update your control plane for it.
- A run from a computer refused when it is created leaves nothing behind. Its record was kept, and the upkeep started the run anyway after
superci runs createhad said it failed. Update your control plane for it. - A job's cache or artifact is not lost to a passing failure: the control plane failing to read the job's token for a moment (its store, or GitHub's keys) is answered as a failure the machine asks again, not as a refusal it takes as final. Update your control plane for it.
- A Docker layer a machine uploaded is kept when the control plane fails partway through taking it (its store, or S3 checking the upload): its record stays until the layer is being converted, and a conversion is noted before it is asked for. Such a layer was lost, or left "being converted" until it timed out, and the next job pulled it again. Update your control plane for it.
- A command that names a control plane (
--plane=ID) acts on it after another was in use in the same workspace. It was refused as "not among the control planes here" once a command had read the other one. - Removing AWS runners from a control plane that no longer knows any AWS account says it is done. It asked to sign in to an account with no number.
- A job the control plane took as its store failed to index it is let go, to be taken again. It was left for nothing to look after. Update your control plane for it.
- A control plane from before 0.19.0 building its jobs' indexes a part at a time indexes the job each part ends at, and counts its run. That job was passed over. Update your control plane for it.
- An AWS control plane reading many records at once while DynamoDB is busy reads every one of them. Records DynamoDB still left for later after eight tries were taken as not there: a job or a cache entry could look missing for that moment. Update your control plane for it.
- A Cloudflare control plane reads its settings as the others do: the secrets kept for runs from a computer are listed and given to its runs, Settings lists each device's key, and AWS runners turned off stay off. It read none of them. Update your control plane for it.
- A Cloudflare runner whose container Cloudflare fails to stop says why, for the control plane to try again. It failed with an error Cloudflare's runtime reported as uncaught. Update your control plane and its Cloudflare launcher for it.
- A job on Modal ends as soon as its steps do, and a Modal control plane answers several requests side by side: a job whose steps take a second takes 5 seconds, where it took over 4 minutes, its machine paid for meanwhile. It answered one request at a time, and its runner's asking for messages, the CLI following a run and the job's own calls (its end too) each waited for the others. Update your control plane for it.
- A Cloudflare launcher asked to start a runner in a place Cloudflare has no location for refuses it, saying so, and a Cloudflare control plane whose containers' location is not one of Cloudflare's starts them in eastern North America, as by default. Such a location went to Cloudflare as it was. Update your control plane and its Cloudflare launcher for it.
- Setting up Cloudflare runners sends a chunk of the runner image that Cloudflare's registry fails (a 500 of its own) again, twice. One such failure ended the setup.
- A job whose spot machine AWS took back is not run again when its branch has a newer push whose run of the same workflow is still going. Run again, it came after that run, and a workflow that cancels runs in progress (
concurrencywithcancel-in-progress) cancelled the newer push's run before any of its jobs began. Its page says why. Update your control plane for it. - Whether the GitHub App is installed is not kept while there is no App yet. A dashboard that asked before the App was made saw it not installed for a minute after it was. Update your control plane for it.
0.19.19
- A control plane asked for a job's log by an id that is no job's, or of a GitLab by a name that is none, answers 400 with what was wrong (it answered 500, as if it had failed itself). Update your control plane for it.
superci jobs retrieve ID --out=FILEof a GitLab job whose log is over 4 MB says the control plane gives only its last 4 MB, and that GitLab's page of the job has it whole. It said a newer control plane would give it whole, which none does for GitLab.- Remove from SuperCI only, when removing a runner provider in the dashboard, removes it from SuperCI only. The button's choice was lost as the dialog was sent, so it removed the provider in its cloud too, or asked to sign in there.
- Settings keeps what is this computer's own while the workspace's control plane does not take this computer's key: its id, signing out, and removing the workspace when there are others. The page showed only why the key was not taken, so a workspace kept twice could not be removed there.
- A machine that came up and waits while GitHub keeps its job queued (as when GitHub's Actions hand out jobs late) is ended, and the job waits ten minutes with no machine before another is started, saying GitHub has not handed it out. Such a machine was ended and another started in its place, twice, each paid while it waited, and then the job failed saying the cloud did not start a machine for it. Update your control plane for it.
- A long job of a run from a computer shows its log while it runs. Its page could say "the control plane answered 502 Bad Gateway" once the job had logged a few MB: an AWS control plane gave each step's log whole beside the log asked for, and measured its answer before the encoding AWS's function URLs add, so it went over the 6 MB an answer from AWS may be. Update your control plane for it.
- A job whose machine did not start three times fails on GitHub too, saying why, when GitHub still has it queued. It failed in SuperCI only, and GitHub kept it queued, with no machine coming, for up to a day. Update your control plane for it.
- The dashboard's Set up a control plane page goes on to Overview by itself once the deploy has made the control plane (to its own pages, with others beside it). It showed the list of control planes instead, and went on nowhere.
- A computer's new key, handed to a control plane, is said once to be on that computer. The control plane's answer was taken for a failure, so it was said twice more, a second apart, and every new key held up a page or a command for three seconds. Update your control plane for it.
- A secret taken out that the control plane still has half a minute later is said as that, as a new value not taken is.
superci secrets deleteand Settings said it was taken out, and runs went on getting it. - A control plane standing by for a move that was not finished, found in the account by a dashboard that did not know of it, is listed with the CI's control planes, where the move can be finished. It was listed as another CI, which nothing here could move to or delete.
- The dashboard takes a port only when it is free on both of this computer's loopback addresses. Taken on one (another program on 127.0.0.1, as
wrangler loginhas 8976), it started on the other alone, where a browser opening localhost could reach that program instead, Cloudflare's sign-in among them; andsuperci dashboardwith SUPERCI_PORT named it in use only where IPv6 is off. - A job written by another request just as a control plane made the indexes of the jobs it kept from before them is listed among the newest jobs. It was left out of them, and of the dashboard's list of jobs, until its record went. Update your control plane for it.
- A job of a run from a computer still waiting for room when the run's records go, a day after it started, fails saying the run is gone. A machine was started for it once there was room, and its runner found no job to take. Update your control plane for it.
- The dashboard's AWS account section, beside a control plane whose machines start in several regions, puts each region on a line of its own: how jobs use it ("Spot, favoured · on-demand", "Spot when cheaper", "Not used"), how many spot CPUs AWS lets it run there, and Copy into it where the runner image is missing. CPUs at once adds up the spot regions in use, and Ask AWS for more offers each. It said the regions allowed in one line and CPUs for the first region only.
- A job's page says its AWS machine in three rows: Machine ("c8a.xlarge · 4 CPU"), Spot or on-demand (and why on-demand), and Region with its zone. The region was not shown, and a spot machine was not said to be one.
- A job's start says "spot" of the machine AWS gave, as it says "on-demand": "spot r8a.16xlarge in us-east-1a, AWS's choice of 14 pools". Without the word it read as an on-demand machine.
- A region AWS answered with an error rather than yes or no (as while an organization's policy is changed) is not offered on Runners as if allowed: it says AWS did not say, with Refresh. It was offered, and adding it failed.
- A job's spot machine comes from the region where it costs least: with several regions on Runners, each one's spot prices are read and the first region counts 15% cheaper (its cache and Docker layers are there). A region later in the list was asked only once the first had no spot machine at all, however much cheaper it was: a 4-CPU machine in Ohio costs a third less than in N. Virginia today. On-demand machines still go in the regions' order. Update your control plane for it.
- When the cheapest pool has no spot machine, the pools asked together next are only those within a quarter of what the job would cost on it (spot price for the speed); the others come after, in a request of their own. AWS weighs a pool's spare machines before its price, so asked for all of them at once it took r8a.16xlarge at $2.83 an hour beside m7a at $0.73. Update your control plane for it.
- No spot pool priced over the on-demand price of the cheapest machine that fits is asked for. Such pools are named on the job's page. Update your control plane for it.
- A machine with more memory than asked for (r8a, r7a, r8g) is asked for only where no general machine has the memory with as many CPUs. For 64 CPUs that leaves m7a, m8a and the others, not r8a at twice their price. Update your control plane for it.
- AWS jobs can get Intel's machines too (c8i, c7i, m8i, m7i), for more spot pools to choose from: in Ohio today, c8i.xlarge is the cheapest 4-CPU spot machine. Each of their CPUs counts a quarter slower than AMD's (it is half a core), so they are chosen when their price makes up for it. Update your control plane for it.
- A job's page says why its spot machine is the one it got: its price, the cheaper first choice that had no machine, and what was not asked for its price. Update your control plane for it.
0.19.18
- A change's note in the dashboard ("Removed Cloudflare. Left: …") is shown once its page has loaded. A page still loading took it, and it was not shown.
- A job with nowhere to run names the operating systems as they are written: "Nowhere to run Windows: Cloudflare runs Linux only" (it said "windows" and "linux").
superci runs create --repo=OWNER/NAMEnames the GitHub repository a run is of, for a checkout whose origin is not GitHub's (a copy of it, say). Such a run's cache was its own, apart from what GitHub's jobs saved, and nothing said so: now the run says when its cache is its own, and why.- A job cancelled while its machine came up shows as Cancelled, saying its machine is ended unless it takes another job. It showed as Failed ("Its machine was lost") and counted among the failures.
- An artifact a job fetches with
actions/download-artifactis unpacked. SuperCI's machines said it was a plain file, not the zip it is, so newer versions of download-artifact kept the zip as it was, under the artifact's name. Update your control plane for it. - Following a run (
superci runs create,superci runs wait), a passed job's end and the run's summary come together. The summary waited up to a minute more for steps' logs and results the job's end had already been said without. superci runs retrieve --testsreads every job's tests that ran, whatever ran it. A passed job with no machine on its record was skipped, so only the failed jobs' tests were shown.
0.19.17
superci planes create cloudflareafter the Cloudflare sign-in ended says it ended (it said to sign in), and a Modal token given in SUPERCI_MODAL_TOKEN_ID that Modal refuses is said as Modal refused it (it was dropped, and the command said to sign in).- A cloud that does not answer at all (Modal or Cloudflare down, say) is a note on each dashboard page, which shows what the other clouds have and keeps working: every page said "Could not reach your cloud", even with the control plane in AWS.
superci planes listnotes it too, and a command that needs that cloud says it did not answer (it said to sign in). - A job no provider could start says AWS's refusal for want of GPU quota once: "AWS lets this account run no GPU machines yet…" (it said "AWS: AWS lets…").
- A label that names an x64 family (
superci/family=c8id) or asks for a disk of the machine's own (superci/scratch=localdisk) gets such a machine on AWS. Without a size in the label it got the standard machine (c8a, no disk of its own). Update your control plane for it. - "Sign in again", after AWS refused a sign-in's last step (the account changed on its page midway), signs in again with several workspaces on the computer. It said "Which workspace?", since its link named none.
- A dashboard page whose dashboard stopped keeps what it showed, dimmed, with a bar saying when that was and to run
superci dashboardagain; once a new one runs, the bar says to open the link it printed. The page was emptied to one line. After a short break (the computer asleep), it picks up by itself. - Overview says "1 job · 1 did not run" (it said "1 jobs").
- Overview's machine time over 6,000 minutes is labelled machine hours (it said "120 h machine minutes").
superci keys create --runson a control plane too old for run keys says to update it, and one that does not take this computer's key says why (both said it had not answered).- A sign-in made elsewhere while the dashboard runs (another terminal's
superci login) shows on the next page; it showed one page later. - A control plane that does not answer is said on Runners, Repositories, Workflows, Runs and Jobs, as on Overview. They guessed at what it had: no runners yet, GitHub to connect, jobs out of reach for want of a sign-in.
- A Cloudflare token given in SUPERCI_CLOUDFLARE_TOKEN that Cloudflare refuses is said as that token (the dashboard said the Cloudflare sign-in had ended, and offered to sign in).
- A change in the dashboard that needs a sign-in that ended says so, as commands do (it said to sign in, or that something went wrong).
- Adding a label on a control plane too old for more labels says to update it (it said the control plane had not answered yet).
- Updating a control plane that does not take this computer's key says why (it said the control plane had not answered yet).
- A dashboard page whose control plane does not take this computer's key says why after half a minute (a control plane from before 0.19.13 reads the key under its old name; a key that expired; a newer control plane), with what to do. It kept saying "Reading your control plane…".
superci runs createstarts a run as GitHub's events would: its job conditions andgithub.eventsee the payload GitHub sends, made from the working tree (the branch, the commit, a pull request's head and base).--label=NAMEgives the pull request labels (its actionlabeled),--event=workflow_dispatchwith--input=NAME=VALUEstarts it by hand (other inputs take their defaults, typed as the workflow says, a required one or a wrong value refused), and--event-payload=FILEputs JSON over the payload.github.eventwas empty, so a job that read it, a label's say, was always skipped. Update your control plane for it.- A job's condition reads every item's field after
*:contains(github.event.pull_request.labels.*.name, 'x')read the first label whole, and was false. superci runs createandruns waitkeep following a run when this computer loses the control plane for a while (its network or DNS drops, or the control plane is restarting): they say so once, ask again every few seconds, and go on where they were. They ended with an error, though the run went on. After ten minutes with no answer they end, saying how to follow the run again.- A job's page opens with every step closed, a running job's too, and draws only the log lines on screen.
- A label's
docker-cacheturns the Docker image cache off or on for a job:runs-on: superci/docker-cache=falsegives it Docker as it comes, nothing kept after it (to time a job cold, say);truegives it the cache from its start, even when its last run used no images.superci machine update --docker-cache=falsedoes it for every job whose label does not say. Ubuntu 26.04 machines. Update your control plane for it. - A job's first run gets Docker images from the cache when its repository's other jobs used them: a new workflow, or a job renamed, had Docker as it comes, pulling everything though the cache had most of it from the repository's other jobs. A job whose own last run used none still gets Docker as it comes, and the layers fetched ahead at a machine's start are still those its own job used. Update your control plane for it.
superci runs createandruns waitend with each job's Docker images,--quiettoo: what came from the cache and what was pulled, assuperci jobs retrievesays them. A machine says this as its job ends, before it uploads what it pulled for the next job (that may take minutes); what was kept, and why not, follows injobs retrieve. Update your control plane for it.- A machine whose cache for Docker images could not be switched in always gets Docker back. systemd starts Docker three times a minute at most, and a machine's start, the switch and putting Docker back are three already: one more left Docker off for the job.
0.19.16
-
Docker images are kept and served on machines whose files are in memory (
superci/scratch=ramdisk). The cache was never switched in there: the kernel mounts no EROFS file from memory's filesystem, so its setup turned it off, while each job still said its layers came from the cache (it counted what the cache's index listed). The layers' files now go on a disk in memory, with no disk of their own beside it (and none in the price). A job says layers came from the cache only when they did, and says why the cache was off when it was. On a 16-CPU machine with files in memory, a local Supabase starts in 27 s instead of 32 s, with 6.2 GB of memory used instead of 11.6 (the images are no longer held both compressed and unpacked). -
A machine gets every layer's link with the cache's index at its start, and fetches the layers its job's last run used right away, before Docker asks for them (106 layers, 3 GB, in 3.3 s): its pull then finds them there. It asked for links layer by layer as Docker pulled, and a burst of those waited seconds on the control plane. Layers a job used are kept in the cache as long as jobs use them, as before.
-
The cache converts up to 64 of a region's Docker image layers at once (it was 16, the rest a minute apart), so a stack's images (a hundred layers) are there for its next run, not filled over five.
-
A job's Docker images say why what was pulled was not kept: no whole file of it on the machine, the cache would not take it, or its upload failed (with the failure's words).
-
A job's Docker images count what the cache had already among what was kept: a layer pulled that the cache had (from another run, or another repository's public one) is there for the next job too, and was said as "none uploaded to the cache". Its machine says those apart (
had). -
superci limits retrievelists every limit spending counts against, each with the command that changes it: the CI's, its AWS account's for a month and a day (its spot and on-demand machines together), and a provider's own. It said "no limit is set" while the AWS account's limit was what refused jobs.superci accounts retrieve awssays the account's limits too. -
Whether AWS itself emails is said with them: with no budget in AWS, nothing emails at 80% or 100% (
superci accounts update aws --aws-budget=emails --email=ADDRESSadds one). With one,superci accounts retrieve awssays what AWS has counted against it so far. That is AWS's own bill, hours behind SuperCI's estimate, and its emails follow that count. -
A job refused at an account's or a provider's limit says the command that raises it: "the AWS account reached its $100 a month (
superci accounts update aws --monthly-usd=Nraises it)". -
A label added while the control plane does not answer (it is starting with a new setting) says to try again in a few seconds; it said to update the control plane.
-
superci connections delete github OWNERfor the first organization a control plane was connected with says that its App stays while the control plane does (superci leavestops SuperCI); it said "That organization is not one added here".
0.19.14
- A job of a run from a computer started again after AWS took back its spot machine keeps its artifacts anew, as a new attempt of a job does at GitHub: its first attempt's
upload-artifactof the same name made the second fail with a name conflict, failing the run though every test had passed. Another job of the run keeping an artifact of that name is still refused, as GitHub refuses it. superci runs createsays a job that was started again, and which job its first attempt was: "Started again on an on-demand machine: AWS took back its spot machine".superci jobs list --run=IDlists that run's jobs (it took the flag and listed every run's).- A step whose result its runner never sent is judged by its own lines: tests that failed there mark it failed (✗, not ·), and each is named with its error, as for a step said to have failed. The summary also waits for steps' results as it waits for their logs (a minute at most).
- A GitHub job that waited for spot (your spot limit reached) or was started again after AWS took back its spot machine registers its runner anew: GitHub took its name once, its next try was refused ("A runner with the name … already exists") and the job failed at Set up runner without running. The registration from the try before is taken out first, and a name GitHub still has gets a new one.
- A dashboard page opened while the one before it was still loading stays open: that page's answer, coming after, put it back (a click on Runners or Settings right after the dashboard opened could land on Overview again).
- A job that waited for room under your AWS spot limit says that wait apart in its start: "1m 7s waited for room under your AWS spot limit", then "2.5 s AWS gave a machine" (it said AWS took 70 s).
superci runs createsays when the run is over and its summary waits for the steps' logs (its runner sends them after the job, a minute at most): it read as finished, then went on.- The cache keeps a job's Docker images again: a machine offers what it pulled once its job is over, and by then the control plane had ended the job's record of its runner and answered every layer "no" (always for a run from a computer, often for a GitHub job), so nothing was kept. A job's page and
superci jobs retrievesay what was uploaded: "97 layers pulled (1.9 GB), none uploaded to the cache" said "kept for the next job". - A control plane asked with a key it does not take says so (status 401, with its version), where it said "nothing here" (404); a read or run key asking for what needs a device's key gets 403.
supercisays why and what to do, never "No runs yet" or a run not there: the key expired or was replaced (sign in again), SuperCI is older than the control plane (update it), or the control plane is from before 0.19.13 and reads the key under its old name (sign in again, or update it). - A key an older SuperCI kept (DASHBOARD_KEY_…) is kept under the new name and handed again, instead of being taken for one that expired: two versions used on one computer replaced each other's key at each command, and a dashboard or a command running with the replaced key lost the control plane. A key that is replaced is left to expire, so a command still running with it goes on.
- Commands run side by side on one computer (a coding agent's, several at once) hand the control plane one key between them: each made and handed its own when the computer needed a new one (six commands, six keys, each listed as a device).
- A key handed by a command (not only by a dashboard) says which device it is on: Settings → Keys and
superci keys listnamed those "A device". superci secrets createandupdateask for the value in a terminal, typed hidden; stdin and--value-envwork as before.superci planes update --dry-runsays when the control plane is on this version already (it is deployed again, and what this version has beside it is made where missing), and from which version it would update.superci planes allow --dry-runreads the control plane's AWS role and says what it lacks, or that nothing would change. An update's step names both functions it uploads.
0.19.13
- A job whose spot machine AWS takes back says why on GitHub: an error in its log and among its annotations, beside GitHub's "The runner has received a shutdown signal". Its row says plainly that SuperCI runs it again by itself, off spot machines, once its run has finished (GitHub runs a job again only then): "run again, off spot machines" read as something to do.
superci jobs retrievegives a running job's log as far as it goes: GitHub has it only as far as its runner has sent it in blocks (minutes behind at times), and what its machine sent after that comes too. It says where the log came from and when its last line was written;--outsays a running job's is its log so far.--run=ID --job=NAMEwithout--outfound the job and asked for no log.- A machine other than the first choice says why, with the price: "Not the first choice: AWS had no spot c8a.16xlarge in us-east-1a ($0.135 an hour)", now in
superci runs createandsuperci jobs listtoo. When the first choice has no machine, AWS is asked for the cheapest of the others of that size it has room in (it took the one it had most room in: an r8a.16xlarge at nearly three times a c8a's price). - A job refused spot for your account's spot limit while machines of SuperCI's that just ended still count toward it (AWS counts a machine until it has shut down) waits up to two minutes for spot, asked every 20 seconds, before an on-demand machine. A job whose machine never took it, and so got another, counts what every machine cost.
--testsand--quietname each test that failed as expected, however many ran (Playwright prints no error for them, and passes one that failed for another reason too), and count them over every test: a run of more than 200 tests counted those among the first 200 only. Each run of a test Playwright repeats (--repeat-each) is counted, as Playwright counts it: ten runs that failed as expected were said as one. Where several processes run tests at once ([slot 2] …), each one's counts are said, and a failed step's last lines are each one's own (they were the last one to end's).- A runner slow to reach the control plane says what it logged meanwhile at the end of
superci runs create(a fixed wait of 30 seconds is its retry after a request that failed). superci runs createwaits up to a minute (it waited 15 seconds) for each step's own log once the run is over before it counts the tests: the runner sends a large log after the job has ended, and a step read from the lines sent as it went, some dropped, counted too few (tests that failed as expected came to 6, 9 or 11 where whole logs have 86). When a log still has not come, the counts say they are from what came, andsuperci runs retrieve ID --testscounts it all.- A run from a computer cancelled before its machine took its job keeps nothing of its secrets (they stayed in the control plane's store for a day). A run key cancels runs from a computer only: it could cancel a GitHub run by its id.
superci runs waitfollows a run with a lot of output, also one already over: a run's status gives a job's lines 1.5 MB at a time (asked for whole, one answer was over what Lambda answers with, and the control plane answered 502).- A job's steps show as GitHub shows them: a parallel group's steps under its row, folded with it, and each step marked background, parallel (with how many steps), wait, wait all or cancel, with the steps it names. For a job of GitHub's, its machine says it once the job begins (from the start of the runner's own log).
- A workspace looks after one CI. Control planes found in its signed-in clouds that are not its own (another CI in the same AWS account, a teammate's) are listed apart, with their names and whose jobs they run, and never taken in by themselves: a new workspace picks one (Use this one, or
superci workspaces update ID --plane=PLANE) or sets up a new one, and one another workspace here looks after opens that workspace.superci planes listlists them apart. A control plane writes whose jobs it runs where its account's sign-in reads it (OWNERS), for that list. - Each CI in an AWS account has a name of its own: renaming one, or setting one up under the workspace's name, is refused when another CI there is called that (whatever the case). Two workspaces on this computer that look after the same CI say so in the switcher and in
superci workspaces list("same CI as …"). - Settings → Keys lists who reaches the CI: each computer's dashboard (the computer's name, when its key was made and last used) and the read and run keys made for coding agents and scripts, each with Remove.
superci keys listlists the computers too, andsuperci keys delete DASHBOARD_KEY_…takes one out (this computer's own:superci logout). - Control planes in one AWS account share one network in each region (made by the first, deleted with the last, and only with no machine in it): AWS gives an account five networks in a region unless asked for more, and each control plane made its own. One made before keeps its own.
- Secrets for runs from a computer, as a repository's are kept for its runs on GitHub:
superci secrets create NAME(the value from stdin or--value-env=VAR, never from the command),list,updateanddelete, and Settings → Secrets. Each is written with your sign-in into the control plane's own cloud and never read back out: lists say names, where each may be used, when it was set and last given to a run, and who started it.--repo,--branch,--workflowand--environmentnarrow where one may be used, GitHub's patterns too (release/*); a job gets the narrowest under each name, and a value given with the run (--secret) wins. A run gets only the secrets its workflows name; one named and not kept is empty, as on GitHub, andsuperci runs createsays which before the jobs start. Run keys start runs that get them. Jobs GitHub sends get GitHub's own secrets, as before. Moving to another control plane carries them along. Needssuperci planes update. - The cache keeps the Docker images jobs pull, for their next runs, on Ubuntu 26.04 machines (
superci/image=ubuntu26): the next job reads them from your bucket in its region instead of the internet (a local Supabase started in 37 s instead of 100 s, a 2 GB Playwright image pulled in 6 s instead of 22 s). Nothing is asked of you and nothing changes in workflows. After a job, its machine keeps the layers it pulled that the cache lacks, before it goes off, so the job's own time is never touched; a repository's first run is Docker as it comes. A layer any registry gives to anyone may be read by every repository; any other only by the repositories that pulled it. A job's page andsuperci jobs retrievesay what it had from the cache and what it pulled. A job whose last run used images gets a fast disk of its own for them, in its price (about $0.02 an hour); one that used none gets nothing. The Cache page andsuperci caches retrievesay what is kept;superci caches update --images=falseturns it off. A layer goes after the cache's days unused. A control plane on AWS has a second function for it,superci-plane-ID-convert, with a role that may only read and write thelayers/part of its buckets;superci planes updateadds it. - The same words everywhere: a device key (each device's dashboard and commands, named after the device), a read key and a run key (
superci keys create NAME [--runs], for coding agents and scripts); a launcher for what SuperCI deploys in Cloudflare or Modal to start machines there for a control plane elsewhere (it was a runner agent; its Worker stayssuperci-runners-ID). The control plane keeps them under the same names (DEVICE_KEY_…, LAUNCHERS):superci planes updatemoves what it kept under the old ones (DASHBOARD_KEY_…, AGENTS) and takes those out. A device still on an older SuperCI reaches an updated control plane once it is updated too. Settings → Keys lists them in rows that fit the card.