今日已更新 293 条资讯 | 累计 23876 条内容
关于我们

标签:#acti

找到 68 篇相关文章

AI 资讯

We Made Our AI-vs-Human PR Stats a Public Live Dashboard

A while back I wrote about 64% of our merged PRs being written by AI . A few people (reasonably) asked: "nice story, but can I verify any of that?" So we put it on a public, auto-updating dashboard: 👉 www.codens.ai/stats/en It shows, for our GitHub organization: What % of merged PRs are authored by AI agents (currently 65%) Median time from PR-open to merge (2 minutes) Who merged what — task-execution agents vs maintenance bots vs auto-fix vs humans Weekly AI-merge counts and a per-repository breakdown Every number is tallied straight from the GitHub API by a small collector script, and the page regenerates itself weekly. We can't inflate it — it's measured, and the down weeks show up too (that's kind of the point). Why bother making it public Two reasons. 1. "Trust me bro" doesn't scale. When you claim most of your code is AI-written, the only honest move is to expose the raw counts so anyone can sanity-check them. The dashboard is that receipt. 2. It's a live dogfooding test. The whole thing — the PRD, the implementation, the review, the auto-fix on production errors — runs on Codens , our own AI dev-automation suite. If our own numbers ever tanked, the dashboard would be the first place it'd show. Public accountability is a good forcing function. Funny footnote: the dashboard itself was code-reviewed by our own AI reviewer before it shipped, and it caught two real bugs — an OG-image percentage that had drifted out of sync with the live number, and a broken error-fallback that would have blanked the page on malformed data. The tool built to sell "AI reviews your PRs" reviewed the PR that announces it. We'll take it. If you want to see the same machinery on your repos, there's a 14-day free trial (no card): codens.ai . Japanese version of the dashboard is here .

2026-07-07 原文 →
AI 资讯

Securing Your Terraform Infrastructure with Checkov and GitHub Actions

Infrastructure as Code (IaC) has revolutionized how we provision and manage cloud resources. Tools like Terraform, Pulumi, and OpenTofu allow us to define infrastructure using code, making it versionable, repeatable, and scalable. However, with great power comes great responsibility. Misconfigurations in IaC can lead to massive security breaches, such as publicly exposed data storage or overly permissive access roles. This is where Static Application Security Testing (SAST) comes in. SAST tools analyze your source code to find security vulnerabilities before the code is deployed. In this article, we'll explore how to apply SAST to a Terraform project using Checkov , a popular open-source static analysis tool for IaC, and how to automate this process using GitHub Actions. (Note: We are intentionally avoiding tfsec for this demonstration to explore other powerful alternatives). Why Checkov? Checkov, created by Bridgecrew (now part of Prisma Cloud), is a static code analysis tool for IaC. It scans cloud infrastructure provisioned using Terraform, Terraform plan, Cloudformation, Kubernetes, Dockerfile, Serverless, or ARM Templates and detects security and compliance misconfigurations. It includes hundreds of built-in policies covering security and compliance best practices for AWS, Azure, and Google Cloud. The Demo Scenario: A Vulnerable S3 Bucket Let's start by creating a simple Terraform configuration for an AWS S3 bucket. We will intentionally introduce a security misconfiguration: making the bucket public without encryption. Create a file named main.tf : # main.tf provider "aws" { region = "us-east-1" } resource "aws_s3_bucket" "my_vulnerable_bucket" { bucket = "my-company-public-data-bucket-12345" } # Misconfiguration 1: Public Read Access resource "aws_s3_bucket_acl" "example" { bucket = aws_s3_bucket . my_vulnerable_bucket . id acl = "public-read" } If we were to deploy this, anyone on the internet could read the contents of this bucket. Let's see how Checkov can

2026-07-05 原文 →
AI 资讯

Copilot CLI drops the PAT requirement inside GitHub Actions

GitHub said this week that Copilot CLI, when it runs inside a GitHub Actions workflow, will accept the built-in GITHUB_TOKEN for authentication. Per the July 2 changelog, the previous path required creating and storing a personal access token. The operational read is small and precise: one fewer human-owned credential to mint, rotate and inherit. The exact scope of the change The changelog covers a narrow surface. It applies to Copilot CLI when invoked from a GitHub Actions workflow, and it swaps the required credential from a PAT to the workflow's ambient GITHUB_TOKEN . GitHub does not describe changes to how Copilot CLI authenticates outside Actions, and this post will not extrapolate to those contexts. If your Copilot CLI usage lives on a developer laptop or in another CI system, nothing in this announcement moves for you. Why the PAT was the wrong credential to leave in the loop A personal access token has almost none of the properties you would want from an automation credential. It does not expire on a job boundary. It carries a person's identity, not the workflow's. It sits in Actions secrets long enough to outlive the engineer who created it. And its scopes were chosen by that engineer, at that moment, often wider than the job actually needs. GITHUB_TOKEN is the opposite shape. Actions mints it at the start of a job, scopes it through the workflow's permissions: block, and revokes it when the job ends. If the token leaks, the window for abuse is the runtime of the job, not the years until somebody remembers to rotate it. When the person who wrote the workflow leaves, the pipeline does not silently break because a token expired with their account. For scripted Copilot CLI calls that had to be wrapped in a PAT, that is the whole win. The tool authenticates against the workflow instead of against a human. Wiring it up The workflow-side pattern is the same one every GITHUB_TOKEN -consuming step already follows: declare permissions: explicitly at the job level, k

2026-07-04 原文 →
AI 资讯

The Go Code Review Comments List: 10 Rules Every Reviewer Cites

Book: The Complete Guide to Go Programming Also by me: Hexagonal Architecture in Go — the companion book in the Thinking in Go series My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub You open a pull request in a Go repo you just joined. Ten minutes later there are six comments on it. None of them are about your logic. They point at a capitalized error string, a receiver named this , a context stored on a struct. Each comment links the same page: the Go Code Review Comments wiki. That page is the closest thing Go has to an official style council. It grew out of the comments Go's own maintainers left on CLs for years, and most Go teams treat it as the default rulebook. The problem is that the wiki tells you what but rarely why , so the rules read like arbitrary taste. They aren't. Each one exists because the alternative bit somebody. Here are ten that reviewers cite the most, with the reason behind each. Everything below is idiomatic on Go 1.23+. 1. Error strings are lowercase and unpunctuated The rule: an error string should not be capitalized and should not end with punctuation. // wrong return fmt . Errorf ( "Failed to open config." ) // right return fmt . Errorf ( "failed to open config" ) The reason is wrapping. Go errors get concatenated. Your string is almost never the whole sentence a user reads; it's a fragment in a chain built with %w : return fmt . Errorf ( "load settings: %w" , err ) // -> "load settings: open config: permission denied" Capitalize your fragment and you get load settings: Open config: permission denied in the middle of a line. End it with a period and you get a period in the middle of a longer message. Lowercase, no trailing punctuation, and every fragment composes cleanly no matter where it lands in the chain. The exception is a string that begins with an exported name or acronym, which keeps its own case ( HTTP , TLS ). 2. Receiver types are consistent ac

2026-07-03 原文 →
AI 资讯

Go Naming: Why Getters Drop the Get Prefix (and Other Idioms)

Book: The Complete Guide to Go Programming Also by me: Hexagonal Architecture in Go — the companion book in the Thinking in Go series My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub You write a Go struct with a private field and a method to read it. Muscle memory from Java, C#, or PHP takes over, and you type GetName() . The code compiles. Tests pass. Then a reviewer leaves a comment that just says "drop the Get" with no explanation, and you're left wondering whether that's a real rule or one person's taste. It's a real rule. It's written into the language's own style guide, the standard library follows it everywhere, and several linters will flag the code that breaks it. Go naming isn't a matter of opinion the way it is in some languages. A handful of conventions are baked into the tooling, and once you know them, half the reviewer nitpicks disappear. Getters drop the Get The convention comes straight from the Effective Go document. If you have an unexported field owner , the accessor is named Owner , not GetName or GetOwner . The mutator, if you need one, keeps the Set prefix. type File struct { owner string } func ( f * File ) Owner () string { return f . owner } func ( f * File ) SetOwner ( o string ) { f . owner = o } The reasoning is about how the call reads. person.Name() says the same thing as GetName() with less noise, and the parentheses already tell you it's a method call. Get adds a word that carries no information in a language where field access and method calls look different anyway. The Set prefix stays because there's no other clean way to signal mutation. Name() reads, SetName(x) writes. The asymmetry is deliberate. This shows up all over the standard library. bytes.Buffer has Len() , not GetLen() . sync.Once has no getters to get wrong, but http.Request exposes fields and methods that never carry a Get . time.Time has Hour() , Minute() , Second() . The pattern is

2026-07-03 原文 →
AI 资讯

glasp v0.3.0 & v0.4.0 — PKCE Support, Timeouts, and Retries

Last time I wrote about using glasp, a Go-based, npm-free CLI for Google Apps Script (GAS), in GitHub Actions. Previous post: Lean, Fast, Simple — npm-free GAS Deployment on GitHub Actions with glasp This time, a quick rundown of what landed in v0.3.0 and v0.4.0 . v0.3.0: PKCE support glasp login now supports PKCE (RFC 7636) as an opt-in. glasp login --pkce # or GLASP_USE_PKCE = 1 glasp login Each login generates a code_verifier and sends an S256 code_challenge to Google. It's a defense against authorization code interception, and it coexists fine with the existing client_secret flow. It only applies to the interactive login — --auth / GLASP_AUTH for CI is untouched. Off by default. Worth turning on if you're in a stricter security environment. v0.4.0: Timeouts and retries The focus here is basically "can this run unattended in CI/CD without falling over." Timeouts Script API requests previously had no timeout — a stuck request could hang the job indefinitely. v0.4.0 adds a 180s default. glasp push --timeout 60 # set to 60s glasp push --no-timeout # disable Also configurable via GLASP_TIMEOUT / GLASP_NO_TIMEOUT env vars or timeoutSeconds in .glasp/config.json . Priority: --no-timeout > flag/env > config > default. If the config file is broken, it warns instead of silently falling back. Retries Transient failures (5xx, 429) now get retried automatically. glasp push --max-retries 5 glasp push --no-retries 3 retries by default (up to 4 attempts total) Only applies to idempotent commands: push , pull , clone , list-deployments Commands with side effects ( create-script , run-function , etc.) are never retried Exponential backoff with jitter, respecting Retry-After It's implemented as a single http.RoundTripper wrapper, so the Google SDK itself isn't touched — same pattern as the timeout implementation. retryTransport → oauth2.Transport → http.DefaultTransport Some refactoring, too Internal packages got reorganized ( #107 ), and the hand-rolled retry transport was swappe

2026-07-02 原文 →
AI 资讯

The GitHub Actions workflow that's been failing for weeks (and how to find yours)

trpc has a scheduled workflow called "Lock Issues & PRs." Its own scorecard shows it failing on almost every run. It is still scheduled, still running, still red. trpc ships excellent software, which is exactly the point: if a project this careful has a workflow that has been red for ages, the rest of us almost certainly do too. It is not a one-off. drizzle-orm has one ("Unpublish release"). cal.com has one ("PR Update"). I scanned 35 popular open-source repos and the same thing kept turning up: a scheduled workflow that fails on nearly every run, quietly, for a long time. Why nobody notices GitHub does email you when a scheduled workflow fails. So how do these survive? Two reasons. First, those emails are routine. You get them for flaky reruns and transient blips too, so you filter them out. Second, a workflow that is always red stops reading as a signal. It is just how that row looks now. I did exactly this on my own project. GitHub emailed me that a workflow had failed. The next day it emailed again. I saw it, told myself I would fix it tomorrow, and promptly forgot. It was my nightly database backup, quietly broken the whole time, and I only caught it when a failure-rate number crept up where I would notice. An always-red workflow is not free It burns minutes every run to produce nothing but a red X. Worse, it trains you to ignore the failure that actually matters: the day a real one lands in the same inbox you have learned to skim past. How to find yours Open your Actions tab and look at the scheduled workflows, the cron-triggered ones nobody watches. If the last several runs are all red, you found one. From the CLI: gh run list --workflow = "Lock Issues & PRs" --status = failure What to do about it Two honest options: fix it, or if the workflow is genuinely abandoned, turn it off. Do not leave it scheduled and red. gh workflow disable "Lock Issues & PRs" Or drop the schedule trigger from the workflow file if it should not run on a timer at all. A disabled work

2026-06-30 原文 →
AI 资讯

Why your GitHub Actions CI is slow (and how to speed it up)

Two days ago GitHub emailed me to say one of my workflows had failed. The next day it emailed me again. I saw it, told myself I would fix it tomorrow, and promptly forgot. It was my nightly database backup, quietly broken the whole time, and I only caught it because a failure-rate number nudged up. A failed run at least gets you an email. A slow run gets you nothing. GitHub never pings you when CI quietly takes twice as long, runs the whole suite twice per PR, or rebuilds dependencies from scratch every time. That waste compounds where no one looks. Here are the usual culprits, each with the exact fix. When I scanned 35 popular open-source repos, not one had a fully clean config. 32 of 35 had no concurrency control, 33 of 35 had no job timeouts, and 22 of 35 ran the full suite twice on every PR. If projects this polished leave minutes on the table, the rest of us definitely do. Your suite runs twice on every PR Trigger a workflow on both push and pull_request and, for a branch in the same repo, opening a PR fires both. You just paid for two identical runs. This one is pure waste and it can roughly halve your PR-related minutes. Trigger on pull_request , and keep push for your default branch: on : push : branches : [ main ] pull_request : Old runs don't cancel when you push again Push a fix 30 seconds after the first push and, with no concurrency group, both runs go to completion. The first is dead weight, and it is holding a slot in your queue while it finishes. This hides even when you do have a group: astro has a concurrency group on one workflow but left off cancel-in-progress , which our scan estimates leaves roughly 1,850 minutes a month on the table. Add a group keyed on the branch, with cancel-in-progress , so a new push supersedes the old run: concurrency : group : ${{ github.workflow }}-${{ github.ref }} cancel-in-progress : true Every run reinstalls dependencies from scratch No cache means every run re-downloads and rebuilds your dependencies. On a typical

2026-06-30 原文 →
AI 资讯

Prioritizing Abstractions Over Complexity: Addressing Illusions in Distributed Systems Platform Design

Introduction In the world of distributed systems, complexity is the beast we’re all trying to tame. Teams building platforms often fall into the trap of believing that hiding this complexity is the ultimate goal. The logic seems sound: if users don’t see the mess, they won’t be burdened by it. But this approach, while well-intentioned, often leads to the creation of illusions —systems that appear simple on the surface but are brittle and unpredictable beneath. These illusions don’t just fail to solve the problem; they exacerbate it, leading to increased cognitive load, unexpected failures, and long-term maintenance nightmares. Consider a platform designed to abstract away the intricacies of distributed transactions. If the abstraction merely masks the complexity without addressing its root causes—such as inconsistent network latencies or partial failures—users will eventually encounter edge cases where the system behaves unpredictably. For example, a transaction might appear to succeed but fail silently due to a race condition in the underlying distributed lock mechanism. The illusion of simplicity breaks down when the system’s internal state deforms under pressure, leading to data inconsistencies or service outages. The core issue lies in the misunderstanding of abstractions . A meaningful abstraction doesn’t just hide complexity; it transforms it into a more manageable form. It exposes the essential properties of the system while encapsulating the non-essential details. In contrast, an illusion merely obscures the complexity, leaving it to fester beneath the surface. For instance, an abstraction might provide a consistent API for distributed state management, while internally handling retries, idempotency, and conflict resolution. An illusion, on the other hand, might simply wrap a flaky distributed database in a prettier interface, without addressing the underlying issues of consistency or availability. The pressure to deliver platforms quickly often exacerbates

2026-06-30 原文 →
AI 资讯

A homemade CI/CD pipeline with GitHub Actions

In the previous article on hosting a Next.js app on a VPS , I'd left the deployment pipeline as a rough sketch: four lines to say "it ships to production on its own when you push." That's the piece I want to open up here, because it's what separates a VPS you fuss over by hand from infrastructure you can forget about. There's a stubborn myth that CI/CD is a big-company thing, with a dedicated DevOps team and six-figure tooling. Not true. The pipeline that deploys this portfolio fits in two YAML files, you can read it in five minutes, and it gives me back exactly the comfort I liked about Vercel: I push to master , I go grab a coffee, the app is live when I'm back. The one thing I gained along the way is knowing precisely what happens between the git push and the running container. Four steps, in this order Deployment is a chain. On every push to master , GitHub Actions runs lint, security scan, image build, and deploy. What matters is the needs : as long as a step fails, the following ones don't start. A critical vulnerability caught by the scan, and the image never gets built. At all. jobs : lint : # ESLint runs-on : ubuntu-latest # ... security : # Trivy scan (reusable workflow) uses : ./.github/workflows/security.yml build-push : # build the Docker image → push to GHCR needs : [ lint , security ] # ... deploy : # SSH to the VPS → docker compose pull && up -d needs : [ build-push ] # ... Lint first, because it's the cheapest step and there's no point building an image if ESLint is already screaming. The scan next, as a barrier. Then the build, which produces the Docker image and pushes it to GHCR, GitHub's container registry (private, in my case). And finally the deploy, which connects over SSH to the VPS, pulls the new image and restarts the container. Four links, each blocking the next. That's the whole secret. The security scan is in the path, not in a review "for later" This is the one I won't budge on. Dependency security, in a lot of projects, is a Dependabo

2026-06-28 原文 →
AI 资讯

GitHub Actions adds a background marker, and the linear job stops being the only shape

A small word that changes the rhythm of a job For as long as I have been writing Actions workflows I have been carrying a quiet workaround in my head. Want to warm a cache while the build runs? Append & to the shell command, then squint at logs that arrive out of order and pray the job doesn't exit on you. It worked, sort of. It also meant that anything more interesting than "run one thing, then the next thing" lived as folklore, hidden inside run: blocks. GitHub closed that gap this week. On June 25 the Actions changelog announced that steps inside a job can now run concurrently, marked with a new background keyword and supported by helpers to wait for them and cancel them. Until now, the changelog notes, every step in a workflow ran in sequence, with each step starting only after the previous one completed. That single rule has shaped every workflow I have ever written. It is gone, and the replacement is the kind of feature you don't notice until the day you reach for it and it's there. What the keywords actually do There are four pieces, all of them documented in the announcement. background: true is the entry point. Set it on a step and that step starts running, and the next step starts immediately. It does not block the job. wait and wait-all are the rendezvous. wait pins on one or more named background steps and pauses until they finish. wait-all is the same idea against every background step still in flight. Either way you get back into a linear flow on your terms. cancel is the cleanup. It gracefully terminates a background step when you no longer need it, which is the missing piece if you have ever tried to kill a long-running side process from inside a job and ended up shelling out to kill . parallel is the convenience wrapper. The changelog describes it as taking a group of steps and converting them into background steps with a wait placed after. For the common "fan out, then join" shape, you write one block instead of decorating five steps by hand. Where

2026-06-26 原文 →
开发者

PaperQuire Render Action — PDFs in Your CI Pipeline

Your docs should build themselves You write your documentation in Markdown. You keep it in a Git repo. Every time someone updates a spec or runbook, someone else has to open PaperQuire (or the CLI), render the PDF, and upload it somewhere. That manual step is now gone. The PaperQuire Render Action generates branded, print-ready PDFs directly in your GitHub Actions workflow — on every push, every PR, or every release. One step. That's it. - uses : paperquire/render-action@v1 with : files : ' docs/*.md' template : executive-report output : build/pdfs Every Markdown file matching the glob is rendered to PDF using the same Chromium engine as the desktop app. Same templates, same quality, no Pandoc or LaTeX to install. What you can build Auto-generate docs on push Whenever someone pushes to docs/ , produce fresh PDFs and attach them as build artifacts: name : Generate PDFs on : push : paths : - ' docs/**/*.md' jobs : render : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 - uses : paperquire/render-action@v1 with : files : ' docs/*.md' template : minimal-clean output : build/pdfs - uses : actions/upload-artifact@v4 with : name : pdfs path : build/pdfs/ Team members download the latest PDFs from the Actions tab. No Slack messages, no "can you re-export this?" Attach PDFs to releases Ship documentation alongside your code: - uses : paperquire/render-action@v1 with : files : ' docs/*.md' template : executive-report output : dist/ - name : Upload to release env : GH_TOKEN : ${{ github.token }} run : gh release upload ${{ github.event.release.tag_name }} dist/*.pdf Every release automatically includes the latest versions of your specs, guides, and reports. PR previews Use the action in pull request workflows so reviewers can download rendered PDFs before merging: on : pull_request : paths : [ ' docs/**' ] jobs : preview : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 - uses : paperquire/render-action@v1 with : files : ' docs/*.md' output : preview

2026-06-26 原文 →
AI 资讯

Your @EventListener Fires Before the Transaction Commits⚙️

Your domain event fires. Your notification service queries the DB for the entity that just got saved. It finds nothing. You add a log line. It starts working. You remove the log. It breaks again. That's not a race condition. That's @EventListener . What's actually happening Spring's @EventListener fires synchronously, inside the calling thread, before the transaction commits. The DB row exists in Hibernate's session — but it hasn't been flushed and committed yet. Other connections, including the one your listener opens when it calls findById , can't see it. The log statement "fixes" it because the delay gives Hibernate time to flush. Remove the log, the flush doesn't happen in time, and you're back to an empty Optional . Here's the broken setup: @Component public class OrderEventListener { @EventListener // fires MID-TRANSACTION, before commit public void onOrderCreated ( OrderCreatedEvent event ) { // Transaction not committed yet. // Other DB connections see nothing. Order order = orderRepository . findById ( event . getOrderId ()) . orElseThrow (); // ← throws here, row doesn't exist yet notificationService . notifyCustomer ( order ); } } The obvious fix and what it costs you Spring ships @TransactionalEventListener for exactly this. Set phase = TransactionPhase.AFTER_COMMIT and the listener fires after the transaction commits. The row is visible. findById returns the order. Problem solved. @Component public class OrderEventListener { @TransactionalEventListener ( phase = TransactionPhase . AFTER_COMMIT ) public void onOrderCreated ( OrderCreatedEvent event ) { // Transaction committed. All connections see the row. Order order = orderRepository . findById ( event . getOrderId ()) . orElseThrow (); // ← works fine notificationService . notifyCustomer ( order ); } } But the trade-off is real. Your listener is now decoupled from the transaction. If the listener fails — notification service is down, the email throws, the external API times out — the transaction alrea

2026-06-25 原文 →