惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
美团技术团队
H
Hacker News: Front Page
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
Simon Willison's Weblog
Simon Willison's Weblog
T
The Exploit Database - CXSecurity.com
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
C
CXSECURITY Database RSS Feed - CXSecurity.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
A
About on SuperTechFans
F
Fortinet All Blogs
量子位
GbyAI
GbyAI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Hacker News
The Hacker News
AWS News Blog
AWS News Blog
Forbes - Security
Forbes - Security
Help Net Security
Help Net Security
I
InfoQ
有赞技术团队
有赞技术团队
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
C
Check Point Blog
T
Troy Hunt's Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Latest news
Latest news
P
Proofpoint News Feed
Jina AI
Jina AI
Last Week in AI
Last Week in AI
Martin Fowler
Martin Fowler
雷峰网
雷峰网
博客园 - Franky
L
LangChain Blog
罗磊的独立博客
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
D
Docker
G
GRAHAM CLULEY
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
When GitHub Actions Goes Silent: The Pending-Forever Bug I Hit Shipping My MCP Server to npm
אחיה כהן · 2026-04-29 · via DEV Community

I have an open-source MCP server. I tag a release, push, GitHub Actions builds, npm publishes, MCP Registry updates. That's the contract. It worked for v2.7.6 through v2.8.4.

Then v2.8.5 didn't publish. Neither did v2.8.6. Or v2.9.0. Or v2.9.1. Or v2.9.2. Or v2.9.3.

Six releases stuck. Not failing — stuck. Yellow dot. Forever.

Here's what was actually happening. And how I got the releases out without GitHub Actions.

The symptom that doesn't match any docs

Every release event triggered the workflow. Every workflow showed up in the runs list. None of them ever started a job.

$ gh run view 25001890100 --json status,conclusion,jobs
{
  "status": "queued",
  "conclusion": null,
  "jobs": []
}

Enter fullscreen mode Exit fullscreen mode

No conclusion. No jobs. Empty pending_deployments. Not "waiting for approval". Not "in_progress". Not "failure". Just pending with no work scheduled — for 125 hours.

If you search "GitHub Actions stuck pending", you'll find a hundred forum posts. Every answer assumes one of:

  1. You hit the runner concurrency limit (3 for free-tier macos)
  2. You have a deployment environment requiring approval
  3. Your runs-on: label is unreachable
  4. You're using self-hosted runners with no online agents

None of those applied. My workflow was simple, no environments with required reviewers, runs-on: macos-latest, no self-hosted runners.

The thing GitHub doesn't tell you in the run UI

The runs list shows pending. The run detail page shows pending. The job list shows nothing. The "deployment" tab shows nothing.

But if you look at your billing dashboard, there's a different story:

Your account has used 100% of included macOS minutes for this billing period.

That's it. That's the entire diagnostic. There is no banner on the run page. The workflow doesn't fail with a clear error. It just sits in the queue forever — because the runner that would pick it up doesn't exist, and the queue doesn't time out events.

The minutes counter resets monthly. Until it does, every release event becomes another silent pending row.

Two facts that surprised me

Fact 1: macOS runners cost 10x more than Linux runners. Both runs-on: macos-latest and runs-on: macos-13 charge against your Actions minutes at a 10x multiplier. The free 2,000 minutes/month gets you 200 minutes of macOS — about 20 release builds if each takes 10 minutes.

Fact 2: Switching to Linux didn't fix it. I changed runs-on: macos-latest to runs-on: ubuntu-latest. Same symptom. 0 jobs queued, status "pending". Why?

The macOS minutes meter is one bucket. The Linux meter is another. When the macOS bucket emptied, my pending macOS runs were still in the queue, blocking new runs. Even after switching the workflow to ubuntu, the concurrency group in the YAML serialized everything:

concurrency:
  group: publish
  cancel-in-progress: false

Enter fullscreen mode Exit fullscreen mode

So new ubuntu runs queued behind old stuck macOS runs and never started.

The two-part fix

Part 1: workflow_dispatch with tag input

Adding a manual trigger lets you re-publish a tag whose release-event run got stuck, without deleting and recreating the GitHub Release:

on:
  release:
    types: [published]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag to publish (e.g. v2.9.3)"
        required: true
        type: string

Enter fullscreen mode Exit fullscreen mode

In every step that needs the tag, fall back through both event types:

- uses: actions/checkout@v6
  with:
    ref: ${{ github.event.inputs.tag || github.ref_name }}

