I'm a DevOps & Platform Engineer on enterprise projects: CI/CD, Kubernetes, Terraform, cloud cost.
I wrote application code before I ran the infrastructure that hosts it, which pays off mostly when a build breaks and someone has to know where to look.
The open-source work here comes from the same place. Most of it is small, read-only, deterministic tools for problems I hit in real deployments, and when the bug is in someone else's code the fix goes upstream rather than into a patch I keep for myself.
role: DevOps & Platform Engineer
building: [trasloco, kubectl-safe-rollout, scadenza, disdetta]
platform: [Azure, Kubernetes, GitOps, Terraform, Azure DevOps, GitHub Actions]
also: [FinOps, Agentic DevOps, .NET backend]
languages: [C#, TypeScript, Go, Rust, Python, Bash, PowerShell]
into: [correctness bugs, observability gaps, release plumbing, cloud cost]
based_in: Turin, ItalyAn open-source tool, in the making, to move CI/CD pipelines between Azure DevOps, GitHub and more. Predictable and reviewable by design: plan/apply, deterministic.
Already usable today to find retired Azure Pipelines tasks, as shown in its Try it now section. The companion repo trasloco-e2e runs the generated pipelines on real runners.
| Project | What it is | Stack | Status | |
|---|---|---|---|---|
| kubectl-safe-rollout | A kubectl plugin that explains why a rollout failed or stalled: deterministic classification, no LLM, and it never writes to the cluster | Go client-go |
||
| scadenza | Which public TLS certificates will not survive 100-day lifetimes. It merges Certificate Transparency logs, live TLS handshakes, Kubernetes/cert-manager and Azure Key Vault into one inventory: where each certificate lives, who renews it, and whether renewal is automatic. Read-only | Go |
||
| disdetta | Finds Bitnami dependencies (bitnamilegacy images, since 2025-08-28) in repositories, clusters and GitOps repos, then plans the exit per component. Read-only, deterministic, no telemetry | Go |
||
| github-actions-recipes | The workflows behind my CI/CD and FinOps posts, one variable isolated per recipe | GitHub Actions |
||
| token-optimization | Idempotent bootstrap that cuts token usage when working with LLM coding agents | PowerShell |
The Go tools here share one shape: single binary, read-only by default, deterministic, no telemetry, Apache-2.0.
kubectl-safe-rollout is submitted to krew-index, so it will be installable with kubectl krew install safe-rollout.
|
Platform & CI/CD |
Cloud & infrastructure |
|
Backend & architecture |
Identity, storage & AI |
I write on LinkedIn about platform details that usually pass unchecked: how Azure DevOps resolves its three expression syntaxes, the compliance rules for self-hosted runners, what Copilot code review does and does not decide, and whether an Azure reservation discount is still applying to anything.
53 pull requests across 42 projects I run or depend on. 13 merged so far, 30 still in review.
Merged (13 merged pull requests)
| Project | Change | PR | |
|---|---|---|---|
| dotnet/runtime | Fix CompareInfo.IsPrefix/IsSuffix with CompareOptions.IgnoreSymbols not ignoring leading/trailing symbols | #132397 |
|
| kubernetes-sigs/apiserver-network-proxy | Add connection_duration_seconds histogram for post-dial connection lifespan | #899 |
|
| StackExchange/StackExchange.Redis | Fix Sentinel connection leak and AbortOnConnectFail=false handling | #3187 |
|
| StackExchange/StackExchange.Redis | Add NOMKSTREAM support to XADD | #3186 |
|
| StackExchange/StackExchange.Redis | Make fallback discovery and keep-alive probes cluster-slot aware | #3185 |
|
| DapperLib/DapperAOT | Fix false-positive DAP214 for {=XXX} literal-replacement syntax | #191 |
|
| nunit/nunit-console | Add AssemblyTargetFramework to IExtensionNode | #1867 |
|
| nunit/nunit-console | Fix --list-extensions showing wrong target framework for extensions | #1861 |
|
| Azure/azure-powershell | Fix Get-AzSubscription silently ignoring mismatched -TenantId under MSI auth | #29994 |
|
| argoproj/argo-events | Close NATS connection when trigger connection init fails | #4158 |
|
| quartznet/quartznet | Add job type exclusion filter to trigger acquisition | #3282 |
|
| rust-embedded/heapless | Add shift_remove family to IndexMap/IndexSet | #685 |
|
| traefik/traefik-helm-chart | Restore secretResourceNames for namespaced role | #1972 |
In review (30 open pull requests)
| Project | Change | PR | |
|---|---|---|---|
| moby/moby | Bridge: repair stale WSL2Mirrored loopback0 drop rules | #53458 |
|
| kubernetes/kube-openapi | Fix duplicate map keys when a type embeds two structs sharing a field | #631 |
|
| kubernetes/perf-tests | Add unit tests for clusterloader2/pkg/errors | #4261 |
|
| docker/cli | Cli/command/image: trim iidfile image ID and fail clearly when missing | #7279 |
|
| docker/cli | Normalize the registry server address to lowercase for credential lookup | #7184 |
|
| containerd/runwasi | Gate ctr image import --local by detected ctr version | #1177 |
|
| argoproj/argo-cd | Add ignoreDraft filter to ApplicationSet Pull Request generator | #29265 |
|
| argoproj/argo-rollouts | Stop degraded stable RS from permanently blocking subset DestinationRule switch | #4990 |
|
| open-policy-agent/opa | Make allow_net restrict file:// refs in JSON schemas | #9044 |
|
| spiffe/spire | Fix inaccurate expiring/outdated SVID sync metrics | #7230 |
|
| thanos-io/objstore | Support a custom GCS API endpoint through the endpoint config option | #270 |
|
| saltstack/salt | Fix file.managed omitting mode from changes when creating a file | #70084 |
|
| BurntSushi/ripgrep | Detect compressed files by magic number in search-zip, not just by extension | #3516 |
|
| BurntSushi/ripgrep | Fix the dangling backslash error for an escaped trailing space | #3515 |
|
| tokio-rs/tracing | Add an opt-in field value truncation wrapper to the subscriber | #3600 |
|
| dtolnay/cxx | Strip r# prefix from raw identifiers in generated C++ names | #1749 |
|
| dotnet/runtime | Return empty string instead of throwing when getpwuid_r fails unexpectedly | #132396 |
|
| dotnet/msbuild | Disable nullable analysis for net4x leg of multi-targeted projects | #14738 |
|
| NLog/NLog | Change the DateLayoutRenderer default format to yyyy-MM-dd HH:mm:ss.ffff | #6252 |
|
| nsubstitute/NSubstitute | Document that Received.InOrder does not track property getters | #998 |
|
| dotnet-outdated/dotnet-outdated | Report packages whose source repository is archived or deleted | #781 |
|
| ansible/terraform-provider-aap | Remove aap_host from state on 404 during Read | #194 |
|
| HangfireIO/Hangfire | Don't disable recurring jobs on transient storage errors | #2589 |
|
| johnlokerse/awesome-azure-devops | Add trasloco to Community Tools and Extensions | #27 |
|
| martcus/awesome-azure-devops | Add trasloco to pipelines | #7 |
|
| sdras/awesome-actions | Add trasloco modernize to Linting | #991 |
|
| temporalio/temporal | Fail batch operations when Visibility queries time out repeatedly | #11753 |
|
| thanos-io/thanos | Filter: prune StoreAPI fan-out for enumerable regex name matchers | #9006 |
|
| tikv/tikv | Storage: expose scheduler write-latch memory usage | #20060 |
|
| tikv/tikv | Tikv_util: fix undefined behavior in RangeLatchGuard's Drop impl | #20022 |

