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
AI 资讯
Three post-deploy checks I run after every Cloudflare Pages build
After spending two weeks debugging issues that only showed up in production — a sitemap _redirects rule that was blocking my own sitemap-index.xml and a Bluesky image upload race against Cloudflare Pages deploy lag — I added three post-deploy checks to my workflow. They're fast and specific to the failure modes I've actually hit, not a full end-to-end test suite. Three sites (aiappdex.com, findindiegame.com, ossfind.com) on Cloudflare Pages with Astro 5 SSG. Here's what I check. Check 1: Sitemap reachability The simplest check and the one I should have had from day one. After a Cloudflare Pages deploy, I verify that sitemap-index.xml is reachable and returning 200 on all three domains: for domain in aiappdex.com findindiegame.com ossfind.com ; do status = $( curl -s -o /dev/null -w "%{http_code}" "https:// $domain /sitemap-index.xml" ) echo " $domain /sitemap-index.xml → $status " if [ " $status " != "200" ] ; then echo "FAIL: $domain sitemap unreachable" fi done I also check sitemap-0.xml — the actual URL sub-sitemap that @astrojs/sitemap generates — and assert that it contains at least a minimum expected URL count. For aiappdex.com that threshold is 1,000; if it drops below that after a deploy, the ETL data pipeline probably broke silently. The reason this check exists: I had a _redirects rule rewriting sitemap-index.xml → sitemap-0.xml as an emergency workaround that turned out to be wrong. It was live for five days before I found it. The rule was blocking the real sitemap-index.xml from reaching crawlers while appearing fine in the browser (which followed the redirect). Curl with -o /dev/null -w "%{http_code}" doesn't follow redirects by default, so it would have caught this immediately. Check 2: IndexNow batch submission After every successful sitemap check, I run node scripts/indexnow.mjs . The script reads the live sitemap XML from each domain, collects all URLs, and POSTs them to the IndexNow endpoint for Bing, Yandex, Naver, and Seznam using site-specific k
AI 资讯
Three post-deploy checks I run after every Cloudflare Pages build
After spending two weeks debugging issues that only showed up in production — a sitemap _redirects rule that was blocking my own sitemap-index.xml and a Bluesky image upload race against Cloudflare Pages deploy lag — I added three post-deploy checks to my workflow. They're fast and specific to the failure modes I've actually hit, not a full end-to-end test suite. Three sites (aiappdex.com, findindiegame.com, ossfind.com) on Cloudflare Pages with Astro 5 SSG. Here's what I check. Check 1: Sitemap reachability The simplest check and the one I should have had from day one. After a Cloudflare Pages deploy, I verify that sitemap-index.xml is reachable and returning 200 on all three domains: for domain in aiappdex.com findindiegame.com ossfind.com ; do status = $( curl -s -o /dev/null -w "%{http_code}" "https:// $domain /sitemap-index.xml" ) echo " $domain /sitemap-index.xml → $status " if [ " $status " != "200" ] ; then echo "FAIL: $domain sitemap unreachable" fi done I also check sitemap-0.xml — the actual URL sub-sitemap that @astrojs/sitemap generates — and assert that it contains at least a minimum expected URL count. For aiappdex.com that threshold is 1,000; if it drops below that after a deploy, the ETL data pipeline probably broke silently. The reason this check exists: I had a _redirects rule rewriting sitemap-index.xml → sitemap-0.xml as an emergency workaround that turned out to be wrong. It was live for five days before I found it. The rule was blocking the real sitemap-index.xml from reaching crawlers while appearing fine in the browser (which followed the redirect). Curl with -o /dev/null -w "%{http_code}" doesn't follow redirects by default, so it would have caught this immediately. Check 2: IndexNow batch submission After every successful sitemap check, I run node scripts/indexnow.mjs . The script reads the live sitemap XML from each domain, collects all URLs, and POSTs them to the IndexNow endpoint for Bing, Yandex, Naver, and Seznam using site-specific k
AI 资讯
Comment orchestrer un double déploiement automatique sur Vercel & GitHub Pages avec GitHub Actions
Introduction Dans le cadre de mon apprentissage des pratiques DevOps modernes, j’ai conçu et implémenté un pipeline CI/CD (Continuous Integration / Continuous Deployment) capable de déployer automatiquement une application web frontend sur deux environnements de production distincts : Vercel et GitHub Pages . Cette mission constitue une application concrète des concepts fondamentaux du DevOps, notamment l’automatisation des processus, la réduction des interventions manuelles et la mise en place d’une chaîne de livraison logicielle fiable et reproductible. Tableau comparatif des plateformes Dans ce projet, le déploiement sur les deux plateformes n’est pas un doublon mais une démarche pédagogique et technique délibérée permettant de tester la flexibilité de l'orchestrateur. Voici comment elles se comparent : Critère GitHub Pages Vercel Hébergement Statique uniquement Statique + SSR + Serverless Domaine gratuit username.github.io projet.vercel.app CI/CD intégré Via GitHub Actions Natif + GitHub Actions Performance Bonne Excellente (Edge Network) Previews PR Non Oui (automatique) Gratuit Oui (illimité) Oui (avec limites) Cas d’usage Portfolios, docs Apps React/Next.js, SaaS ⚠️ Le problème du double déploiement : Laisser Vercel en mode automatique génère un conflit critique avec GitHub Actions. Pour éviter que deux builds s'exécutent en parallèle, j'ai désactivé le déploiement natif de Vercel en ajoutant un fichier vercel.json à la racine contenant "git": { "deploymentEnabled": false } . Le pipeline complet — deploy.yml Voici le code source du fichier de configuration de l'orchestrateur GitHub Actions ( .github/workflows/deploy.yml ). Ce script gère séquentiellement l'installation, le build et la publication vers nos deux cibles : name : CI/CD -- Deploy to Vercel & GitHub Pages # Declenchement : uniquement sur push vers main on : push : branches : - main jobs : build-and-deploy : runs-on : ubuntu-latest permissions : contents : write steps : # Etape 1 : Recuperer le code
AI 资讯
Building a Kaggle Competition Notification Bot
I built a tool called "kaggle-dingdong" that automatically fetches Kaggle competition information and sends notifications to Email, Slack, and Discord. It runs daily on a schedule via GitHub Actions, and you get notified whenever a new competition is published. https://github.com/asherish/kaggle-dingdong Why I Built This Checking the Kaggle competitions page every day is tedious. Featured competitions in particular have entry deadlines, so missing them means losing the opportunity. While RSS feeds and official notification features exist, I wanted notifications delivered directly to the channels I actually use (Discord and Slack), so I built my own. Tech Stack Python 3.13 uv — Package manager and build tool (by Astral) Kaggle Python SDK v2.0.0 — Fetching competition info GitHub Actions — Automated daily execution at 09:00 UTC pytest — Testing Three notification channels are supported: Channel Method Format Email SMTP HTML (card layout) Slack Incoming Webhook Block Kit Discord Webhook Rich Embed Architecture GitHub Actions (cron: daily at 09:00 UTC) ↓ Fetch competition list via Kaggle API ↓ Filter by conditions in config.json ↓ Compare with sent history to extract unnotified competitions ↓ Send notifications to configured channels ↓ Update sent history (max 200 entries) The project structure is as follows: kaggle-dingdong/ ├── src/kaggle_dingdong/ │ ├── __main__.py # Entry point │ ├── config.py # Configuration loading │ ├── competitions.py # Fetch & filter competitions from Kaggle API │ ├── email_sender.py # Email notifications │ ├── slack_sender.py # Slack notifications │ ├── discord_sender.py # Discord notifications │ └── history.py # Sent history management ├── tests/ # pytest tests ├── config.json # Filter configuration └── .github/workflows/ └── notify.yml # GitHub Actions workflow Implementation Highlights Fetching and Filtering Competitions The Kaggle SDK is used to fetch the competition list. In addition to the default sort order, it also fetches with recentl
AI 资讯
Tag release pipelines without a 400-line GitHub Actions workflow
You push v1.2.3 and expect a predictable sequence: tests pass → version is resolved → GitHub Release is created . In practice, teams usually pick one of two painful options: One giant workflow — every stage in a single YAML file. It works until you need reuse, workflow_call , or different triggers per stage. workflow_run chains — workflow A triggers workflow B. Passing outputs between runs is awkward, and renaming a workflow breaks the chain silently. There is a middle path: keep small, focused stage workflows (the ones you already have), declare order and wiring in one pipeline file , and use a single orchestrator step on tag push. This tutorial uses pipeline-compose-run — available on the GitHub Marketplace — and a copy-paste example you can drop into any repo. Full example (copy .github/ ): examples/run-tag-release What we are building On git push origin v* : release.yml ← one job, one action step └─ pipeline.yml ← declares order + wiring ├─ ci.yml ├─ stage-version-sync.yml → exports version └─ stage-release-publish.yml ← receives version No generated workflow to commit. No manual workflow_run graph. Step 1 — Entry workflow Create .github/workflows/release.yml : name : Release on : push : tags : [ " v*" ] permissions : contents : write actions : write jobs : run-pipeline : runs-on : ubuntu-latest steps : - uses : actions/checkout@v6 - uses : aeswibon/pipeline-compose-run@v0.3.0 with : pipeline_file : .github/pipelines/pipeline.yml github_token : ${{ github.token }} The actions: write permission is required because the action dispatches your stage workflows via workflow_dispatch . Step 2 — Pipeline file (order only) Create .github/pipelines/pipeline.yml : name : pipeline version : 1 stages : - id : ci workflow : .github/workflows/ci.yml - id : version-sync workflow : .github/workflows/stage-version-sync.yml needs : - ci outputs : - version - id : release-publish workflow : .github/workflows/stage-release-publish.yml needs : - version-sync inputs : version : ${{ co
AI 资讯
agentic workflows are being domesticated by actions
GitHub's Agentic Workflows preview has the kind of headline that makes people reach for the wrong conclusion. Natural language Markdown can turn into GitHub Actions workflows. That sounds like "the YAML is going away." I do not think that is the interesting story. The interesting story is that the agent is not escaping the workflow engine. It is being pulled into it. That matters because a lot of agent demos still pretend the future is a smart process floating above the boring machinery: the agent understands the request, edits the repo, runs some commands, and hands back a neat result. Nice demo. Very clean. Production engineering is not clean like that. Production engineering has permissions, logs, runner groups, approval rules, secrets, firewalls, budgets, weird old repositories, compliance questions, and someone who has to explain what happened when the helpful automation did something surprising. So the shape of Agentic Workflows is useful precisely because it is less magical than the demo version. GitHub is putting agents inside the same CI/CD world that already carries a lot of organizational trust. That is the right direction. markdown is not the control plane The cute part is that a developer can describe a workflow in Markdown and have GitHub turn that into standard Actions YAML. That is useful. YAML is not a personality test, and most teams have better things to do than memorize every Actions syntax edge case. But Markdown is only the input surface. The control plane is still Actions. That distinction matters. If the generated workflow is a normal Actions workflow, then all the existing machinery can still matter: repository permissions, runner selection, logs, environments, approvals, branch protection, organization policy, and whatever security controls the company already built around CI. This is where I get more optimistic about agentic tooling. The bad version of agents asks every organization to trust a new, parallel execution model because the mode
AI 资讯
Your branch protection is quietly turning away first-time contributors
Ten weeks ago I did the thing every "grow your open source project" guide tells you to do. I carved a few small, self-contained tasks out of my backlog, labeled them good first issue , wrote crisp descriptions, and waited for contributors to roll in. They didn't roll in. The issues just sat there. This morning, one of them finally got picked up. A first-time contributor opened a clean PR against my MCP server: a smoke-test suite, no new dependencies, green across the whole Node CI matrix. Exactly the contribution the label was advertising for. And then my own repository spent the next twenty minutes trying to stop it from getting merged. Not with anything dramatic. With three quiet, individually-reasonable "best practice" gates that, stacked together, form a gauntlet aimed squarely at the one person you spent ten weeks trying to attract. I want to walk through each gate, because almost everything written about contributors is about attracting them, and almost nothing is about the last hundred feet — the silent friction between a willing PR and a merged commit. The advice is only half the story "Add good first issues and contributors will come" is true in the same way "build it and they will come" is true: technically, eventually, for a small subset, with survivorship bias baked in. My good first issue opened on March 31. The PR that closed it merged on June 8. That's sixty-nine days of a clearly-labeled, beginner-friendly task sitting untouched. I'm not complaining about the wait — that part is normal. I'm pointing out that the advice stops exactly where the interesting problem starts. Because the bottleneck was never finding someone willing. When someone willing finally showed up, the friction was entirely on my side of the fence. Gate 1: the CI that silently refuses to run GitHub Actions does not run workflows on pull requests from first-time contributors until a maintainer approves the run. This is a sane anti-abuse measure — fork PRs can run arbitrary code in yo
AI 资讯
What a policy gate catches in AI-generated code, and what slips through
I maintain an open-source GitHub Action called vorsken. It does one thing: scan the diff on a pull request with Semgrep, apply a fixed policy, and return BLOCK, FLAG, or PASS. No dashboard, no model that drifts over time. Rules at ERROR/HIGH/CRITICAL severity block the merge, WARNING/MEDIUM flag it, the rest pass. Same diff, same verdict. The usual pitch for a tool like this is that it catches the SQL injection your AI assistant wrote. I wanted to see what it actually catches against real assistant output, so I generated 28 functions and ran them through. The test Seven backend tasks: a FastAPI upload endpoint, a URL-fetch helper, JWT auth, a SQL filter, an ImageMagick subprocess call, a LangChain file agent, and a LangChain RAG pipeline. I generated each one four times, with ChatGPT (GPT-5.5 Instant), Claude Code (Opus 4.8), Claude Code plus the security-guidance plugin, and Cursor (Composer 2.5). Single-shot, neutral prompt, no security hints. Then I scanned all 28 with the same ruleset. I'm reporting which rule fired on which file, not whether some model thinks the code is safe. That part you can reproduce. Task ChatGPT Claude Code + plugin Cursor Verdict file upload — — — — PASS url fetch (SSRF) ssrf ssrf ssrf — FLAG / Cursor PASS jwt auth api8 api8 — — BLOCK / 2 PASS sql filter — — — — PASS imagemagick — — — — PASS fs agent — overperm — — 1 BLOCK / 3 PASS rag dangerous dangerous dangerous dangerous BLOCK 7 BLOCK, 3 FLAG, 18 PASS across 28 functions. The basics were fine SQL filter, ImageMagick, file upload: clean on every tool. The SQL was parameterized, the subprocess calls passed argument lists instead of shell strings, the uploads weren't doing anything reckless. If you still expect current models to spray SQL injection across a straightforward CRUD task, they don't. On conventional work they get it right. Two of the flags are soft. The JWT api8 hits landed on a SECRET_KEY = "CHANGE_ME" placeholder, which you can read as a false positive or as a gate doing i
AI 资讯
Spent hours trying to auto-post from Hashnode to Dev.to. RSS? Blocked. GraphQL API? Now paid. Proxy services? Also blocked. I documented every dead end + the fix that actually works by building a GitHub Actions workflow that syncs Hashnode to Dev.to
How to Auto-Sync Your Hashnode Blog to Dev.to Using GitHub Actions (2026 Guide) FOLASAYO SAMUEL OLAYEMI FOLASAYO SAMUEL OLAYEMI FOLASAYO SAMUEL OLAYEMI Follow Jun 7 How to Auto-Sync Your Hashnode Blog to Dev.to Using GitHub Actions (2026 Guide) # discuss # automation # tutorial # devops 5 reactions Comments Add Comment 5 min read
AI 资讯
You're Not Doing GitOps (You're Doing CI/CD With Extra Steps)
The Uncomfortable Truth Here's a test: when your deployment fails in production, what happens to your main branch? If the answer is "the broken code is already merged" — congratulations, you're doing CI/CD with a Git trigger. That's not GitOps. It's a pipeline that happens to watch a branch. I've spent years building platform engineering systems at enterprise scale — identity management frameworks, infrastructure-as-code pipelines, AI agent platforms that manage operational code. And I keep seeing the same mistake: teams adopt "GitOps" by adding a deployment step after merge, then wonder why they get drift. True GitOps has one non-negotiable rule: main always equals production. If a deployment fails, main doesn't change. Period. This isn't just my opinion — it's the logical extension of OpenGitOps principles : declarative desired state, versioned in Git, automatically reconciled. The enforcement mechanism I'm describing is how you make those principles real rather than aspirational. The Anti-Pattern Everyone Runs The most common "GitOps" setup I see in enterprise teams looks like this: Developer opens PR CI runs tests Reviewer approves PR merges to main Deployment triggers from main ❌ Deployment fails main now contains code that isn't in production This is merge-then-deploy . It's standard CI/CD with extra steps. The moment you merge before confirming a successful deployment, you've broken the core GitOps contract: Git as the single source of truth for what's actually running. The result? Drift. Stale state in main . A branch that lies about what's deployed. Every subsequent PR is now based on a broken foundation. The Enforcement Pattern: Deploy Before Merge The fix isn't philosophical — it's mechanical. GitHub's Merge Queue gives you exactly the right primitive: Developer opens PR CI runs tests (standard checks) Reviewer approves → PR enters the merge queue Merge queue trigger runs a dry-run deployment against the target environment If dry-run passes → queue trigge
AI 资讯
CHANGELOG.md is for Both Humans and AI Now, So Let’s Automate It
Hoi hoi! I’m @nyaomaru, a frontend engineer who recently discovered the deliciousness of a cheese...
AI 资讯
Running Claude in CI: A GitHub Actions + Claude Code SDK Auto-PR-Reviewer That Costs $0.03 per Review
⚠️ この記事はアフィリエイト広告(プロモーション)を含みます。リンク先で発生した収益の一部が運営者に支払われますが、読者の購入価格には一切影響ありません。 By the end of this article you will have a GitHub Actions workflow that, on every pull_request , runs the Claude Code SDK headlessly, reads only the diff, and posts inline review comments via the GitHub API. I'll show the exact YAML and Python that run in my own repos, the token math that keeps each review at roughly $0.03, and the three failures that cost me a weekend before it worked. Why I stopped piping the full repo into Claude on GitHub Actions My first version did the obvious thing: clone the repo, concatenate every changed file in full, and ask Claude to "review this PR." It worked on toy PRs and exploded on real ones. A 9-file refactor sent ~48,000 input tokens and the review drifted into commentary about code the PR didn't touch. The fix that changed the economics: feed Claude the unified diff with 3 lines of context , not the files. A git diff against the merge base is typically 5–15x smaller than the files it touches. On claude-haiku-4-5 , a median PR in my projects now costs about $0.028 per review (measured across 60 PRs: 4,100 input tokens + 900 output tokens average). The expensive version was hitting $0.40+ on Sonnet because file context dominated. The other lesson: the diff alone is not enough context to judge correctness, but it is enough to catch the 80% of review nits that humans waste time on — unhandled errors, missing null checks, off-by-one, leftover debug prints, secrets in code. So I scoped the prompt to exactly that, and told it to stay silent when unsure. Silence is a feature; a reviewer that comments on everything gets muted by the team within a week. The GitHub Actions workflow YAML that triggers Claude on pull_request This is the full .github/workflows/claude-review.yml . It runs on every PR, restores a uv-cached venv, and calls a Python entrypoint. Note the permissions block — without pull-requests: write the comment-posting step fails with a 403 that GitH