r/cicd

▲ 1 r/cicd

Where do you run checks during coding-agent iterations?

I used up my free GitHub Actions minutes in a few days while testing an agent factory.

I'm building a local workflow runner, so I have a reason for asking. I'm exploring local checks during the edit/test loop, with hosted CI verifying the finished PR.

I still want failures locally to mean the same thing in CI. Dependencies and leftovers from previous runs seem like the tricky part.

For people running coding agents: where do your repeated checks run? Have ordinary scripts been enough, or have you needed a self-hosted runner or a clean container per task?

reddit.com
u/follow_beer — 8 days ago
▲ 5 r/cicd+1 crossposts

New experimental TeamCity plugin that mirrors Jenkins jobs

The idea behind Jenkins Bridge is simple: Connect TeamCity to Jenkins and mirror your Jenkins jobs in the TeamCity UI without migrating or rewriting them.

In this first version, you can:

  • Start Jenkins jobs from TeamCity, including parameterized builds.
  • Follow live build progress and console output in TeamCity.
  • View Jenkins pipeline stages, dependencies, and stage logs in the Pipeline Graph.
  • Investigate Jenkins test results and failure details using TeamCity’s test interface.
  • See build results, parameters, VCS changes, and published artifacts.

If you use Jenkins, would this be useful in your setup? Feedback from real cases would be terrific.

Thanks a lot!

u/AmazingCow7223 — 8 days ago
▲ 5 r/cicd+1 crossposts

I built an open-source tool that shows what a Salesforce change will trigger (flows, triggers, validation rules, roll-ups) from a git diff

Disclosure: I'm the author.

I got tired of changes that passed tests and still broke something through an automation cycle or a validation rule nobody remembered. sf-preflight reads your SFDX project plus a git diff and walks the order of execution to show the blast radius. It's offline, needs no org credentials, and is Apache-2.0.

Example on the sample org in the repo: changing one field surfaces two automation cycles, a validation-rule collision, and an affected Agentforce action. GIF and repo are here: https://github.com/visparashar/sf-preflight

It's early (0.x). What would make this useful or trustworthy enough for your team to try? I'm especially interested in cases where it gets the order of execution wrong.

u/Accidentalsfguy — 8 days ago
▲ 2 r/cicd+1 crossposts

Graybox supports keys

Last month I shared my personal debugging tool: https://github.com/ViniTamanhao/graybox-core

The biggest criticism i received across the board was manual key overriding support, and now I am happy to say this was included in 0.2.1

If you work with API development and want some new tooling, take a look in Graybox. The core idea is to capture and reuse API cycles during the dev process. It's useful both for handmade code and agentic coding.

If you have any inquiries, please let me know.

u/The_Platypus_Master — 9 days ago
▲ 0 r/cicd+1 crossposts

Self-hosted Actions runners without dedicating a whole machine to CI

GitHub's standard self-hosted runner is convenient when you can give it a dedicated machine, but it's only one runner per machine.

But keeping a separate box just for CI can get expensive, and I'd rather not have build scripts and leftover containers messing with a machine I also use for other things.

What I like about gh-runnerd is that it runs multiple runners on one machine, with each job getting its own fully isolated VM.

When the job finishes, the whole VM gets destroyed, and the next job starts fresh.

Is anyone here using this or something similar?

https://github.com/RefireLab/gh-runnerd

reddit.com
u/AroundTech — 12 days ago
▲ 5 r/cicd+1 crossposts

When should I introduce CI/CD in a project like this?

I’m building a Splitwise-like app called Splitly using the PERN stack (PostgreSQL, Express, React, Node).

The backend is my main focus right now. I already have:

  • Authentication and refresh-token flow
  • Centralized error handling
  • PostgreSQL
  • Automated tests
  • Git feature branches

I’m wondering when it makes sense to introduce CI/CD.

My current thinking is:

  • Set up CI with GitHub Actions now to run type checks, linting, and tests on every push/PR.
  • Add CD later, once the MVP is stable and I’m ready for deployment.

For people who work on production applications, is this a reasonable approach?

At what point in a project do you usually introduce CI/CD, and is there any reason to wait before adding CI?