Enter fullscreen mode Exit fullscreen mode

That alone isn't enough — if the runner pool is still empty, the dispatched run also stalls. But it gives you a clean re-trigger path the moment runners are back.

Part 2: portable runner OS

The workflow downloaded mcp-publisher_darwin_${ARCH}.tar.gz — hardcoded "darwin". Switching to ubuntu broke that step. Generalize:

- name: Download mcp-publisher
  run: |
    OS=$(uname -s | tr '[:upper:]' '[:lower:]')
    ARCH=$(uname -m)
    if [ "$ARCH" = "x86_64" ]; then ARCH=amd64; fi
    if [ "$ARCH" = "aarch64" ]; then ARCH=arm64; fi
    curl -sL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}_${ARCH}.tar.gz" -o mcp-publisher.tar.gz
    tar -xzf mcp-publisher.tar.gz mcp-publisher

Enter fullscreen mode Exit fullscreen mode

Now the same step works on macOS-arm64, macOS-x86_64, ubuntu-x86_64, and any future runner.

The manual workaround that actually shipped the release

While the workflow stays stuck, here's how I got v2.9.3 to npm and the MCP Registry from my laptop:

npm: the easy part

git checkout v2.9.3
npm publish --provenance --access public

Enter fullscreen mode Exit fullscreen mode

--provenance requires a valid OIDC token, which only works inside GitHub Actions. Skip it locally:

npm publish --access public

Enter fullscreen mode Exit fullscreen mode

You lose the provenance attestation, but the package ships. Provenance is a nice-to-have, not a publish blocker.

MCP Registry: the trickier part

The MCP Registry's CLI authenticates interactively:

mcp-publisher login github
# Opens a browser, asks you to paste a code, etc.

Enter fullscreen mode Exit fullscreen mode

That's fine for humans. For a script — or for a Claude session running headless — you need non-interactive auth. The mcp-publisher binary accepts -token:

GH_TOKEN=$(gh auth token)
mcp-publisher login github -token "$GH_TOKEN"
mcp-publisher publish

Enter fullscreen mode Exit fullscreen mode

The gh CLI you already use for everything else? Its token works as your GitHub PAT for mcp-publisher. No browser, no copy-paste.

After running these, the MCP Registry's io.github.achiya-automation/safari-mcp v2.9.3 went from "stuck on v2.7.6 for 3 weeks" to isLatest: true in about 15 seconds.

What I'd tell past-me

  1. Check the billing dashboard *first* when an Actions run sits pending with no error. The run UI does not surface "you're out of minutes". The billing page does.
  2. Don't trust runs-on: ubuntu-latest to "just be cheaper" — it is, but if you've burned your macOS minutes on stalled runs, the queue can still serialize new ones behind dead ones via your concurrency: group.
  3. Keep a manual publish path documented. Both npm and the MCP Registry have non-interactive auth options. Write the bash one-liners somewhere your future self can find them at 2am.
  4. workflow_dispatch with a tag input is cheap insurance. It costs you 6 lines of YAML and saves you from needing to delete-and-recreate GitHub Releases when the release-event run gets corrupted.

FAQ

Why didn't a timeout-minutes: rescue me?
That's a job-level timeout. It applies once a job starts. A run that never starts a job has nothing to time out.

Couldn't I have used a self-hosted runner?
Yes — and that's the right answer for high-volume projects. For an OSS hobby project, self-hosted is operationally heavier than the manual publish path.

Doesn't --provenance matter for supply-chain security?
For widely-installed packages, yes. For an OSS project's own emergency-publish workaround, the trade-off is "ship the release without provenance" vs "ship nothing". Pick the first one and re-publish with provenance on the next clean release.

Could I have known about the billing limit before hitting it?
GitHub does send an email when you cross 75% of your minutes. The email goes to the address on your billing account, which may not be the address you watch. Worth setting up a filter.

What about Actions minutes for OSS public repos?
GitHub gives unlimited minutes to public repos using GitHub-hosted runners — but that's only for repos owned by organizations on the Free plan, with the runner type matching the included unlimited tier. For personal accounts and certain runner combinations, the standard quota applies. Check the actual numbers under Settings → Billing → Plans for your specific account type.


If you've hit a similar stuck-pending pattern with no error in the run UI — that's the bug. Check your minutes. Then ship from your laptop.

The repo (with the workflow that handles all this now) is safari-mcp on GitHub.