reddit.com
u/Ok-Box6882 — 14 days ago
▲ 3 r/cicd

Do GitHub's usage report and Actions metrics answer your CI cost questions?

GitHub now gives two things for Actions costs: the detailed usage report (a CSV with cost per repo and workflow) and the Actions usage metrics page under Insights.

If you use them: is there a cost question they still don't answer for you? For example why the cost went up this week, which team caused it, or what to fix first.

If you don't use them: what do you use instead? A script on the billing API, Grafana, a spreadsheet, or nothing?

About me: I'm a solo developer building a small tool in this area. I want to know where GitHub's own tools are already enough. No link.

reddit.com
u/Zealousideal_Tip4089 — 11 days ago
▲ 2 r/cicd+1 crossposts

The Variable That Only Reported Itself: how a build timestamp doubled our CI time

The Continuous Integration / Development process (CI/CD) for any non-trivial software project is important; it is this which exercises your code, makes it breathe, jump, fly, choke, crash and burn -- preferably before the code makes it to production. At the size and complexity of RuneCast this is especially true, and inefficiencies that used to be slight annoyances become choke points for development. Cue xkcd 303, "Compiling".

With this in context, I was ecstatic early this morning working on fixing some UI bugs with Claude and we were able to reduce the most expensive chunk of the pipeline by over 50% (upon further testing more like 70-80%). It all had to do with unnecessary dependencies I had invented for a small convenience -- and which turned out to have a "degenerate" effect on the reproducability of the build by forcing multiple and redundant builds for every release, merge, and tag.

Our CI was spending about 28 minutes of runner time per release rebuilding an image that already existed. The cause was a variable whose entire job was to print the time it was built -- and which, by existing, stopped the same commit from producing the same image upon repeated builds.

Two triggers, one commit

A release in our repos does two things in quick succession: merge to master, then push a version tag at that same commit. Both are push events. Both fire an image-publishing workflow. This has the effect of building the same image twice because the release gets tagged both as vX.Y.Z and master (and latest).

I had come upon this before earlier in the week (maybe last week?) and fixed it — or thought I had. The two runs were racing: the tag run started before the master run had written the shared build cache, so it got no cache and recompiled everything from scratch. The fix was a concurrency key on the commit SHA, so the second run waits for the first and reads the cache it just wrote.

That was a real improvement, and it is also the wrong question answered well. I had made the redundant compile cheaper instead of asking why it was happening at all. The comment I left in the workflow even said so, in a way I did not hear at the time: "neither is redundant — only their compiles were."

What it was costing

We run two self-hosted CI runners. Here is what the last five backend releases actually looked like:

run wall clock of which
master push 29–37 min the build
tag push 51–62 min ~35 min waiting for the first run, then ~28 min rebuilding

So the cache was helping — 28 minutes beats 35 — and the whole thing was still absurd. Roughly an hour of runner time per release, on two runners, with every open PR's CI queued behind it. We also published a debug variant (alpine with musl has no debug symbols by default) so each run built two images. Four builds for two distinct artifacts.

Then the story fell apart. I had been saying the two images were byte-identical, and I had checked: same manifest digest. But they were only identical because both runs write :latest and the tag run happened to finish last and overwrite it. The images themselves were not the same. One build argument differed.

It was RUNECAST_BUILD_TIME, and it came from date -u.

"That's degenerate"

That was the reaction when I described the field: it serves no purpose other than to report the build time.

It is worth checking before believing. built_at has exactly three consumers: a tooltip, a "built …" line in a build-info widget, and a test asserting it is non-empty. Nothing branches on it. Our version-skew detection — the thing that actually cares whether a client is running stale code — uses the bundle hash and the build announced by the server, not this.

So it is inert. But it is not harmless, and the distinction is the whole point.

The intended relationship is image = f(commit). One commit, one image. With a clock reading as an input it becomes image = f(commit, t) where t is free — so commit → image stops being a function at all and becomes one-to-many. Every question of the form "which image is this commit?" loses its answer. That is not an abstraction: it is exactly why :latest and :v0.41.1 could disagree, and why "what is prod actually running?" needed a digest comparison rather than a glance.

The sharpest way I can put it:

>The variable had entropy but no information. Nonzero variance, zero signal about anything anyone cared about.

That is noise, in the strict sense. And "degenerate" is the right word for it, in the rank-deficiency sense — treat the provenance record as a vector of facts (version, git_sha, git_describe, git_branch, dirty, built_at) and, once keyed properly, built_at lies in the span of git_sha. It adds no dimension. Before the fix it did add one, but the dimension it added was pure clock.

The fix is three words long

Use the commit date.

TZ=UTC git show -s --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ HEAD

This is not a clever trick; it is the SOURCE_DATE_EPOCH convention that the Reproducible Builds project standardised years ago, and it is why the field keeps its name. built_at is the timestamp the build represents, not the moment a runner happened to execute.

The proof is two rebuilds, two seconds apart:

backend frontend
rebuild 1 07:25:38Z
rebuild 2 07:25:38Z
commit date 07:25:38Z
wall clock at build 12:57:13Z

Before the change, those two rebuilds differed. After it, a rebuild of the same commit is idempotent.

Which means the actual saving is not the 28 minutes. It is that the tag run no longer needs to build anything: a tag is a name for an image, not a reason to produce one. When master has already published :sha-<sha>, the tag run now points :v0.41.1 at that exact manifest and exits. Seconds, no compile, and :sha-<sha>, :latest and :v0.41.1 are the same digest by construction rather than by whichever run finished last.

That re-tag was only safe once the build became reproducible. With a clock in the inputs, naming master's image :v0.41.1 would have been a guess that it was the right image.

What it actually cost

The first build to run the new workflow came in at 17.0 minutes, against 29-37 before. That is the debug image alone -- one image per run instead of two.

The double build comes off on top of it. A release used to cost the master run plus another 22-27 minutes for the tag run to rebuild the same commit, so 52-64 minutes of runner time per release. It should now be about 17.

before after
build, per run 29-37 min
images per run 2
tag run 22-27 min rebuilding
runner time per release 52-64 min

Update: when I first wrote this, the re-tag was a projection; no release had run through the new workflow yet. The next one (v0.41.2, Sep 30) measured it: the master build took 12m37s, and the tag run took 23 seconds, a re-tag with no compile. That is about 13 minutes of runner time per release, against 52-64 before. Part of the drop from 17 to 12.6 minutes comes from a dependency cache (cargo-chef) that landed the same week, so not all of it belongs to the timestamp.

The general shape

I have been thinking a lot recently on orthogonality, specifically in spectral contexts such as Fourier Transforms (Jacob Lurie has a great lecture on the Categorification of Fourier Theory that is not only a master class in the subject, but in how to give a great lecture), and orthogonal bases ideas in general. Happily for me this is another concept that comes up over and over again and almost seeming like a self-fulfilling prophecy -- anything I work on seems to have some tie to it.

The part I keep turning over is where this hid. It hid in metadata -- the category of thing we all agree is inert. Nobody audits a display field. Nobody writes a test for a tooltip. "It only reports itself" reads as a reason to stop looking, when it should be the opposite: a value that feeds nothing has no downstream pressure keeping it honest, so it is exactly where an undeclared input can sit for years.

The principle has a name specifically for use in build systems: hermeticity. A hermetic build depends only on its declared inputs. The timestamp at which the build happens to be run is an undeclared, ambient input, which in our case made it actively harmful, not just a little messy or unclean. The orthogonality concept comes in here because the build wall-clock time is an unrelated high entropy event that the build now has a dependency on (a random variable) which of course makes the outcome entirely non-deterministic. This ruins any sort of caching, or identity verification provenance.

The whole point of the build hash is that I, the author, provide a build hash I know is good. Then you, yes you Dear reader, download my code, build it, and get the same hash. Given you know and trust my key (which ideally means meeting irl to exchange and verify keys, but that's not a fight for here and now), you have a root of trust and an attestation chain from yourself, having just built the code and seen the hash, back to me with the trusted key and signed hash.

RuneCast is a word game that runs as a Discord Activity: runeca.st. I wrote the intro and the closing sections by hand. The middle was drafted with Claude from the session where we found this, and we edited it together.

u/CycleFive — 14 days ago